Skip to content

Commit e2fcfab

Browse files
authored
Clarify s2nc/s2nd PQ output (#4702)
1 parent de0b39d commit e2fcfab

File tree

4 files changed

+91
-54
lines changed

4 files changed

+91
-54
lines changed

bin/echo.c

+20-3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ const char *sig_hash_strs[] = {
5151
[S2N_TLS_HASH_MD5_SHA1] = "MD5_SHA1",
5252
};
5353

54+
/* Careful: don't change this without updating the integration tests that check for it!
55+
* Negative cases may stop working but not fail when this is updated.
56+
*/
57+
const char *pq_enabled_note = "PQ key exchange enabled";
58+
5459
void print_s2n_error(const char *app_error)
5560
{
5661
fprintf(stderr, "[%d] %s: '%s' : '%s'\n", getpid(), app_error, s2n_strerror(s2n_errno, "EN"),
@@ -175,9 +180,21 @@ int print_connection_info(struct s2n_connection *conn)
175180
printf("Application protocol: %s\n", s2n_get_application_protocol(conn));
176181
}
177182

178-
printf("Curve: %s\n", s2n_connection_get_curve(conn));
179-
printf("KEM: %s\n", s2n_connection_get_kem_name(conn));
180-
printf("KEM Group: %s\n", s2n_connection_get_kem_group_name(conn));
183+
const char *kem = s2n_connection_get_kem_name(conn);
184+
if (strcmp(kem, "NONE") != 0) {
185+
printf("Legacy TLS1.2 KEM: %s (%s, but the use of PQ key exchange with "
186+
"TLS1.2 was experimental and is neither stable nor on a path to "
187+
"standardization. The TLS1.3 version should be used instead: "
188+
"https://aws.github.io/s2n-tls/usage-guide/ch15-post-quantum.html)\n",
189+
kem, pq_enabled_note);
190+
}
191+
192+
const char *kem_group = s2n_connection_get_kem_group_name(conn);
193+
if (strcmp(kem_group, "NONE") != 0) {
194+
printf("KEM Group: %s (%s)\n", kem_group, pq_enabled_note);
195+
} else {
196+
printf("Curve: %s\n", s2n_connection_get_curve(conn));
197+
}
181198

182199
uint32_t length = 0;
183200
const uint8_t *status = s2n_connection_get_ocsp_response(conn, &length);

nix/README.md

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ To enter the development shell, run `nix develop` at the root of the project.
2828

2929
There are some helper scripts in the environment to make building easier, but if you're familiar with Nix, note that these are
3030
separate from the buildPhase, configurePhase and checkPhase.
31+
32+
### Specific libcrypto
33+
34+
By default, the devShell uses Openssl-3. To run the devShell with a different libcrypto like awslc, use `nix develop .#awslc`. The currently supported options are awslc, openssl111, openssl102, and libressl. See flake.nix in the root directory.
35+
3136
### Configure and build
3237

3338
From inside the devShell: `configure; build`.

tests/integrationv2/test_pq_handshake.py

+50-41
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from utils import invalid_test_parameters, get_parameter_name, to_bytes
99
from global_flags import get_flag, S2N_PROVIDER_VERSION
1010

11+
PQ_ENABLED_FLAG = "PQ key exchange enabled"
12+
1113
CIPHERS = [
1214
None, # `None` will default to the appropriate `test_all` cipher preference in the S2N client provider
1315
Ciphers.KMS_PQ_TLS_1_0_2019_06,
@@ -31,120 +33,120 @@
3133
# The tuple keys have the form (client_{cipher, kem_group}, server_{cipher, kem_group})
3234
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_PQ_TLS_1_0_2019_06):
3335
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
34-
"kem": "NONE", "kem_group": "NONE"},
36+
"kem": None, "kem_group": None},
3537
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_PQ_TLS_1_0_2020_02):
3638
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
37-
"kem": "NONE", "kem_group": "NONE"},
39+
"kem": None, "kem_group": None},
3840
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_PQ_TLS_1_0_2020_07):
3941
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
40-
"kem": "NONE", "kem_group": "NONE"},
42+
"kem": None, "kem_group": None},
4143

