|
16 | 16 | #include "crypto/s2n_ecc_evp.h" |
17 | 17 |
|
18 | 18 | #include "api/s2n.h" |
| 19 | +#include "crypto/s2n_fips.h" |
| 20 | +#include "crypto/s2n_libcrypto.h" |
19 | 21 | #include "s2n_test.h" |
20 | 22 | #include "stuffer/s2n_stuffer.h" |
21 | 23 | #include "testlib/s2n_testlib.h" |
|
27 | 29 |
|
28 | 30 | extern const struct s2n_ecc_named_curve s2n_unsupported_curve; |
29 | 31 |
|
| 32 | +DEFINE_POINTER_CLEANUP_FUNC(EC_KEY*, EC_KEY_free); |
| 33 | +DEFINE_POINTER_CLEANUP_FUNC(EC_POINT*, EC_POINT_free); |
| 34 | + |
30 | 35 | int main(int argc, char** argv) |
31 | 36 | { |
32 | 37 | BEGIN_TEST(); |
33 | 38 | EXPECT_SUCCESS(s2n_disable_tls13_in_test()); |
| 39 | + |
| 40 | + /* Test the EC_KEY_CHECK_FIPS feature probe. AWS-LC is a libcrypto known to support this feature. */ |
| 41 | + if (s2n_libcrypto_is_awslc()) { |
| 42 | + EXPECT_TRUE(s2n_ecc_evp_supports_fips_check()); |
| 43 | + } |
| 44 | + |
34 | 45 | { |
35 | 46 | /* Test generate ephemeral keys for all supported curves */ |
36 | 47 | for (size_t i = 0; i < s2n_all_supported_curves_list_len; i++) { |
@@ -405,5 +416,79 @@ int main(int argc, char** argv) |
405 | 416 | EXPECT_SUCCESS(s2n_ecc_evp_params_free(&client_params)); |
406 | 417 | } |
407 | 418 | }; |
| 419 | + |
| 420 | + /** |
| 421 | + *= https://tools.ietf.org/rfc/rfc8446#section-4.2.8.2 |
| 422 | + *= type=test |
| 423 | + *# For the curves secp256r1, secp384r1, and secp521r1, peers MUST |
| 424 | + *# validate each other's public value Q by ensuring that the point is a |
| 425 | + *# valid point on the elliptic curve. The appropriate validation |
| 426 | + *# procedures are defined in Section 4.3.7 of [ECDSA] and alternatively |
| 427 | + *# in Section 5.6.2.3 of [KEYAGREEMENT]. This process consists of three |
| 428 | + *# steps: (1) verify that Q is not the point at infinity (O), (2) verify |
| 429 | + *# that for Q = (x, y) both integers x and y are in the correct |
| 430 | + *# interval, and (3) ensure that (x, y) is a correct solution to the |
| 431 | + *# elliptic curve equation. For these curves, implementors do not need |
| 432 | + *# to verify membership in the correct subgroup. |
| 433 | + * |
| 434 | + * s2n-tls performs this validation by invoking the libcrypto APIs: EC_KEY_check_key, and |
| 435 | + * EC_KEY_check_fips. To ensure that these APIs are properly called, step (1) is invalidated. |
| 436 | + */ |
| 437 | + { |
| 438 | + const struct s2n_ecc_named_curve* const nist_curves[] = { |
| 439 | + &s2n_ecc_curve_secp256r1, |
| 440 | + &s2n_ecc_curve_secp384r1, |
| 441 | + &s2n_ecc_curve_secp521r1, |
| 442 | + }; |
| 443 | + |
| 444 | + for (size_t i = 0; i < s2n_array_len(nist_curves); i++) { |
| 445 | + const struct s2n_ecc_named_curve* curve = nist_curves[i]; |
| 446 | + |
| 447 | + DEFER_CLEANUP(struct s2n_ecc_evp_params server_params = { 0 }, s2n_ecc_evp_params_free); |
| 448 | + DEFER_CLEANUP(struct s2n_ecc_evp_params client_params = { 0 }, s2n_ecc_evp_params_free); |
| 449 | + DEFER_CLEANUP(struct s2n_blob shared_key = { 0 }, s2n_free); |
| 450 | + |
| 451 | + /* Create a server key. */ |
| 452 | + server_params.negotiated_curve = curve; |
| 453 | + EXPECT_SUCCESS(s2n_ecc_evp_generate_ephemeral_key(&server_params)); |
| 454 | + EXPECT_NOT_NULL(server_params.evp_pkey); |
| 455 | + |
| 456 | + /* Create a client key. */ |
| 457 | + client_params.negotiated_curve = curve; |
| 458 | + EXPECT_SUCCESS(s2n_ecc_evp_generate_ephemeral_key(&client_params)); |
| 459 | + EXPECT_NOT_NULL(client_params.evp_pkey); |
| 460 | + |
| 461 | + /* Retrieve the existing client public key. */ |
| 462 | + DEFER_CLEANUP(EC_KEY* ec_key = EVP_PKEY_get1_EC_KEY(client_params.evp_pkey), |
| 463 | + EC_KEY_free_pointer); |
| 464 | + EXPECT_NOT_NULL(ec_key); |
| 465 | + const EC_GROUP* group = EC_KEY_get0_group(ec_key); |
| 466 | + EXPECT_NOT_NULL(group); |
| 467 | + const EC_POINT* public_key = EC_KEY_get0_public_key(ec_key); |
| 468 | + EXPECT_NOT_NULL(public_key); |
| 469 | + |
| 470 | + /* Invalidate the public key by setting the coordinate to infinity. */ |
| 471 | + DEFER_CLEANUP(EC_POINT* invalid_public_key = EC_POINT_dup(public_key, group), |
| 472 | + EC_POINT_free_pointer); |
| 473 | + EXPECT_NOT_NULL(invalid_public_key); |
| 474 | + EXPECT_EQUAL(EC_POINT_set_to_infinity(group, invalid_public_key), 1); |
| 475 | + EXPECT_EQUAL(EC_KEY_set_public_key(ec_key, invalid_public_key), 1); |
| 476 | + EXPECT_EQUAL(EVP_PKEY_set1_EC_KEY(client_params.evp_pkey, ec_key), 1); |
| 477 | + |
| 478 | + /* Compute the server's shared secret. */ |
| 479 | + int ret = s2n_ecc_evp_compute_shared_secret_from_params(&server_params, |
| 480 | + &client_params, &shared_key); |
| 481 | + |
| 482 | + /* If s2n-tls is in FIPS mode and the libcrypto supports the EC_KEY_check_fips API, |
| 483 | + * ensure that this API is called by checking for the correct error. |
| 484 | + */ |
| 485 | + if (s2n_is_in_fips_mode() && s2n_ecc_evp_supports_fips_check()) { |
| 486 | + EXPECT_FAILURE_WITH_ERRNO(ret, S2N_ERR_ECDHE_INVALID_PUBLIC_KEY_FIPS); |
| 487 | + } else { |
| 488 | + EXPECT_FAILURE_WITH_ERRNO(ret, S2N_ERR_ECDHE_INVALID_PUBLIC_KEY); |
| 489 | + } |
| 490 | + } |
| 491 | + } |
| 492 | + |
408 | 493 | END_TEST(); |
409 | 494 | } |
0 commit comments