Skip to content

Commit 3203c4c

Browse files
bretambrosealfred2gsbSteveKxiazhverasfod
authored
Tls1.3 win update (#676)
Co-authored-by: alfred2g <[email protected]> Co-authored-by: Steve Kim <[email protected]> Co-authored-by: Vera Xia <[email protected]> Co-authored-by: Igor Abdrakhimov <[email protected]>
1 parent b1774b6 commit 3203c4c

17 files changed

+1087
-162
lines changed

.builder/actions/tls_server_setup.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""
2+
Setup local TLS server for tests
3+
"""
4+
5+
import Builder
6+
7+
import os
8+
import sys
9+
import subprocess
10+
import atexit
11+
import time
12+
13+
14+
class TlsServerSetup(Builder.Action):
15+
"""
16+
Set up this machine for running the mock server test
17+
18+
This action should be run in the 'pre_build_steps' or 'build_steps' stage.
19+
"""
20+
21+
def run(self, env):
22+
if not env.project.needs_tests(env):
23+
print("Skipping TLS server setup because tests disabled for project")
24+
return
25+
26+
self.env = env
27+
28+
base_dir = os.path.dirname(os.path.realpath(__file__))
29+
dir = os.path.join(base_dir, "..", "..", "tests", "tls_server")
30+
31+
print("Running openssl TLS server")
32+
33+
python_path = sys.executable
34+
p = subprocess.Popen([python_path, "tls_server.py",
35+
], cwd=dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
36+
37+
@atexit.register
38+
def close_tls_server():
39+
print("Terminating openssl TLS server")
40+
p.terminate()
41+
out, err = p.communicate()
42+
print("TLS server stdout:\n{}".format(out))
43+
print("TLS server stderr:\n{}".format(err))

builder.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
"linux": {
1818
"_comment": "set up SoftHSM2 for PKCS#11 tests (see: ./builder/actions/pkcs11_test_setup.py)",
1919
"+pre_build_steps": ["pkcs11-test-setup"]
20+
},
21+
"windows": {
22+
"+pre_build_steps": ["tls-server-setup"]
23+
2024
}
2125
},
2226
"build_env": {

include/aws/io/private/pki_utils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ AWS_IO_API int aws_import_key_pair_to_cert_context(
113113
HCERTSTORE *cert_store,
114114
PCCERT_CONTEXT *certs,
115115
HCRYPTPROV *crypto_provider,
116-
HCRYPTKEY *private_key_handle);
116+
HCRYPTKEY *private_key_handle,
117+
bool *tls13_disabled);
117118

118119
#endif /* _WIN32 */
119120

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef AWS_IO_TLS_CHANNEL_HANDLER_PRIVATE_H
2+
#define AWS_IO_TLS_CHANNEL_HANDLER_PRIVATE_H
3+
4+
/**
5+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
6+
* SPDX-License-Identifier: Apache-2.0.
7+
*/
8+
#include <aws/io/io.h>
9+
10+
AWS_EXTERN_C_BEGIN
11+
12+
#ifdef _WIN32
13+
/**
14+
* Force to use schannel creds. Default to false.
15+
* For windows build above WINDOWS_BUILD_1809, we have deprecated CHANNEL_CREDS.
16+
* Set the value to true to force to use CHANNEL_CREDS.
17+
*/
18+
AWS_IO_API void aws_windows_force_schannel_creds(bool use_schannel_creds);
19+
#endif
20+
21+
AWS_EXTERN_C_END
22+
#endif /* AWS_IO_TLS_CHANNEL_HANDLER_PRIVATE_H */

source/windows/secure_channel_tls_handler.c

Lines changed: 496 additions & 122 deletions
Large diffs are not rendered by default.

source/windows/windows_pki_utils.c

Lines changed: 114 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -269,83 +269,106 @@ void aws_close_cert_store(HCERTSTORE cert_store) {
269269
CertCloseStore(cert_store, 0);
270270
}
271271

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(
273279
PCCERT_CONTEXT certs,
274280
const BYTE *key,
275281
DWORD decoded_len,
276-
bool is_client_mode,
277282
wchar_t uuid_wstr[AWS_UUID_STR_LEN],
283+
enum aws_rsa_private_key_container_type key_container_type,
278284
HCRYPTPROV *out_crypto_provider,
279-
HCRYPTKEY *out_private_key_handle) {
285+
HCRYPTKEY *out_private_key_handle,
286+
bool *tls13_disabled) {
280287

281288
/* out-params will adopt these resources if the function is successful.
282289
* if function fails these resources will be cleaned up before returning */
283290
HCRYPTPROV crypto_prov = 0;
284291
HCRYPTKEY h_key = 0;
285292

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;
296295

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+
}
303328

329+
if (key_container_type == AWS_RPKCT_EPHEMERAL) {
304330
if (!CertSetCertificateContextProperty(certs, CERT_KEY_PROV_HANDLE_PROP_ID, 0, (void *)crypto_prov)) {
305331
AWS_LOGF_ERROR(
306332
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,
308336
(int)GetLastError());
309337
aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
310338
goto on_error;
311339
}
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;
312343
} 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-
327344
CRYPT_KEY_PROV_INFO key_prov_info;
328345
AWS_ZERO_STRUCT(key_prov_info);
329346
key_prov_info.pwszContainerName = uuid_wstr;
330347
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+
}
331351
key_prov_info.dwKeySpec = AT_KEYEXCHANGE;
332352

333353
if (!CertSetCertificateContextProperty(certs, CERT_KEY_PROV_INFO_PROP_ID, 0, &key_prov_info)) {
334354
AWS_LOGF_ERROR(
335355
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,
337358
(int)GetLastError());
338359
aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
339360
goto on_error;
340361
}
341362
}
342363

364+
AWS_LOGF_DEBUG(
365+
AWS_LS_IO_PKI, "static: successfully imported rsa private key, key container type %d", (int)key_container_type);
366+
343367
*out_crypto_provider = crypto_prov;
344368
*out_private_key_handle = h_key;
345369
return AWS_OP_SUCCESS;
346370

347371
on_error:
348-
349372
if (h_key != 0) {
350373
CryptDestroyKey(h_key);
351374
}
@@ -357,6 +380,51 @@ static int s_cert_context_import_rsa_private_key(
357380
return AWS_OP_ERR;
358381
}
359382

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+
360428
#define ECC_256_MAGIC_NUMBER 0x20
361429
#define ECC_384_MAGIC_NUMBER 0x30
362430

@@ -546,7 +614,8 @@ int aws_import_key_pair_to_cert_context(
546614
HCERTSTORE *store,
547615
PCCERT_CONTEXT *certs,
548616
HCRYPTPROV *crypto_provider,
549-
HCRYPTKEY *private_key_handle) {
617+
HCRYPTKEY *private_key_handle,
618+
bool *tls13_disabled) {
550619

551620
struct aws_array_list certificates, private_keys;
552621
AWS_ZERO_STRUCT(certificates);
@@ -724,7 +793,14 @@ int aws_import_key_pair_to_cert_context(
724793
switch (cert_type) {
725794
case AWS_CT_X509_RSA:
726795
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);
728804
break;
729805

730806
#ifndef AWS_SUPPORT_WIN7

tests/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,18 @@ add_test_case(sock_write_cb_is_async)
8888
add_test_case(socket_validate_port)
8989

9090
if(WIN32)
91+
set(WIN_VERSION ${CMAKE_SYSTEM_VERSION})
92+
string(REPLACE "." ";" BUILD_VERSION ${CMAKE_SYSTEM_VERSION})
93+
separate_arguments(BUILD_VERSION)
94+
list(GET BUILD_VERSION 2 BUILD_V)
95+
message("Windows Version " ${CMAKE_SYSTEM_VERSION})
96+
97+
if(${BUILD_V} GREATER_EQUAL 20348)
98+
message("Building for version 22000 or higher: supporting TLS1.3")
99+
add_net_test_case(tls_client_channel_negotiation_success_mtls_tls1_3)
100+
endif()
91101
add_test_case(local_socket_pipe_connected_race)
102+
add_test_case(tls_client_channel_negotiation_success_ecc384_deprecated)
92103
endif()
93104

94105
add_test_case(channel_setup)

tests/resources/tls13_device.key

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC+g+9xsahL85TU
3+
Gtvib/yIZsTO0qNj2AorItR+nZ0M2r4X4M45NdQsUKMpkcJ6mGMmpNW28RC1+DI+
4+
VnxKAlY+Bztr1C2SMkZej3fRUMvdix1mKFWjm3M9w7YUFdasSKvAEuioL0/23agz
5+
3eGiLhN8GxZ9BhjvuRPb2BD1QNt2QeMM/dR5B05zXxvvkZ8xhXCzu601EG8/2cwL
6+
59wH7wVzKlneCxQkbXIB1RUgQLSVLZ9+v2vxJlBFtHUWenAJDnnKKe+FxCYJ3lgw
7+
JvH0QnnTGiNWxd6QZnqWbQ5RiWikK2cJTfhNw6rV/qZ6rJslUGJhp3hlXqktmwbb
8+
A82hbK+7AgMBAAECggEAKwg8Bm89d2JehIZIkl3/KYQlAh5b34qFyXaFjs/lEGk8
9+
NMKHci6xbQ0Nva75wZ04EBt9VmQfBSs5lhEM496hQkN57YIwhOwsLuGzC6l3UuRA
10+
ULndliXfotzY/LJuGd4URT9AI/UD19v7STPd6jcEGa04qCa/bS5dyPOF6Q+sQop8
11+
2omzQ1HBIA+bQz/XNb/APgS3Cz1DUG5KpLZ/JdMbEVbZZv1uMq/vtopri2mVrF1i
12+
2hrO+Rzchgko0prpM/CJECPUq/tzf9vKJJPQTPjSq6gW0w7iDcwwvZ53e/eevwE8
13+
hgddW9OH9VdzlVUiYUP9Mo/o2LpblRleYy5oiRG0QQKBgQD4kM2qSH8ujTmwcQR3
14+
YBcQkWXP7M6tQnsvAis+hJVuRUE5IK0ptLKnNOUNtVWaXmjjTx4M6wq39LP+gjhP
15+
z1aD2HIxq6S94wzkUBd5UQ25qRE+sm0/blWWjTiUTsZljH9kP+dt4ehNlLH1+IWr
16+
UdWoFy0iXJ/RfJq3Ix2G5RIW4QKBgQDENqhTVMd7OxA2TRbgFy19RzTd42lVbLJQ
17+
aL8XOKLrB3w7vPRnMRtEb9NWTCrzGKRFWhetOk2mRjdJdrUzvEYiCB1zHIvHWT3r
18+
VZtqKpRopjnBz0quTiTE8eyIW2zb/2i2K67funEY/6mcPmrNeUTDV+VgqKha8YIG
19+
EmbGKlsGGwKBgQDYErhV0FOOmgGOGZCyXPtv0ZTZnJdFEceXY6FH5WUoyFccXAVr
20+
fcLXiymaMwnI+UzgXERZInDc3IEjOvvMlQY18o/CEd1Rm+/3AJCHSyhNPmTZRa2m
21+
ODl6eCS494mLeQi8kriRUpHn7tyMX4+DD85VImB/wFjFeDXeAU6HltWUwQKBgFFP
22+
8UuvS4em/13xbnRpRoGvO5pkfqdXB0JJVj9yShmqHXLIKGSHNiyTRvpxUC8z3Aed
23+
gUhZbApm+Mxp9Ee/UzURNdsZTlfLhNx8uo4xnRUNJcxKckFvws8XDpWnhaJZ4vPz
24+
gGHY6ruYX5qPR0VlZvio+TaoTjR59w87GvouXVBXAoGAegBMrk0AnDrkp24qLIou
25+
Wuex7zPT0ch8m3oAO2HTw5+eQsRq3jHIsGe5bWmYmb38JdMX9hDoG6xoA9KtZ5GR
26+
p9tvssL61lcjVHKqPMB0lGbHUYkV1dFHQLyST1rU2dGRLrasOfA5+O+JIvcUfXkt
27+
fDPgrVwKYwFMF3lHfqurlv4=
28+
-----END PRIVATE KEY-----

tests/resources/tls13_device.pem.crt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIEBjCCAu6gAwIBAgIUS65CZ7+pv9CHaRQf1/uFEpbc8gUwDQYJKoZIhvcNAQEL
3+
BQAwgZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQH
4+
DAdTZWF0dGxlMQ8wDQYDVQQKDAZBbWF6b24xDTALBgNVBAsMBFNES3MxEjAQBgNV
5+
BAMMCWxvY2FsaG9zdDEwMC4GCSqGSIb3DQEJARYhYXdzLXNkay1jb21tb24tcnVu
6+
dGltZUBhbWF6b24uY29tMB4XDTI0MTIwOTE4MTgyMloXDTI2MDQyMzE4MTgyMlow
7+
gZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT
8+
ZWF0dGxlMQ8wDQYDVQQKDAZBbWF6b24xDTALBgNVBAsMBFNES3MxEjAQBgNVBAMM
9+
CWxvY2FsaG9zdDEwMC4GCSqGSIb3DQEJARYhYXdzLXNkay1jb21tb24tcnVudGlt
10+
ZUBhbWF6b24uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvoPv
11+
cbGoS/OU1Brb4m/8iGbEztKjY9gKKyLUfp2dDNq+F+DOOTXULFCjKZHCephjJqTV
12+
tvEQtfgyPlZ8SgJWPgc7a9QtkjJGXo930VDL3YsdZihVo5tzPcO2FBXWrEirwBLo
13+
qC9P9t2oM93hoi4TfBsWfQYY77kT29gQ9UDbdkHjDP3UeQdOc18b75GfMYVws7ut
14+
NRBvP9nMC+fcB+8FcypZ3gsUJG1yAdUVIEC0lS2ffr9r8SZQRbR1FnpwCQ55yinv
15+
hcQmCd5YMCbx9EJ50xojVsXekGZ6lm0OUYlopCtnCU34TcOq1f6meqybJVBiYad4
16+
ZV6pLZsG2wPNoWyvuwIDAQABo0IwQDAdBgNVHQ4EFgQU9e1gHOdRMBOQfOm+Iv/8
17+
1O1nERkwHwYDVR0jBBgwFoAUsScN2gc75tU4sIBIyoSZ7jk8isAwDQYJKoZIhvcN
18+
AQELBQADggEBAF37+XsR7k+Lx//10DwJvGU9WlQ+q+jQ0US3XPX7/QPkTY8fDeGE
19+
sGzVZ8WzmZQ10sP/Ac3MSMcG2Wp8aDZ52NSxyW6q7BQWLUSk+HQLkPyfULZ5oxYT
20+
JZ5iiqIswIJxGEl+hAtm/plxY9ndRnN9Gn7JQqj/Yjw1yvIoge/mQ5GyLjv4IPIi
21+
JqF1mwbmI0GOFGJNExvDjFrtKNYMloYRrSEjeUkr7hRKyoKo5/HNfuqFQz4DE9wq
22+
LYPYo3Ul/WyoduSG2WtXOLMd8zGEnXDfdwB0oCJrEMwQQbPk4rUbvHDEu3zkpqls
23+
MbxduaL9hTEgkNczKi5QHp60u3njrpvvWW0=
24+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)