4244
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2019_06):
4345
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
44-
"kem": "NONE", "kem_group": "NONE"},
46+
"kem": None, "kem_group": None},
4547
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_02):
4648
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
47-
"kem": "NONE", "kem_group": "NONE"},
49+
"kem": None, "kem_group": None},
4850
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_07):
4951
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
50-
"kem": "NONE", "kem_group": "NONE"},
52+
"kem": None, "kem_group": None},
5153

5254
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_PQ_TLS_1_0_2019_06):
5355
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
54-
"kem": "NONE", "kem_group": "NONE"},
56+
"kem": None, "kem_group": None},
5557
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_PQ_TLS_1_0_2020_02):
5658
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
57-
"kem": "NONE", "kem_group": "NONE"},
59+
"kem": None, "kem_group": None},
5860
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_PQ_TLS_1_0_2020_07):
5961
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384",
60-
"kem": "kyber512r3", "kem_group": "NONE"},
62+
"kem": "kyber512r3", "kem_group": None},
6163

6264
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11, Ciphers.KMS_PQ_TLS_1_0_2019_06):
6365
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
64-
"kem": "NONE", "kem_group": "NONE"},
66+
"kem": None, "kem_group": None},
6567
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11, Ciphers.KMS_PQ_TLS_1_0_2020_02):
6668
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
67-
"kem": "NONE", "kem_group": "NONE"},
69+
"kem": None, "kem_group": None},
6870
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11, Ciphers.KMS_PQ_TLS_1_0_2020_07):
6971
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
70-
"kem": "NONE", "kem_group": "NONE"},
72+
"kem": None, "kem_group": None},
7173

7274
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2019_06):
7375
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
74-
"kem": "NONE", "kem_group": "NONE"},
76+
"kem": None, "kem_group": None},
7577
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_02):
7678
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
77-
"kem": "NONE", "kem_group": "NONE"},
79+
"kem": None, "kem_group": None},
7880
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_07):
7981
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
80-
"kem": "NONE", "kem_group": "NONE"},
82+
"kem": None, "kem_group": None},
8183

8284
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_TLS_1_0_2018_10):
8385
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
84-
"kem": "NONE", "kem_group": "NONE"},
86+
"kem": None, "kem_group": None},
8587
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_TLS_1_0_2018_10):
8688
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
87-
"kem": "NONE", "kem_group": "NONE"},
89+
"kem": None, "kem_group": None},
8890
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_TLS_1_0_2018_10):
8991
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
90-
"kem": "NONE", "kem_group": "NONE"},
92+
"kem": None, "kem_group": None},
9193

9294
(Ciphers.KMS_TLS_1_0_2018_10, Ciphers.KMS_PQ_TLS_1_0_2019_06):
9395
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
94-
"kem": "NONE", "kem_group": "NONE"},
96+
"kem": None, "kem_group": None},
9597
(Ciphers.KMS_TLS_1_0_2018_10, Ciphers.KMS_PQ_TLS_1_0_2020_02):
9698
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
97-
"kem": "NONE", "kem_group": "NONE"},
99+
"kem": None, "kem_group": None},
98100
(Ciphers.KMS_TLS_1_0_2018_10, Ciphers.KMS_PQ_TLS_1_0_2020_07):
99101
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
100-
"kem": "NONE", "kem_group": "NONE"},
102+
"kem": None, "kem_group": None},
101103

