@@ -269,83 +269,106 @@ void aws_close_cert_store(HCERTSTORE cert_store) {
269
269
CertCloseStore (cert_store , 0 );
270
270
}
271
271
272
- static int s_cert_context_import_rsa_private_key (
272
+ enum aws_rsa_private_key_container_type {
273
+ AWS_RPKCT_PERSIST_TO_USER_PROFILE ,
274
+ AWS_RPKCT_PERSIST_TO_GLOBAL ,
275
+ AWS_RPKCT_EPHEMERAL ,
276
+ };
277
+
278
+ static int s_cert_context_import_rsa_private_key_to_key_container (
273
279
PCCERT_CONTEXT certs ,
274
280
const BYTE * key ,
275
281
DWORD decoded_len ,
276
- bool is_client_mode ,
277
282
wchar_t uuid_wstr [AWS_UUID_STR_LEN ],
283
+ enum aws_rsa_private_key_container_type key_container_type ,
278
284
HCRYPTPROV * out_crypto_provider ,
279
- HCRYPTKEY * out_private_key_handle ) {
285
+ HCRYPTKEY * out_private_key_handle ,
286
+ bool * tls13_disabled ) {
280
287
281
288
/* out-params will adopt these resources if the function is successful.
282
289
* if function fails these resources will be cleaned up before returning */
283
290
HCRYPTPROV crypto_prov = 0 ;
284
291
HCRYPTKEY h_key = 0 ;
285
292
286
- if (is_client_mode ) {
287
- /* use CRYPT_VERIFYCONTEXT so that keys are ephemeral (not stored to disk, registry, etc) */
288
- if (!CryptAcquireContextW (& crypto_prov , NULL , NULL , PROV_RSA_FULL , CRYPT_VERIFYCONTEXT )) {
289
- AWS_LOGF_ERROR (
290
- AWS_LS_IO_PKI ,
291
- "static: error creating a new rsa crypto context for key with errno %d" ,
292
- (int )GetLastError ());
293
- aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
294
- goto on_error ;
295
- }
293
+ const wchar_t * container_name = NULL ;
294
+ DWORD acquire_context_flags = 0 ;
296
295
297
- if (!CryptImportKey (crypto_prov , key , decoded_len , 0 , 0 , & h_key )) {
298
- AWS_LOGF_ERROR (
299
- AWS_LS_IO_PKI , "static: failed to import rsa key into crypto provider, error code %d" , GetLastError ());
300
- aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
301
- goto on_error ;
302
- }
296
+ switch (key_container_type ) {
297
+ case AWS_RPKCT_PERSIST_TO_USER_PROFILE :
298
+ container_name = uuid_wstr ;
299
+ acquire_context_flags = CRYPT_NEWKEYSET ;
300
+ break ;
301
+ case AWS_RPKCT_PERSIST_TO_GLOBAL :
302
+ container_name = uuid_wstr ;
303
+ acquire_context_flags = CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET ;
304
+ break ;
305
+ case AWS_RPKCT_EPHEMERAL :
306
+ break ;
307
+ }
308
+
309
+ if (!CryptAcquireContextW (& crypto_prov , container_name , NULL , PROV_RSA_FULL , acquire_context_flags )) {
310
+ AWS_LOGF_WARN (
311
+ AWS_LS_IO_PKI ,
312
+ "static: error creating a new rsa crypto context for key: key container type %d; error code %d" ,
313
+ (int )key_container_type ,
314
+ (int )GetLastError ());
315
+ aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
316
+ goto on_error ;
317
+ }
318
+
319
+ if (!CryptImportKey (crypto_prov , key , decoded_len , 0 , 0 , & h_key )) {
320
+ AWS_LOGF_ERROR (
321
+ AWS_LS_IO_PKI ,
322
+ "static: failed to import rsa key into crypto provider: key container type %d; error code %d" ,
323
+ (int )key_container_type ,
324
+ GetLastError ());
325
+ aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
326
+ goto on_error ;
327
+ }
303
328
329
+ if (key_container_type == AWS_RPKCT_EPHEMERAL ) {
304
330
if (!CertSetCertificateContextProperty (certs , CERT_KEY_PROV_HANDLE_PROP_ID , 0 , (void * )crypto_prov )) {
305
331
AWS_LOGF_ERROR (
306
332
AWS_LS_IO_PKI ,
307
- "static: error creating a new certificate context for rsa key with errno %d" ,
333
+ "static: error setting a certificate context property for rsa key: key container type %d; error code "
334
+ "%d" ,
335
+ (int )key_container_type ,
308
336
(int )GetLastError ());
309
337
aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
310
338
goto on_error ;
311
339
}
340
+ /* Secure Channel doesn't support TLS 1.3 with ephemeral keys. */
341
+ AWS_LOGF_INFO (AWS_LS_IO_PKI , "static: TLS 1.3 does not support ephemeral keys, disabling TLS 1.3" );
342
+ * tls13_disabled = true;
312
343
} else {
313
- if (!CryptAcquireContextW (& crypto_prov , uuid_wstr , NULL , PROV_RSA_FULL , CRYPT_NEWKEYSET )) {
314
- AWS_LOGF_ERROR (
315
- AWS_LS_IO_PKI , "static: error creating a new rsa crypto context with errno %d" , (int )GetLastError ());
316
- aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
317
- goto on_error ;
318
- }
319
-
320
- if (!CryptImportKey (crypto_prov , key , decoded_len , 0 , 0 , & h_key )) {
321
- AWS_LOGF_ERROR (
322
- AWS_LS_IO_PKI , "static: failed to import rsa key into crypto provider, error code %d" , GetLastError ());
323
- aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
324
- goto on_error ;
325
- }
326
-
327
344
CRYPT_KEY_PROV_INFO key_prov_info ;
328
345
AWS_ZERO_STRUCT (key_prov_info );
329
346
key_prov_info .pwszContainerName = uuid_wstr ;
330
347
key_prov_info .dwProvType = PROV_RSA_FULL ;
348
+ if (key_container_type == AWS_RPKCT_PERSIST_TO_GLOBAL ) {
349
+ key_prov_info .dwFlags = CRYPT_MACHINE_KEYSET ;
350
+ }
331
351
key_prov_info .dwKeySpec = AT_KEYEXCHANGE ;
332
352
333
353
if (!CertSetCertificateContextProperty (certs , CERT_KEY_PROV_INFO_PROP_ID , 0 , & key_prov_info )) {
334
354
AWS_LOGF_ERROR (
335
355
AWS_LS_IO_PKI ,
336
- "static: error creating a new certificate context for key with errno %d" ,
356
+ "static: error setting a certificate context property: key container type %d; error code %d" ,
357
+ (int )key_container_type ,
337
358
(int )GetLastError ());
338
359
aws_raise_error (AWS_ERROR_SYS_CALL_FAILURE );
339
360
goto on_error ;
340
361
}
341
362
}
342
363
364
+ AWS_LOGF_DEBUG (
365
+ AWS_LS_IO_PKI , "static: successfully imported rsa private key, key container type %d" , (int )key_container_type );
366
+
343
367
* out_crypto_provider = crypto_prov ;
344
368
* out_private_key_handle = h_key ;
345
369
return AWS_OP_SUCCESS ;
346
370
347
371
on_error :
348
-
349
372
if (h_key != 0 ) {
350
373
CryptDestroyKey (h_key );
351
374
}
@@ -357,6 +380,51 @@ static int s_cert_context_import_rsa_private_key(
357
380
return AWS_OP_ERR ;
358
381
}
359
382
383
+ static int s_cert_context_import_rsa_private_key (
384
+ PCCERT_CONTEXT certs ,
385
+ const BYTE * key ,
386
+ DWORD decoded_len ,
387
+ bool is_client_mode ,
388
+ wchar_t uuid_wstr [AWS_UUID_STR_LEN ],
389
+ HCRYPTPROV * out_crypto_provider ,
390
+ HCRYPTKEY * out_private_key_handle ,
391
+ bool * tls13_disabled ) {
392
+
393
+ const enum aws_rsa_private_key_container_type client_available_key_container_types [] = {
394
+ AWS_RPKCT_PERSIST_TO_USER_PROFILE ,
395
+ AWS_RPKCT_PERSIST_TO_GLOBAL ,
396
+ AWS_RPKCT_EPHEMERAL ,
397
+ };
398
+
399
+ /* NOTE We didn't verify server-side with ephemeral keys, so use only persistent key containers. */
400
+ const enum aws_rsa_private_key_container_type server_available_key_container_types [] = {
401
+ AWS_RPKCT_PERSIST_TO_USER_PROFILE ,
402
+ AWS_RPKCT_PERSIST_TO_GLOBAL ,
403
+ };
404
+
405
+ size_t key_container_types_num = is_client_mode ? AWS_ARRAY_SIZE (client_available_key_container_types )
406
+ : AWS_ARRAY_SIZE (server_available_key_container_types );
407
+ const enum aws_rsa_private_key_container_type * available_key_container_types =
408
+ is_client_mode ? client_available_key_container_types : server_available_key_container_types ;
409
+
410
+ /* Try importing into various Windows key containers until we succeed or exhaust all possible options. */
411
+ for (size_t i = 0 ; i < key_container_types_num ; ++ i ) {
412
+ if (s_cert_context_import_rsa_private_key_to_key_container (
413
+ certs ,
414
+ key ,
415
+ decoded_len ,
416
+ uuid_wstr ,
417
+ available_key_container_types [i ],
418
+ out_crypto_provider ,
419
+ out_private_key_handle ,
420
+ tls13_disabled ) == AWS_OP_SUCCESS ) {
421
+ return AWS_OP_SUCCESS ;
422
+ }
423
+ }
424
+
425
+ return AWS_OP_ERR ;
426
+ }
427
+
360
428
#define ECC_256_MAGIC_NUMBER 0x20
361
429
#define ECC_384_MAGIC_NUMBER 0x30
362
430
@@ -546,7 +614,8 @@ int aws_import_key_pair_to_cert_context(
546
614
HCERTSTORE * store ,
547
615
PCCERT_CONTEXT * certs ,
548
616
HCRYPTPROV * crypto_provider ,
549
- HCRYPTKEY * private_key_handle ) {
617
+ HCRYPTKEY * private_key_handle ,
618
+ bool * tls13_disabled ) {
550
619
551
620
struct aws_array_list certificates , private_keys ;
552
621
AWS_ZERO_STRUCT (certificates );
@@ -724,7 +793,14 @@ int aws_import_key_pair_to_cert_context(
724
793
switch (cert_type ) {
725
794
case AWS_CT_X509_RSA :
726
795
result = s_cert_context_import_rsa_private_key (
727
- * certs , key , decoded_len , is_client_mode , uuid_wstr , crypto_provider , private_key_handle );
796
+ * certs ,
797
+ key ,
798
+ decoded_len ,
799
+ is_client_mode ,
800
+ uuid_wstr ,
801
+ crypto_provider ,
802
+ private_key_handle ,
803
+ tls13_disabled );
728
804
break ;
729
805
730
806
#ifndef AWS_SUPPORT_WIN7
0 commit comments