Skip to content

Commit 52220a8

Browse files
authored
Complete the migration to s2n_pq_is_enabled() (#2510)
* Migrate ad-hoc PQ checks to consolidated s2n_pq_is_enabled function * Fix typo in comment * Better parameterization for TLS1.3 PQ handshake test
1 parent 750f844 commit 52220a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+699
-670
lines changed

error/s2n_errno.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ static const char *no_such_error = "Internal s2n error";
215215
ERR_ENTRY(S2N_ERR_SESSION_TICKET_NOT_SUPPORTED, "Session ticket not supported for this connection") \
216216
ERR_ENTRY(S2N_ERR_OCSP_NOT_SUPPORTED, "OCSP stapling was requested, but is not supported") \
217217
ERR_ENTRY(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES, "Invalid signature algorithms preferences version") \
218-
ERR_ENTRY(S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS, "PQ KEMs are disallowed while in FIPS mode") \
219218
ERR_ENTRY(S2N_RSA_PSS_NOT_SUPPORTED, "RSA-PSS signing not supported by underlying libcrypto implementation") \
220219
ERR_ENTRY(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE, "Inner plaintext size exceeds limit") \
221220
ERR_ENTRY(S2N_ERR_INVALID_ECC_PREFERENCES, "Invalid ecc curves preferences version") \

error/s2n_errno.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ typedef enum {
111111
S2N_ERR_BAD_KEY_SHARE,
112112
S2N_ERR_CANCELLED,
113113
S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED,
114-
S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS,
115114
S2N_ERR_MAX_INNER_PLAINTEXT_SIZE,
116115
S2N_ERR_RECORD_STUFFER_SIZE,
117116
S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE,

tests/integrationv2/common.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import threading
66

77
from constants import TEST_CERT_DIRECTORY
8+
from global_flags import get_flag, S2N_NO_PQ, S2N_FIPS_MODE
89

910

1011
def data_bytes(n_bytes):
@@ -27,6 +28,13 @@ def data_bytes(n_bytes):
2728
return bytes(byte_array)
2829

2930

31+
def pq_enabled():
32+
"""
33+
Returns true or false to indicate whether PQ crypto is enabled in s2n
34+
"""
35+
return not (get_flag(S2N_NO_PQ, False) or get_flag(S2N_FIPS_MODE, False))
36+
37+
3038
class AvailablePorts(object):
3139
"""
3240
This iterator will atomically return the next number.

tests/integrationv2/test_pq_handshake.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33

44
from configuration import available_ports, PROVIDERS, PROTOCOLS
5-
from common import Ciphers, ProviderOptions, Protocols, data_bytes, KemGroups, Certificates
5+
from common import Ciphers, ProviderOptions, Protocols, data_bytes, KemGroups, Certificates, pq_enabled
66
from fixtures import managed_process
77
from providers import Provider, S2N, OpenSSL
88
from utils import invalid_test_parameters, get_parameter_name
@@ -163,7 +163,13 @@ def test_s2nc_to_s2nd_pq_handshake(managed_process, protocol, client_cipher, ser
163163
server = managed_process(S2N, server_options, timeout=5)
164164
client = managed_process(S2N, client_options, timeout=5)
165165

166-
expected_result = EXPECTED_RESULTS.get((client_cipher, server_cipher), None)
166+
if pq_enabled():
167+
expected_result = EXPECTED_RESULTS.get((client_cipher, server_cipher), None)
168+
else:
169+
# If PQ is not enabled in s2n, we expect classic handshakes to be negotiated.
170+
# Leave the expected cipher blank, as there are multiple possibilities - the
171+
# important thing is that kem and kem_group are NONE.
172+
expected_result = {"cipher": "", "kem": "NONE", "kem_group": "NONE"}
167173

168174
# Client and server are both s2n; can make meaningful assertions about negotiation for both
169175
for results in client.get_results():
@@ -181,6 +187,10 @@ def test_s2nc_to_s2nd_pq_handshake(managed_process, protocol, client_cipher, ser
181187
@pytest.mark.parametrize("cipher", [Ciphers.PQ_TLS_1_0_2020_12], ids=get_parameter_name)
182188
@pytest.mark.parametrize("kem_group", KEM_GROUPS, ids=get_parameter_name)
183189
def test_s2nc_to_oqs_openssl_pq_handshake(managed_process, protocol, cipher, kem_group):
190+
# If PQ is not enabled in s2n, there is no reason to test against oqs_openssl
191+
if not pq_enabled():
192+
return
193+
184194
host = "localhost"
185195
port = next(available_ports)
186196

@@ -223,6 +233,10 @@ def test_s2nc_to_oqs_openssl_pq_handshake(managed_process, protocol, cipher, kem
223233
@pytest.mark.parametrize("cipher", [Ciphers.PQ_TLS_1_0_2020_12], ids=get_parameter_name)
224234
@pytest.mark.parametrize("kem_group", KEM_GROUPS, ids=get_parameter_name)
225235
def test_oqs_openssl_to_s2nd_pq_handshake(managed_process, protocol, cipher, kem_group):
236+
# If PQ is not enabled in s2n, there is no reason to test against oqs_openssl
237+
if not pq_enabled():
238+
return
239+
226240
host = "localhost"
227241
port = next(available_ports)
228242

tests/integrationv2/test_well_known_endpoints.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from constants import TRUST_STORE_BUNDLE
44
from configuration import available_ports, PROTOCOLS
5-
from common import ProviderOptions, Protocols, Ciphers
5+
from common import ProviderOptions, Protocols, Ciphers, pq_enabled
66
from fixtures import managed_process
77
from global_flags import get_flag, S2N_FIPS_MODE
88
from providers import Provider, S2N
@@ -30,13 +30,34 @@
3030
Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02
3131
]
3232

33-
EXPECTED_RESULTS = {
34-
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06): {"cipher": "ECDHE-BIKE-RSA-AES256-GCM-SHA384", "kem": "BIKE1r1-Level1"},
35-
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11): {"cipher": "ECDHE-SIKE-RSA-AES256-GCM-SHA384", "kem": "SIKEp503r1-KEM"},
36-
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07): {"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384", "kem": "kyber512r2"},
37-
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02): {"cipher": "ECDHE-BIKE-RSA-AES256-GCM-SHA384", "kem": "BIKE1r2-Level1"},
38-
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02): {"cipher": "ECDHE-SIKE-RSA-AES256-GCM-SHA384", "kem": "SIKEp434r2-KEM"},
39-
}
33+
34+
if pq_enabled():
35+
EXPECTED_RESULTS = {
36+
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06):
37+
{"cipher": "ECDHE-BIKE-RSA-AES256-GCM-SHA384", "kem": "BIKE1r1-Level1"},
38+
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11):
39+
{"cipher": "ECDHE-SIKE-RSA-AES256-GCM-SHA384", "kem": "SIKEp503r1-KEM"},
40+
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07):
41+
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384", "kem": "kyber512r2"},
42+
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02):
43+
{"cipher": "ECDHE-BIKE-RSA-AES256-GCM-SHA384", "kem": "BIKE1r2-Level1"},
44+
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02):
45+
{"cipher": "ECDHE-SIKE-RSA-AES256-GCM-SHA384", "kem": "SIKEp434r2-KEM"},
46+
}
47+
else:
48+
EXPECTED_RESULTS = {
49+
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06):
50+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
51+
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11):
52+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
53+
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07):
54+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
55+
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02):
56+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
57+
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02):
58+
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
59+
}
60+
4061

4162
@pytest.mark.uncollect_if(func=invalid_test_parameters)
4263
@pytest.mark.parametrize("protocol", PROTOCOLS, ids=get_parameter_name)

tests/integrationv2/utils.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from common import Protocols, Curves, Ciphers
22
from providers import S2N, OpenSSL
3-
from global_flags import get_flag, S2N_NO_PQ, S2N_FIPS_MODE
43

54

65
def get_expected_s2n_version(protocol, provider):
@@ -63,12 +62,6 @@ def invalid_test_parameters(*args, **kwargs):
6362
return True
6463

6564
if cipher is not None:
66-
# TODO Remove this check once the pq-enabled update is complete; once complete,
67-
# s2n will ignore PQ ciphers if PQ is not enabled, so we won't have to perform
68-
# this check in the tests (See discussion in PR #2426).
69-
if cipher.pq and (get_flag(S2N_NO_PQ, False) or get_flag(S2N_FIPS_MODE, False)):
70-
return True
71-
7265
# If the selected protocol doesn't allow the cipher, don't test
7366
if protocol is not None:
7467
if cipher.min_version > protocol:

tests/testlib/s2n_pq_hybrid_test_utils.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include "utils/s2n_safety.h"
2121
#include "crypto/s2n_drbg.h"
2222
#include "crypto/s2n_openssl.h"
23-
#include "crypto/s2n_fips.h"
23+
#include "pq-crypto/s2n_pq.h"
2424
#include "stuffer/s2n_stuffer.h"
2525
#include "tests/testlib/s2n_testlib.h"
2626
#include "tls/s2n_kex.h"
@@ -55,7 +55,6 @@ int s2n_hybrid_pq_entropy(void *ptr, uint32_t size) {
5555

5656
static int setup_connection(struct s2n_connection *conn, const struct s2n_kem *kem, struct s2n_cipher_suite *cipher_suite,
5757
const char *cipher_pref_version) {
58-
S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
5958
conn->actual_protocol_version = S2N_TLS12;
6059

6160
const struct s2n_ecc_preferences *ecc_preferences = NULL;
@@ -73,7 +72,7 @@ static int setup_connection(struct s2n_connection *conn, const struct s2n_kem *k
7372
int s2n_test_hybrid_ecdhe_kem_with_kat(const struct s2n_kem *kem, struct s2n_cipher_suite *cipher_suite,
7473
const char *cipher_pref_version, const char * kat_file_name, uint32_t server_key_message_length,
7574
uint32_t client_key_message_length) {
76-
S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
75+
ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
7776

7877
/* Part 1 setup a client and server connection with everything they need for a key exchange */
7978
struct s2n_connection *client_conn = NULL, *server_conn = NULL;

tests/testlib/s2n_pq_kat_test_utils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include "tests/testlib/s2n_nist_kats.h"
2020
#include "utils/s2n_mem.h"
2121
#include "utils/s2n_safety.h"
22-
#include "crypto/s2n_fips.h"
22+
#include "pq-crypto/s2n_pq.h"
2323
#include "pq-crypto/s2n_pq_random.h"
2424

2525
/* We include s2n_drbg.c directly in order to access the static functions in our entropy callbacks. */
@@ -103,7 +103,7 @@ S2N_RESULT s2n_get_random_bytes_for_pq_kat_tests(uint8_t *buffer, uint32_t num_b
103103
}
104104

105105
int s2n_test_kem_with_kat(const struct s2n_kem *kem, const char *kat_file_name) {
106-
S2N_ERROR_IF(s2n_is_in_fips_mode(), S2N_ERR_PQ_KEMS_DISALLOWED_IN_FIPS);
106+
ENSURE_POSIX(s2n_pq_is_enabled(), S2N_ERR_PQ_DISABLED);
107107
ENSURE_POSIX(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
108108

109109
notnull_check(kem);

tests/unit/s2n_choose_supported_group_test.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ int main() {
138138
}
139139
}
140140

141-
#if !defined(S2N_NO_PQ)
142141
/* Test for PQ */
143142
{
144143
const struct s2n_kem_group *test_kem_groups[] = {
@@ -313,7 +312,6 @@ int main() {
313312
EXPECT_SUCCESS(s2n_connection_free(server_conn));
314313
}
315314
}
316-
#endif
317315

318316
END_TEST();
319317
return 0;

tests/unit/s2n_cipher_suite_match_test.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#include <string.h>
2020

2121
#include "crypto/s2n_ecc_evp.h"
22-
#include "crypto/s2n_fips.h"
22+
#include "pq-crypto/s2n_pq.h"
2323
#include "tls/s2n_cipher_suites.h"
2424
#include "tls/s2n_connection.h"
2525
#include "tls/s2n_security_policies.h"
@@ -226,7 +226,7 @@ int main(int argc, char **argv)
226226
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
227227
TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
228228
TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384,
229-
TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384,
229+
TLS_ECDHE_SIKE_RSA_WITH_AES_256_GCM_SHA384,
230230
TLS_ECDHE_KYBER_RSA_WITH_AES_256_GCM_SHA384,
231231
};
232232
const uint8_t cipher_count = sizeof(wire_ciphers) / S2N_TLS_CIPHER_SUITE_LEN;
@@ -359,11 +359,27 @@ int main(int argc, char **argv)
359359
EXPECT_EQUAL(conn->secure.cipher_suite, s2n_cipher_suite_from_wire(expected_rsa_wire_choice));
360360
EXPECT_SUCCESS(s2n_connection_wipe(conn));
361361

362-
#if !defined(S2N_NO_PQ)
363-
if (!s2n_is_in_fips_mode()) {
364-
/* There is no support for PQ KEMs while in FIPS mode */
365-
/* Test that clients that support PQ ciphers can negotiate them. */
366-
const uint8_t expected_pq_wire_choice[] = {TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384};
362+
/* Test that PQ cipher suites are marked available/unavailable appropriately in s2n_cipher_suites_init() */
363+
{
364+
const struct s2n_cipher_suite *pq_suites[] = {
365+
&s2n_ecdhe_sike_rsa_with_aes_256_gcm_sha384,
366+
&s2n_ecdhe_bike_rsa_with_aes_256_gcm_sha384,
367+
&s2n_ecdhe_kyber_rsa_with_aes_256_gcm_sha384,
368+
};
369+
370+
for (size_t i = 0; i < s2n_array_len(pq_suites); i++) {
371+
if (s2n_pq_is_enabled()) {
372+
EXPECT_EQUAL(pq_suites[i]->available, 1);
373+
EXPECT_NOT_NULL(pq_suites[i]->record_alg);
374+
} else {
375+
EXPECT_EQUAL(pq_suites[i]->available, 0);
376+
EXPECT_NULL(pq_suites[i]->record_alg);
377+
}
378+
}
379+
}
380+
381+
/* Test that clients that support PQ ciphers can negotiate them. */
382+
{
367383
uint8_t client_extensions_data[] = {
368384
0xFE, 0x01, /* PQ KEM extension ID */
369385
0x00, 0x04, /* Total extension length in bytes */
@@ -377,7 +393,14 @@ int main(int argc, char **argv)
377393
conn->secure.client_pq_kem_extension.data = client_extensions_data;
378394
conn->secure.client_pq_kem_extension.size = client_extensions_len;
379395
EXPECT_SUCCESS(s2n_set_cipher_as_tls_server(conn, wire_ciphers, cipher_count));
380-
EXPECT_EQUAL(conn->secure.cipher_suite, s2n_cipher_suite_from_wire(expected_pq_wire_choice));
396+
const uint8_t bike_cipher[] = {TLS_ECDHE_BIKE_RSA_WITH_AES_256_GCM_SHA384};
397+
const uint8_t ecc_cipher[] = {TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384};
398+
if (s2n_pq_is_enabled()) {
399+
EXPECT_EQUAL(conn->secure.cipher_suite, s2n_cipher_suite_from_wire(bike_cipher));
400+
} else {
401+
EXPECT_EQUAL(conn->secure.cipher_suite, s2n_cipher_suite_from_wire(ecc_cipher));
402+
}
403+
381404
EXPECT_SUCCESS(s2n_connection_wipe(conn));
382405

383406
/* Test cipher preferences that use PQ cipher suites that require TLS 1.2 fall back to classic ciphers if a client
@@ -395,7 +418,6 @@ int main(int argc, char **argv)
395418
EXPECT_SUCCESS(s2n_connection_wipe(conn));
396419
}
397420
}
398-
#endif
399421

400422
/* Clean+free to setup for ECDSA tests */
401423
EXPECT_SUCCESS(s2n_config_free(server_config));

0 commit comments

Comments
 (0)