[cifs-protocol] FW: [REG:111061756137964] Encryption of the key for "netsh branchcache importkey and exportkey.

Christopher R. Hertel crh at ubiqx.mn.org
Fri Jun 24 18:52:00 MDT 2011


Edgar, et. al.,

I am attaching two things:
1) The key file I am trying to decrypt.

   Filename: export-key.pw-is-foo.nc

   This is the Windows-produced file that I need to decrypt.  The 
   passphrase I used to extract this file using netsh was "foo".

2) The code that I am currently using to try and decrypt the extracted 
   key.

   Filename: oSSL_key_dx.c

   This is the OpenSSL-based decryption code I have written.  It's
   fairly brute-force.

   I have added several comments to indicate where it is I am having
   trouble.

Send questions and suggestions.  I will try whatever you suggest when I 
return home after the MS Plugfest.

Thanks.

Chris -)-----
-------------- next part --------------
A non-text attachment was scrubbed...
Name: export-key.pw-is-foo.nc
Type: application/x-netcdf
Size: 80 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/cifs-protocol/attachments/20110624/d6176d93/attachment.nc>
-------------- next part --------------
/* ========================================================================== **
 *                                oSSL_key_dx.c
 *
 * $Id$
 *
 * -------------------------------------------------------------------------- **
 *
 * Description:
 *  Decrypt an exported BranchCache Server Secret key.
 *
 * -------------------------------------------------------------------------- **
 *
 * Notes:
 *  + To compile:  cc -o oSSL_key_dx oSSL_key_dx.c -lssl
 *
 *  + These are the steps needed to extract an exported PeerDist key:
 *    1) Generate SHA256( passphrase ).
 *    2) AES Decrypt the contents of the keyfile, using SHA256( passphrase )
 *       as the key.
 *    3) Separate the first 32 bytes of the result of step 2 from the
 *       remainder.  The remainder is is the server's secret key.
 *       The first 32 bytes is the SHA256 of the key.
 *    4) Validate the key against the SHA256 of the key.
 *
 * ========================================================================== **
 */

#include <stdlib.h>       /* Standard library.  */
#include <stdio.h>        /* I/O stuff.         */
#include <errno.h>        /* For <errno>.       */
#include <string.h>       /* for strerror(3).   */
#include <stdarg.h>       /* Variable arg lists.*/

#include <openssl/aes.h>  /* OpenSSL AES tools. */
#include <openssl/sha.h>  /* OpenSSL sha tools. */


/* -------------------------------------------------------------------------- **
 * Macros:
 *
 *  Err()   - This is a conceited little macro that simply replaces
 *            fprintf( stderr, ... ) with something shorter and easier
 *            to type.
 *  Say()   - This is a conceited little macro that simply replaces
 *            printf(3) with something shorter and easier to type.
 *  ErrStr  - Shorthand for the error message associated with <errno>.
 */

#define Err( ... ) (void)fprintf( stderr, __VA_ARGS__ )
#define Say( ... ) (void)printf( __VA_ARGS__ )
#define ErrStr (strerror( errno ))


/* -------------------------------------------------------------------------- **
 * Defined constants:
 */

#define bSIZE 2048


/* -------------------------------------------------------------------------- **
 * Static Functions:
 */

void Fail( char *fmt, ... )
  /* ------------------------------------------------------------------------ **
   * Format and print a failure message on <stderr>, then exit the process.
   *
   *  Input:  fmt - Format string, as used in printf(), etc.
   *          ... - Variable parameter list.
   *
   *  Output: none
   *
   *  Notes:  Exits the process returning EXIT_FAILURE.
   *
   * ------------------------------------------------------------------------ **
   */
  {
  va_list ap;

  va_start( ap, fmt );
  (void)fprintf( stderr, "Failure: " );
  (void)vfprintf( stderr, fmt, ap );
  va_end( ap );
  exit( EXIT_FAILURE );
  } /* Fail */


static void hexlist( FILE *outF, const unsigned char *bufr, int len )
  /* ------------------------------------------------------------------------ **
   * Output a hex string representing a block of bytes.
   *
   *  Input:  outF  - Stream to which to send the output.
   *          bufr  - A pointer to a bunch of bytes.
   *          len   - Number of bytes of <bufr> to output.
   *
   *  Output: <none>
   *
   * ------------------------------------------------------------------------ **
   */
  {
  int i;

  (void)fprintf( outF, "[" );
  for( i = 0; i < len; i++ )
    {
    (void)fprintf( outF, "%.2x", bufr[i] );
    }
  (void)fprintf( outF, "]" );
  } /* hexlist */


