@@ -11,6 +11,14 @@ typedef struct _CryptProviderParams
1111 const DWORD flags ;
1212} CryptProviderParams ;
1313
14+ typedef struct _RsaKey
15+ {
16+ BLOBHEADER header ;
17+ DWORD length ;
18+ BYTE key [1 ];
19+ } RsaKey ;
20+
21+
1422const CryptProviderParams AesProviders [] =
1523{
1624 {MS_ENH_RSA_AES_PROV , PROV_RSA_AES , 0 },
@@ -310,25 +318,25 @@ DWORD free_encryption_context(Remote* remote)
310318 DWORD result = ERROR_SUCCESS ;
311319
312320 dprintf ("[ENC] Freeing encryption context %p" , remote -> enc_ctx );
313- if (remote -> enc_ctx != NULL );
321+ if (remote -> enc_ctx != NULL );
322+ {
323+ dprintf ("[ENC] Encryption context not null, so ditching AES key" );
324+ if (remote -> enc_ctx -> aes_key != 0 )
314325 {
315- dprintf ("[ENC] Encryption context not null, so ditching AES key" );
316- if (remote -> enc_ctx -> aes_key != 0 )
317- {
318- CryptDestroyKey (remote -> enc_ctx -> aes_key );
319- }
320-
321- dprintf ("[ENC] Encryption context not null, so ditching provider" );
322- if (remote -> enc_ctx -> provider != 0 )
323- {
324- CryptReleaseContext (remote -> enc_ctx -> provider , 0 );
325- }
326+ CryptDestroyKey (remote -> enc_ctx -> aes_key );
327+ }
326328
327- dprintf ("[ENC] Encryption context not null, so freeing the context" );
328- free (remote -> enc_ctx );
329- remote -> enc_ctx = NULL ;
329+ dprintf ("[ENC] Encryption context not null, so ditching provider" );
330+ if (remote -> enc_ctx -> provider != 0 )
331+ {
332+ CryptReleaseContext (remote -> enc_ctx -> provider , 0 );
330333 }
331- return result ;
334+
335+ dprintf ("[ENC] Encryption context not null, so freeing the context" );
336+ free (remote -> enc_ctx );
337+ remote -> enc_ctx = NULL ;
338+ }
339+ return result ;
332340}
333341
334342DWORD request_negotiate_aes_key (Remote * remote , Packet * packet )
@@ -396,14 +404,104 @@ DWORD request_negotiate_aes_key(Remote* remote, Packet* packet)
396404 break ;
397405 }
398406
399- ctx -> valid = TRUE;
400- } while ( 0 );
407+ // now we need to encrypt this key data using the public key given
408+ CHAR * pubKeyPem = packet_get_tlv_value_string ( packet , TLV_TYPE_RSA_PUB_KEY );
401409
410+ if (pubKeyPem != NULL )
411+ {
412+ DWORD binaryRequiredSize = 0 ;
413+ CryptStringToBinaryA (pubKeyPem , 0 , CRYPT_STRING_BASE64HEADER , NULL , & binaryRequiredSize , NULL , NULL );
414+ dprintf ("[ENC] Required size for the binary key is: %u (%x)" , binaryRequiredSize , binaryRequiredSize );
415+ BYTE * pubKeyBin = (BYTE * )malloc (binaryRequiredSize );
416+ if (!CryptStringToBinaryA (pubKeyPem , 0 , CRYPT_STRING_BASE64HEADER , pubKeyBin , & binaryRequiredSize , NULL , NULL ))
417+ {
418+ result = GetLastError ();
419+ dprintf ("[ENC] Failed to convert the given base64 encoded key into bytes: %u (%x)" , result , result );
420+ break ;
421+ }
402422
403- if (remote -> enc_ctx -> valid )
404- {
405- packet_add_tlv_raw (response , TLV_TYPE_AES_KEY , remote -> enc_ctx -> key_data .key , remote -> enc_ctx -> key_data .length );
406- }
423+ DWORD keyRequiredSize = 0 ;
424+ CERT_PUBLIC_KEY_INFO * pubKeyInfo = NULL ;
425+ if (!CryptDecodeObjectEx (X509_ASN_ENCODING , X509_PUBLIC_KEY_INFO , pubKeyBin , binaryRequiredSize , CRYPT_ENCODE_ALLOC_FLAG , 0 , & pubKeyInfo , & keyRequiredSize ))
426+ {
427+ result = GetLastError ();
428+ dprintf ("[ENC] Failed to decode: %u (%x)" , result , result );
429+ break ;
430+ }
431+
432+ dprintf ("[ENC] Key algo: %s" , pubKeyInfo -> Algorithm .pszObjId );
433+
434+ HCRYPTPROV rsaProv = 0 ;
435+ if (!CryptAcquireContext (& rsaProv , NULL , MS_ENHANCED_PROV , PROV_RSA_FULL , CRYPT_VERIFYCONTEXT ))
436+ {
437+ dprintf ("[ENC] Failed to create the RSA provider with CRYPT_VERIFYCONTEXT" );
438+ if (!CryptAcquireContext (& rsaProv , NULL , MS_ENHANCED_PROV , PROV_RSA_FULL , CRYPT_NEWKEYSET ))
439+ {
440+ result = GetLastError ();
441+ dprintf ("[ENC] Failed to create the RSA provider with CRYPT_NEWKEYSET: %u (%x)" , result , result );
442+ break ;
443+ }
444+ else
445+ {
446+ dprintf ("[ENC] Created the RSA provider with CRYPT_NEWKEYSET" );
447+ }
448+ }
449+ else
450+ {
451+ dprintf ("[ENC] Created the RSA provider with CRYPT_VERIFYCONTEXT" );
452+ }
453+
454+ HCRYPTKEY pubCryptKey = 0 ;
455+ if (!CryptImportPublicKeyInfo (rsaProv , X509_ASN_ENCODING , pubKeyInfo , & pubCryptKey ))
456+ {
457+ result = GetLastError ();
458+ dprintf ("[ENC] Failed to import the key: %u (%x)" , result , result );
459+ break ;
460+ }
461+
462+ DWORD requiredEncSize = remote -> enc_ctx -> key_data .length ;
463+ CryptEncrypt (pubCryptKey , 0 , TRUE, 0 , NULL , & requiredEncSize , requiredEncSize );
464+ dprintf ("[ENC] Encrypted data length: %u (%x)" , requiredEncSize , requiredEncSize );
465+
466+ LPBYTE cipherText = (LPBYTE )calloc (1 , requiredEncSize );
467+ DWORD aesKeySize = remote -> enc_ctx -> key_data .length ;
468+ memcpy_s (cipherText , requiredEncSize , remote -> enc_ctx -> key_data .key , remote -> enc_ctx -> key_data .length );
469+
470+ if (!CryptEncrypt (pubCryptKey , 0 , TRUE, 0 , cipherText , & aesKeySize , requiredEncSize ))
471+ {
472+ result = GetLastError ();
473+ dprintf ("[ENC] Failed to encrypt: %u (%x)" , result , result );
474+
475+ // encryption failed, so pass on the raw AES key instead
476+ packet_add_tlv_raw (response , TLV_TYPE_AES_KEY , remote -> enc_ctx -> key_data .key , remote -> enc_ctx -> key_data .length );
477+ }
478+ else
479+ {
480+ dprintf ("[ENC] Encryption witih RSA succeded, byteswapping because MS is stupid and does stuff in little endian." );
481+ // Given that we are encrypting such a small amount of data, we're going to assume that the size
482+ // of the key matches the size of the block of data we've decrypted.
483+ for (DWORD i = 0 ; i < requiredEncSize / 2 ; ++ i )
484+ {
485+ BYTE b = cipherText [i ];
486+ cipherText [i ] = cipherText [requiredEncSize - i - 1 ];
487+ cipherText [requiredEncSize - i - 1 ] = b ;
488+ }
489+ // encryption succeeded, pass this key back to the call in encrypted form
490+ packet_add_tlv_raw (response , TLV_TYPE_ENC_AES_KEY , cipherText , requiredEncSize );
491+ }
492+ free (cipherText );
493+ LocalFree (pubKeyInfo );
494+ CryptDestroyKey (pubCryptKey );
495+ CryptReleaseContext (rsaProv , 0 );
496+ }
497+ else
498+ {
499+ // no public key was given, so send it back in the raw
500+ packet_add_tlv_raw (response , TLV_TYPE_AES_KEY , remote -> enc_ctx -> key_data .key , remote -> enc_ctx -> key_data .length );
501+ }
502+
503+ ctx -> valid = TRUE;
504+ } while (0 );
407505
408506 packet_transmit_response (result , remote , response );
409507
0 commit comments