Skip to content

Commit

Permalink
Clarify s2nc/s2nd PQ output
Browse files Browse the repository at this point in the history
  • Loading branch information
lrstewart committed Aug 12, 2024
1 parent 6578f88 commit d91acb4
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 54 deletions.
21 changes: 18 additions & 3 deletions bin/echo.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ const char *sig_hash_strs[] = {
[S2N_TLS_HASH_MD5_SHA1] = "MD5_SHA1",
};

/* Careful: don't change this without updating the integration tests that check for it!
* Negative cases may stop working but not fail when this is updated.
*/
const char *pq_enabled_note = "PQ key exchange enabled";

void print_s2n_error(const char *app_error)
{
fprintf(stderr, "[%d] %s: '%s' : '%s'\n", getpid(), app_error, s2n_strerror(s2n_errno, "EN"),
Expand Down Expand Up @@ -175,9 +180,19 @@ int print_connection_info(struct s2n_connection *conn)
printf("Application protocol: %s\n", s2n_get_application_protocol(conn));
}

printf("Curve: %s\n", s2n_connection_get_curve(conn));
printf("KEM: %s\n", s2n_connection_get_kem_name(conn));
printf("KEM Group: %s\n", s2n_connection_get_kem_group_name(conn));
const char *kem = s2n_connection_get_kem_name(conn);
if (strcmp(kem, "NONE") != 0) {
printf("Legacy TLS1.2 KEM: %s (%s, but TLS1.3 PQ hybrid key exchange strongly recommended instead. "
"See https://github.com/aws/s2n-tls/blob/main/docs/usage-guide/topics/ch15-post-quantum.md)\n",
kem, pq_enabled_note);
}

const char *kem_group = s2n_connection_get_kem_group_name(conn);
if (strcmp(kem_group, "NONE") != 0) {
printf("KEM Group: %s (%s)\n", kem_group, pq_enabled_note);
} else {
printf("Curve: %s\n", s2n_connection_get_curve(conn));
}

uint32_t length = 0;
const uint8_t *status = s2n_connection_get_ocsp_response(conn, &length);
Expand Down
5 changes: 5 additions & 0 deletions nix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ To enter the development shell, run `nix develop` at the root of the project.

There are some helper scripts in the environment to make building easier, but if you're familiar with Nix, note that these are
separate from the buildPhase, configurePhase and checkPhase.

### Specific libcrypto

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.

### Configure and build

From inside the devShell: `configure; build`.
Expand Down
91 changes: 50 additions & 41 deletions tests/integrationv2/test_pq_handshake.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from utils import invalid_test_parameters, get_parameter_name, to_bytes
from global_flags import get_flag, S2N_PROVIDER_VERSION

PQ_ENABLED_FLAG = "PQ key exchange enabled"

CIPHERS = [
None, # `None` will default to the appropriate `test_all` cipher preference in the S2N client provider
Ciphers.KMS_PQ_TLS_1_0_2019_06,
Expand All @@ -31,120 +33,120 @@
# The tuple keys have the form (client_{cipher, kem_group}, server_{cipher, kem_group})
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},

(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},

(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384",
"kem": "kyber512r3", "kem_group": "NONE"},
"kem": "kyber512r3", "kem_group": None},

(Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11, Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11, Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},

(Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},

(Ciphers.KMS_PQ_TLS_1_0_2019_06, Ciphers.KMS_TLS_1_0_2018_10):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_02, Ciphers.KMS_TLS_1_0_2018_10):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.KMS_TLS_1_0_2018_10):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},

(Ciphers.KMS_TLS_1_0_2018_10, Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_TLS_1_0_2018_10, Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},
(Ciphers.KMS_TLS_1_0_2018_10, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384",
"kem": "NONE", "kem_group": "NONE"},
"kem": None, "kem_group": None},