/* -------------------------------------------------------------------------- **
 * Program Mainline.
 */

int main( int argc, char *argv[] )
  /* ------------------------------------------------------------------------ **
   * Program Mainline.
   *
   *  Input:  argc  - You know what this is.
   *          argv  - You know what to do.
   *
   *  Output: EXIT_SUCCESS
   *          or, if you are having a really bad day, EXIT_FAILURE.
   *
   * ------------------------------------------------------------------------ **
   */
  {
  int            i;
  FILE          *keyf;
  unsigned char *doublewide;
  AES_KEY        aes_ppHash[1];
  size_t         readlen;
  size_t         phraselen;
  unsigned char  inBufr[bSIZE];
  unsigned char  outBufr[bSIZE];
  unsigned char  ppHash[SHA256_DIGEST_LENGTH];
  unsigned char  iv[32];

  /* Validate the command line.  Somewhat.
   */
  if( argc != 3 )
    {
    Err( "Usage:\t%s <keyfile> <passphrase>\n", argv[0] );
    Err( "\tWhere <keyfile> is the name of the file that contains the\n" );
    Err( "\texported key, and <passphrase> is the phrase used as the\n" );
    Err( "\tencryption key when the server secret was exported.\n\tIt " );
    Err( "may be necessary to place the passphrase in quotation marks.\n" );
    exit( EXIT_FAILURE );
    }

  /* Open the keyfile.
   */
  keyf = fopen( argv[1], "r" );
  if( NULL == keyf )
    {
    Err( "Failure opening file \"%s\"; %s.\n", argv[1], ErrStr );
    return( EXIT_FAILURE );
    }

  /* Read the keyfile.
   * FIX:  This assumes that the encrypted file fits into one buffer.
   */
  readlen = fread( inBufr, 1, bSIZE, keyf );
  if( 0 == readlen )
    {
    Err( "Error reading input from %s; %s.\n", argv[1], ErrStr );
    return( EXIT_FAILURE );
    }
  Err( "Read %d bytes from file %s.\n", readlen, argv[1] );

  /* Expand and hash the passphrase.
   * NOTE: This "emulates" Windows Unicode encoding.
   */
  phraselen  = strlen( argv[2] );
  doublewide = (unsigned char *)calloc( phraselen, 1 );
  for( i = 0; i < phraselen; i++ )
    {
    doublewide[i*2] = argv[2][i];
    doublewide[1+(i*2)] = '\0';
    }
  Err( "PassPhrase: " );
  hexlist( stderr, doublewide, 2*phraselen );
  Err( "\n" );
  (void)SHA256( outBufr, (phraselen * 2), ppHash );
  free( doublewide );

  /* Initializes the AES_KEY with the key and the 256-bit size.
   * Note: 256 == key size (32 bytes) in bits.
   *       This initializes the <aes_ppHash> variable.
   */
  (void)AES_set_decrypt_key( ppHash, 256, aes_ppHash );

  /* We don't know how to handle the <iv>, so we clear it.
   * Then try to cbc decrypt the input, writing to the output.
   * Note: Yes, we call AES_cbc_encrypt() to decrypt the data.
   * FIX:  This is probabably wrong.  We never specify the CBC block size,
   *       only the key size.  The default appears to be 32 bytes, just
   *       like the key size (and the iv size).
   */
  memset( iv, 0, 32 );
  AES_cbc_encrypt( inBufr, outBufr, readlen, aes_ppHash, iv, AES_DECRYPT );

  /* Output the results.
   * 1) The decrypted key.
   * 2) The decrypted hash.
   * 3) The hash calculated from the decrypted key.
   */
  Say( "     Key: " );
  hexlist( stdout, &outBufr[32], readlen-32 );
  Say( "\n    Hash: " );
  hexlist( stdout, outBufr, 32 );
  Say( "\nKey hash: " );
  (void)SHA256( &outBufr[32], readlen-32, ppHash );
  hexlist( stdout, ppHash, 32 );
  Say( "\n" );

  return( EXIT_SUCCESS );
  } /* main */

/* ========================================================================== */


More information about the cifs-protocol mailing list