102104
# The expected kem_group string for this case purposefully excludes a curve;
103105
# depending on how s2n was compiled, the curve may be either x25519 or one
104106
# of the NIST curves.
105107
(Ciphers.PQ_TLS_1_0_2020_12, Ciphers.PQ_TLS_1_0_2020_12):
106108
{"cipher": "TLS_AES_256_GCM_SHA384",
107-
"kem": "NONE", "kem_group": "_kyber-512-r3"},
109+
"kem": None, "kem_group": "_kyber-512-r3"},
108110
(Ciphers.PQ_TLS_1_0_2020_12, Ciphers.PQ_TLS_1_0_2023_01):
109111
{"cipher": "TLS_AES_256_GCM_SHA384",
110-
"kem": "NONE", "kem_group": "_kyber-512-r3"},
112+
"kem": None, "kem_group": "_kyber-512-r3"},
111113
(Ciphers.PQ_TLS_1_0_2023_01, Ciphers.PQ_TLS_1_0_2023_01):
112114
{"cipher": "TLS_AES_256_GCM_SHA384",
113-
"kem": "NONE", "kem_group": "_kyber-512-r3"},
115+
"kem": None, "kem_group": "_kyber-512-r3"},
114116
(Ciphers.PQ_TLS_1_0_2023_01, Ciphers.PQ_TLS_1_0_2020_12):
115117
{"cipher": "TLS_AES_256_GCM_SHA384",
116-
"kem": "NONE", "kem_group": "_kyber-512-r3"},
118+
"kem": None, "kem_group": "_kyber-512-r3"},
117119
(Ciphers.PQ_TLS_1_0_2020_12, Ciphers.KMS_PQ_TLS_1_0_2020_07):
118120
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384",
119-
"kem": "kyber512r3", "kem_group": "NONE"},
121+
"kem": "kyber512r3", "kem_group": None},
120122
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.PQ_TLS_1_0_2020_12):
121123
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384",
122-
"kem": "kyber512r3", "kem_group": "NONE"},
124+
"kem": "kyber512r3", "kem_group": None},
123125
(Ciphers.PQ_TLS_1_0_2020_12, KemGroups.P256_KYBER512R3):
124-
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
126+
{"cipher": "AES256_GCM_SHA384", "kem": None,
125127
"kem_group": "secp256r1_kyber-512-r3"},
126128
(KemGroups.P256_KYBER512R3, Ciphers.PQ_TLS_1_0_2020_12):
127-
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
129+
{"cipher": "AES256_GCM_SHA384", "kem": None,
128130
"kem_group": "secp256r1_kyber-512-r3"},
129131
(KemGroups.P256_KYBER512R3, Ciphers.PQ_TLS_1_0_2023_01):
130-
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
132+
{"cipher": "AES256_GCM_SHA384", "kem": None,
131133
"kem_group": "secp256r1_kyber-512-r3"},
132134
(KemGroups.P256_KYBER512R3, Ciphers.PQ_TLS_1_3_2023_06_01):
133-
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
135+
{"cipher": "AES256_GCM_SHA384", "kem": None,
134136
"kem_group": "secp256r1_kyber-512-r3"},
135137
(KemGroups.P384_KYBER768R3, Ciphers.PQ_TLS_1_3_2023_06_01):
136-
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
138+
{"cipher": "AES256_GCM_SHA384", "kem": None,
137139
"kem_group": "secp384r1_kyber-768-r3"},
138140
(KemGroups.P521_KYBER1024R3, Ciphers.PQ_TLS_1_3_2023_06_01):
139-
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
141+
{"cipher": "AES256_GCM_SHA384", "kem": None,
140142
"kem_group": "secp521r1_kyber-1024-r3"},
141143
(Ciphers.PQ_TLS_1_3_2023_06_01, KemGroups.X25519Kyber768Draft00):
142144
{"cipher": "TLS_AES_256_GCM_SHA384",
143-
"kem": "NONE",
145+
"kem": None,
144146
"kem_group": "X25519Kyber768Draft00"},
145147
(Ciphers.PQ_TLS_1_3_2023_06_01, KemGroups.SecP256r1Kyber768Draft00):
146148
{"cipher": "TLS_AES_256_GCM_SHA384",
147-
"kem": "NONE",
149+
"kem": None,
148150
"kem_group": "SecP256r1Kyber768Draft00"},
149151
}
150152