# The expected kem_group string for this case purposefully excludes a curve;
# depending on how s2n was compiled, the curve may be either x25519 or one
# of the NIST curves.
(Ciphers.PQ_TLS_1_0_2020_12, Ciphers.PQ_TLS_1_0_2020_12):
{"cipher": "TLS_AES_256_GCM_SHA384",
"kem": "NONE", "kem_group": "_kyber-512-r3"},
"kem": None, "kem_group": "_kyber-512-r3"},
(Ciphers.PQ_TLS_1_0_2020_12, Ciphers.PQ_TLS_1_0_2023_01):
{"cipher": "TLS_AES_256_GCM_SHA384",
"kem": "NONE", "kem_group": "_kyber-512-r3"},
"kem": None, "kem_group": "_kyber-512-r3"},
(Ciphers.PQ_TLS_1_0_2023_01, Ciphers.PQ_TLS_1_0_2023_01):
{"cipher": "TLS_AES_256_GCM_SHA384",
"kem": "NONE", "kem_group": "_kyber-512-r3"},
"kem": None, "kem_group": "_kyber-512-r3"},
(Ciphers.PQ_TLS_1_0_2023_01, Ciphers.PQ_TLS_1_0_2020_12):
{"cipher": "TLS_AES_256_GCM_SHA384",
"kem": "NONE", "kem_group": "_kyber-512-r3"},
"kem": None, "kem_group": "_kyber-512-r3"},
(Ciphers.PQ_TLS_1_0_2020_12, Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384",
"kem": "kyber512r3", "kem_group": "NONE"},
"kem": "kyber512r3", "kem_group": None},
(Ciphers.KMS_PQ_TLS_1_0_2020_07, Ciphers.PQ_TLS_1_0_2020_12):
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384",
"kem": "kyber512r3", "kem_group": "NONE"},
"kem": "kyber512r3", "kem_group": None},
(Ciphers.PQ_TLS_1_0_2020_12, KemGroups.P256_KYBER512R3):
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
{"cipher": "AES256_GCM_SHA384", "kem": None,
"kem_group": "secp256r1_kyber-512-r3"},
(KemGroups.P256_KYBER512R3, Ciphers.PQ_TLS_1_0_2020_12):
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
{"cipher": "AES256_GCM_SHA384", "kem": None,
"kem_group": "secp256r1_kyber-512-r3"},
(KemGroups.P256_KYBER512R3, Ciphers.PQ_TLS_1_0_2023_01):
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
{"cipher": "AES256_GCM_SHA384", "kem": None,
"kem_group": "secp256r1_kyber-512-r3"},
(KemGroups.P256_KYBER512R3, Ciphers.PQ_TLS_1_3_2023_06_01):
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
{"cipher": "AES256_GCM_SHA384", "kem": None,
"kem_group": "secp256r1_kyber-512-r3"},
(KemGroups.P384_KYBER768R3, Ciphers.PQ_TLS_1_3_2023_06_01):
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
{"cipher": "AES256_GCM_SHA384", "kem": None,
"kem_group": "secp384r1_kyber-768-r3"},
(KemGroups.P521_KYBER1024R3, Ciphers.PQ_TLS_1_3_2023_06_01):
{"cipher": "AES256_GCM_SHA384", "kem": "NONE",
{"cipher": "AES256_GCM_SHA384", "kem": None,
"kem_group": "secp521r1_kyber-1024-r3"},
(Ciphers.PQ_TLS_1_3_2023_06_01, KemGroups.X25519Kyber768Draft00):
{"cipher": "TLS_AES_256_GCM_SHA384",
"kem": "NONE",
"kem": None,
"kem_group": "X25519Kyber768Draft00"},
(Ciphers.PQ_TLS_1_3_2023_06_01, KemGroups.SecP256r1Kyber768Draft00):
{"cipher": "TLS_AES_256_GCM_SHA384",
"kem": "NONE",
"kem": None,
"kem_group": "SecP256r1Kyber768Draft00"},
}

Expand Down Expand Up @@ -181,11 +183,18 @@ def assert_s2n_negotiation_parameters(s2n_results, expected_result):
if expected_result is not None:
assert to_bytes(
("Cipher negotiated: " + expected_result['cipher'])) in s2n_results.stdout
assert to_bytes(
("KEM: " + expected_result['kem'])) in s2n_results.stdout
# Purposefully leave off the "KEM Group: " prefix in order to perform partial matches
# without specifying the curve.
assert to_bytes(expected_result['kem_group']) in s2n_results.stdout
if expected_result['kem']:
assert to_bytes(
("KEM: " + expected_result['kem'])) in s2n_results.stdout
assert to_bytes(PQ_ENABLED_FLAG) in s2n_results.stdout
if expected_result['kem_group']:
# Purposefully leave off the "KEM Group: " prefix in order to perform partial matches
# without specifying the curve.
assert to_bytes(expected_result['kem_group']) in s2n_results.stdout
assert to_bytes(PQ_ENABLED_FLAG) in s2n_results.stdout
if not expected_result['kem'] and not expected_result['kem_group']:
assert to_bytes(PQ_ENABLED_FLAG) not in s2n_results.stdout
assert to_bytes("Curve:") in s2n_results.stdout


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

# Client and server are both s2n; can make meaningful assertions about negotiation for both
for results in client.get_results():
Expand Down
26 changes: 16 additions & 10 deletions tests/integrationv2/test_well_known_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from fixtures import managed_process # lgtm [py/unused-import]
from global_flags import get_flag, is_criterion_on, S2N_FIPS_MODE, S2N_USE_CRITERION
from providers import Provider, S2N
from test_pq_handshake import PQ_ENABLED_FLAG
from utils import invalid_test_parameters, get_parameter_name, to_bytes


Expand Down Expand Up @@ -60,28 +61,28 @@
if pq_enabled():
EXPECTED_RESULTS = {
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-KYBER-RSA-AES256-GCM-SHA384", "kem": "kyber512r3"},
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
}
else:
EXPECTED_RESULTS = {
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2019_06):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_07):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.KMS_PQ_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
("kms.us-east-1.amazonaws.com", Ciphers.PQ_SIKE_TEST_TLS_1_0_2020_02):
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": "NONE"},
{"cipher": "ECDHE-RSA-AES256-GCM-SHA384", "kem": None},
}


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

if expected_result is not None:
assert to_bytes(expected_result['cipher']) in results.stdout
assert to_bytes(expected_result['kem']) in results.stdout
if expected_result['kem']:
assert to_bytes(expected_result['kem']) in results.stdout
assert to_bytes(PQ_ENABLED_FLAG) in results.stdout
else:
assert to_bytes('KEM:') not in results.stdout
assert to_bytes(PQ_ENABLED_FLAG) not in results.stdout

0 comments on commit d91acb4

Please sign in to comment.