@@ -181,11 +183,18 @@ def assert_s2n_negotiation_parameters(s2n_results, expected_result):
181183
if expected_result is not None:
182184
assert to_bytes(
183185
("Cipher negotiated: " + expected_result['cipher'])) in s2n_results.stdout
184-
assert to_bytes(
185-
("KEM: " + expected_result['kem'])) in s2n_results.stdout
186-
# Purposefully leave off the "KEM Group: " prefix in order to perform partial matches
187-
# without specifying the curve.
188-
assert to_bytes(expected_result['kem_group']) in s2n_results.stdout
186+
if expected_result['kem']:
187+
assert to_bytes(
188+
("KEM: " + expected_result['kem'])) in s2n_results.stdout
189+
assert to_bytes(PQ_ENABLED_FLAG) in s2n_results.stdout
190+
if expected_result['kem_group']:
191+
# Purposefully leave off the "KEM Group: " prefix in order to perform partial matches
192+
# without specifying the curve.
193+
assert to_bytes(expected_result['kem_group']) in s2n_results.stdout
194+
assert to_bytes(PQ_ENABLED_FLAG) in s2n_results.stdout
195+
if not expected_result['kem'] and not expected_result['kem_group']:
196+
assert to_bytes(PQ_ENABLED_FLAG) not in s2n_results.stdout
197+
assert to_bytes("Curve:") in s2n_results.stdout
189198

190199

191200
def assert_awslc_negotiation_parameters(awslc_results, expected_result):
@@ -256,7 +265,7 @@ def test_s2nc_to_s2nd_pq_handshake(managed_process, protocol, certificate, clien
256265
# If PQ is not enabled in s2n, we expect classic handshakes to be negotiated.
257266
# Leave the expected cipher blank, as there are multiple possibilities - the
258267
# important thing is that kem and kem_group are NONE.
259-
expected_result = {"cipher": "", "kem": "NONE", "kem_group": "NONE"}
268+
expected_result = {"cipher": "", "kem": None, "kem_group": None}
260269

261270
# Client and server are both s2n; can make meaningful assertions about negotiation for both
262271
for results in client.get_results():

tests/integrationv2/test_well_known_endpoints.py

+16-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from fixtures import managed_process # lgtm [py/unused-import]
77
from global_flags import get_flag, is_criterion_on, S2N_FIPS_MODE, S2N_USE_CRITERION
88
from providers import Provider, S2N
9+
from test_pq_handshake import PQ_ENABLED_FLAG
910
from utils import invalid_test_parameters, get_parameter_name, to_bytes
1011

1112

@@ -60,28 +61,28 @@
6061
if pq_enabled():
6162
EXPECTED_RESULTS = {
6263
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06):
63-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
64+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
6465
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11):
65-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
66+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
6667
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07):
6768
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384", "kem": "kyber512r3"},
6869
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02):
69-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
70+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
7071
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02):
71-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
72+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
7273
}
7374
else:
7475
EXPECTED_RESULTS = {
7576
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06):
76-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
77+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
7778
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11):
78-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
79+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
7980
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07):
80-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
81+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
8182
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02):
82-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
83+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
8384
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02):
84-
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
85+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
8586
}
8687

8788

@@ -122,4 +123,9 @@ def test_well_known_endpoints(managed_process, protocol, endpoint, provider, cip
122123

123124
if expected_result is not None:
124125
assert to_bytes(expected_result['cipher']) in results.stdout
125-
assert to_bytes(expected_result['kem']) in results.stdout
126+
if expected_result['kem']:
127+
assert to_bytes(expected_result['kem']) in results.stdout
128+
assert to_bytes(PQ_ENABLED_FLAG) in results.stdout
129+
else:
130+
assert to_bytes('KEM:') not in results.stdout
131+
assert to_bytes(PQ_ENABLED_FLAG) not in results.stdout

0 commit comments

Comments
 (0)