From 6126680a321dd91e5e6368bfc038c578bb252d6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 16:16:53 -0400 Subject: [PATCH 1/4] Added Brainpool curves for TLS 1.3 and ECDSA verification Fixes #380 NetX Secure lacked Brainpool domain parameters and TLS 1.3 mappings, so it could not negotiate Brainpool key shares or verify signatures on these curves. Added RFC 5639 P256r1, P384r1 and P512r1 curves, RFC 8734 groups and signature schemes, X.509 OIDs, and a general projective doubling formula. Added regression vectors and TLS handshake tests. Standalone ECDH, ECDSA and Brainpool tests passed (3/3); TLS 1.3 Brainpool tests passed (3/3); the TLS 1.2 ECC baseline passed (1/1). GCC 14 CMake/Ninja builds passed for TLS 1.3, TLS 1.2 and no-ECC configurations. Assisted-by: Codex (GPT-6-Sol) --- crypto_libraries/inc/nx_crypto_ec.h | 22 +- crypto_libraries/src/nx_crypto_ec.c | 386 ++++++++++++++++- .../src/nx_crypto_generic_ciphersuites.c | 15 +- crypto_libraries/src/nx_crypto_methods.c | 23 + nx_secure/inc/nx_secure_tls.h | 5 + nx_secure/inc/nx_secure_x509.h | 6 +- .../src/nx_secure_tls_find_curve_method.c | 23 + ...x_secure_tls_process_certificate_request.c | 10 +- ...nx_secure_tls_process_certificate_verify.c | 33 +- ...ecure_tls_process_clienthello_extensions.c | 30 +- ...ecure_tls_process_serverhello_extensions.c | 3 + .../nx_secure_tls_send_certificate_request.c | 12 +- .../nx_secure_tls_send_certificate_verify.c | 43 +- ...x_secure_tls_send_clienthello_extensions.c | 85 +++- ...x_secure_tls_send_serverhello_extensions.c | 4 +- nx_secure/src/nx_secure_x509_oid_parse.c | 9 +- test/cmake/crypto/regression/CMakeLists.txt | 3 +- .../nx_secure_test/brainpool_certs.c | 109 +++++ .../nx_secure_test/nx_secure_brainpool_test.c | 394 ++++++++++++++++++ .../nx_secure_tls_1_3_provisioned_psk_test.c | 39 +- ...ls_clienthello_signature_algorithms_test.c | 77 +++- .../nx_secure_tls_ecc_basic_test.c | 65 ++- 22 files changed, 1349 insertions(+), 47 deletions(-) create mode 100644 test/regression/nx_secure_test/brainpool_certs.c create mode 100644 test/regression/nx_secure_test/nx_secure_brainpool_test.c diff --git a/crypto_libraries/inc/nx_crypto_ec.h b/crypto_libraries/inc/nx_crypto_ec.h index 133b000ad..dc1a4694d 100644 --- a/crypto_libraries/inc/nx_crypto_ec.h +++ b/crypto_libraries/inc/nx_crypto_ec.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -460,12 +462,21 @@ extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp224r1; extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp256r1; extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp384r1; extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp521r1; +extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_brainpoolp256r1; +extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_brainpoolp384r1; +extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_brainpoolp512r1; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp384; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp512; #define NX_CRYPTO_EC_GET_SECP192R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_secp192r1 #define NX_CRYPTO_EC_GET_SECP224R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_secp224r1 #define NX_CRYPTO_EC_GET_SECP256R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_secp256r1 #define NX_CRYPTO_EC_GET_SECP384R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_secp384r1 #define NX_CRYPTO_EC_GET_SECP521R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_secp521r1 +#define NX_CRYPTO_EC_GET_BRAINPOOLP256R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_brainpoolp256r1 +#define NX_CRYPTO_EC_GET_BRAINPOOLP384R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_brainpoolp384r1 +#define NX_CRYPTO_EC_GET_BRAINPOOLP512R1(curve) curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_brainpoolp512r1 UINT _nx_crypto_ec_point_is_infinite(NX_CRYPTO_EC_POINT *point); VOID _nx_crypto_ec_point_set_infinite(NX_CRYPTO_EC_POINT *point); @@ -614,6 +625,16 @@ UINT _nx_crypto_method_ec_secp521r1_operation(UINT op, VOID *crypto_metadata, ULONG crypto_metadata_size, VOID *packet_ptr, VOID (*nx_crypto_hw_process_callback)(VOID *, UINT)); +UINT _nx_crypto_method_ec_brainpool_operation(UINT op, + VOID *handle, + struct NX_CRYPTO_METHOD_STRUCT *method, + UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits, + UCHAR *input, ULONG input_length_in_byte, + UCHAR *iv_ptr, + UCHAR *output, ULONG output_length_in_byte, + VOID *crypto_metadata, ULONG crypto_metadata_size, + VOID *packet_ptr, + VOID (*nx_crypto_hw_process_callback)(VOID *, UINT)); #ifdef NX_CRYPTO_ENABLE_CURVE25519_448 extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_x25519; @@ -659,4 +680,3 @@ UINT _nx_crypto_ec_extract_fixed_size_le(NX_CRYPTO_HUGE_NUMBER *number, #endif #endif /* NX_CRYPTO_EC_H */ - diff --git a/crypto_libraries/src/nx_crypto_ec.c b/crypto_libraries/src/nx_crypto_ec.c index 92e4ce171..33ac783dc 100644 --- a/crypto_libraries/src/nx_crypto_ec.c +++ b/crypto_libraries/src/nx_crypto_ec.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -370,6 +372,120 @@ static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_secp521r1_h[] = HN_ULONG_TO_UBASE(0x00000001) }; +/* RFC 5639 brainpoolP256r1 domain parameters. */ +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp256r1_p[] = +{ + HN_ULONG_TO_UBASE(0x1F6E5377), HN_ULONG_TO_UBASE(0x2013481D), HN_ULONG_TO_UBASE(0xD5262028), HN_ULONG_TO_UBASE(0x6E3BF623), + HN_ULONG_TO_UBASE(0x9D838D72), HN_ULONG_TO_UBASE(0x3E660A90), HN_ULONG_TO_UBASE(0xA1EEA9BC), HN_ULONG_TO_UBASE(0xA9FB57DB) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp256r1_a[] = +{ + HN_ULONG_TO_UBASE(0xF330B5D9), HN_ULONG_TO_UBASE(0xE94A4B44), HN_ULONG_TO_UBASE(0x26DC5C6C), HN_ULONG_TO_UBASE(0xFB8055C1), + HN_ULONG_TO_UBASE(0x417AFFE7), HN_ULONG_TO_UBASE(0xEEF67530), HN_ULONG_TO_UBASE(0xFC2C3057), HN_ULONG_TO_UBASE(0x7D5A0975) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp256r1_b[] = +{ + HN_ULONG_TO_UBASE(0xFF8C07B6), HN_ULONG_TO_UBASE(0x6BCCDC18), HN_ULONG_TO_UBASE(0x5CF7E1CE), HN_ULONG_TO_UBASE(0x95841629), + HN_ULONG_TO_UBASE(0xBBD77CBF), HN_ULONG_TO_UBASE(0xF330B5D9), HN_ULONG_TO_UBASE(0xE94A4B44), HN_ULONG_TO_UBASE(0x26DC5C6C) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp256r1_gx[] = +{ + HN_ULONG_TO_UBASE(0x9ACE3262), HN_ULONG_TO_UBASE(0x3A4453BD), HN_ULONG_TO_UBASE(0xE3BD23C2), HN_ULONG_TO_UBASE(0xB9DE27E1), + HN_ULONG_TO_UBASE(0xFC81B7AF), HN_ULONG_TO_UBASE(0x2C4B482F), HN_ULONG_TO_UBASE(0xCB7E57CB), HN_ULONG_TO_UBASE(0x8BD2AEB9) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp256r1_gy[] = +{ + HN_ULONG_TO_UBASE(0x2F046997), HN_ULONG_TO_UBASE(0x5C1D54C7), HN_ULONG_TO_UBASE(0x2DED8E54), HN_ULONG_TO_UBASE(0xC2774513), + HN_ULONG_TO_UBASE(0x14611DC9), HN_ULONG_TO_UBASE(0x97F8461A), HN_ULONG_TO_UBASE(0xC3DAC4FD), HN_ULONG_TO_UBASE(0x547EF835) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp256r1_n[] = +{ + HN_ULONG_TO_UBASE(0x974856A7), HN_ULONG_TO_UBASE(0x901E0E82), HN_ULONG_TO_UBASE(0xB561A6F7), HN_ULONG_TO_UBASE(0x8C397AA3), + HN_ULONG_TO_UBASE(0x9D838D71), HN_ULONG_TO_UBASE(0x3E660A90), HN_ULONG_TO_UBASE(0xA1EEA9BC), HN_ULONG_TO_UBASE(0xA9FB57DB) +}; + +/* RFC 5639 brainpoolP384r1 domain parameters. */ +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp384r1_p[] = +{ + HN_ULONG_TO_UBASE(0x3107EC53), HN_ULONG_TO_UBASE(0x87470013), HN_ULONG_TO_UBASE(0x901D1A71), HN_ULONG_TO_UBASE(0xACD3A729), + HN_ULONG_TO_UBASE(0x7FB71123), HN_ULONG_TO_UBASE(0x12B1DA19), HN_ULONG_TO_UBASE(0xED5456B4), HN_ULONG_TO_UBASE(0x152F7109), + HN_ULONG_TO_UBASE(0x50E641DF), HN_ULONG_TO_UBASE(0x0F5D6F7E), HN_ULONG_TO_UBASE(0xA3386D28), HN_ULONG_TO_UBASE(0x8CB91E82) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp384r1_a[] = +{ + HN_ULONG_TO_UBASE(0x22CE2826), HN_ULONG_TO_UBASE(0x04A8C7DD), HN_ULONG_TO_UBASE(0x503AD4EB), HN_ULONG_TO_UBASE(0x8AA5814A), + HN_ULONG_TO_UBASE(0xBA91F90F), HN_ULONG_TO_UBASE(0x139165EF), HN_ULONG_TO_UBASE(0x4FB22787), HN_ULONG_TO_UBASE(0xC2BEA28E), + HN_ULONG_TO_UBASE(0xCE05AFA0), HN_ULONG_TO_UBASE(0x3C72080A), HN_ULONG_TO_UBASE(0x3D8C150C), HN_ULONG_TO_UBASE(0x7BC382C6) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp384r1_b[] = +{ + HN_ULONG_TO_UBASE(0xFA504C11), HN_ULONG_TO_UBASE(0x3AB78696), HN_ULONG_TO_UBASE(0x95DBC994), HN_ULONG_TO_UBASE(0x7CB43902), + HN_ULONG_TO_UBASE(0x3EEB62D5), HN_ULONG_TO_UBASE(0x2E880EA5), HN_ULONG_TO_UBASE(0x07DCD2A6), HN_ULONG_TO_UBASE(0x2FB77DE1), + HN_ULONG_TO_UBASE(0x16F0447C), HN_ULONG_TO_UBASE(0x8B39B554), HN_ULONG_TO_UBASE(0x22CE2826), HN_ULONG_TO_UBASE(0x04A8C7DD) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp384r1_gx[] = +{ + HN_ULONG_TO_UBASE(0x47D4AF1E), HN_ULONG_TO_UBASE(0xEF87B2E2), HN_ULONG_TO_UBASE(0x36D646AA), HN_ULONG_TO_UBASE(0xE826E034), + HN_ULONG_TO_UBASE(0x0CBD10E8), HN_ULONG_TO_UBASE(0xDB7FCAFE), HN_ULONG_TO_UBASE(0x7EF14FE3), HN_ULONG_TO_UBASE(0x8847A3E7), + HN_ULONG_TO_UBASE(0xB7C13F6B), HN_ULONG_TO_UBASE(0xA2A63A81), HN_ULONG_TO_UBASE(0x68CF45FF), HN_ULONG_TO_UBASE(0x1D1C64F0) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp384r1_gy[] = +{ + HN_ULONG_TO_UBASE(0x263C5315), HN_ULONG_TO_UBASE(0x42820341), HN_ULONG_TO_UBASE(0x77918111), HN_ULONG_TO_UBASE(0x0E464621), + HN_ULONG_TO_UBASE(0xF9912928), HN_ULONG_TO_UBASE(0xE19C054F), HN_ULONG_TO_UBASE(0xFEEC5864), HN_ULONG_TO_UBASE(0x62B70B29), + HN_ULONG_TO_UBASE(0x95CFD552), HN_ULONG_TO_UBASE(0x5CB1EB8E), HN_ULONG_TO_UBASE(0x20F9C2A4), HN_ULONG_TO_UBASE(0x8ABE1D75) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp384r1_n[] = +{ + HN_ULONG_TO_UBASE(0xE9046565), HN_ULONG_TO_UBASE(0x3B883202), HN_ULONG_TO_UBASE(0x6B7FC310), HN_ULONG_TO_UBASE(0xCF3AB6AF), + HN_ULONG_TO_UBASE(0xAC0425A7), HN_ULONG_TO_UBASE(0x1F166E6C), HN_ULONG_TO_UBASE(0xED5456B3), HN_ULONG_TO_UBASE(0x152F7109), + HN_ULONG_TO_UBASE(0x50E641DF), HN_ULONG_TO_UBASE(0x0F5D6F7E), HN_ULONG_TO_UBASE(0xA3386D28), HN_ULONG_TO_UBASE(0x8CB91E82) +}; + +/* RFC 5639 brainpoolP512r1 domain parameters. */ +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp512r1_p[] = +{ + HN_ULONG_TO_UBASE(0x583A48F3), HN_ULONG_TO_UBASE(0x28AA6056), HN_ULONG_TO_UBASE(0x2D82C685), HN_ULONG_TO_UBASE(0x2881FF2F), + HN_ULONG_TO_UBASE(0xE6A380E6), HN_ULONG_TO_UBASE(0xAECDA12A), HN_ULONG_TO_UBASE(0x9BC66842), HN_ULONG_TO_UBASE(0x7D4D9B00), + HN_ULONG_TO_UBASE(0x70330871), HN_ULONG_TO_UBASE(0xD6639CCA), HN_ULONG_TO_UBASE(0xB3C9D20E), HN_ULONG_TO_UBASE(0xCB308DB3), + HN_ULONG_TO_UBASE(0x33C9FC07), HN_ULONG_TO_UBASE(0x3FD4E6AE), HN_ULONG_TO_UBASE(0xDBE9C48B), HN_ULONG_TO_UBASE(0xAADD9DB8) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp512r1_a[] = +{ + HN_ULONG_TO_UBASE(0x77FC94CA), HN_ULONG_TO_UBASE(0xE7C1AC4D), HN_ULONG_TO_UBASE(0x2BF2C7B9), HN_ULONG_TO_UBASE(0x7F1117A7), + HN_ULONG_TO_UBASE(0x8B9AC8B5), HN_ULONG_TO_UBASE(0x0A2EF1C9), HN_ULONG_TO_UBASE(0xA8253AA1), HN_ULONG_TO_UBASE(0x2DED5D5A), + HN_ULONG_TO_UBASE(0xEA9863BC), HN_ULONG_TO_UBASE(0xA83441CA), HN_ULONG_TO_UBASE(0x3DF91610), HN_ULONG_TO_UBASE(0x94CBDD8D), + HN_ULONG_TO_UBASE(0xAC234CC5), HN_ULONG_TO_UBASE(0xE2327145), HN_ULONG_TO_UBASE(0x8B603B89), HN_ULONG_TO_UBASE(0x7830A331) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp512r1_b[] = +{ + HN_ULONG_TO_UBASE(0x8016F723), HN_ULONG_TO_UBASE(0x2809BD63), HN_ULONG_TO_UBASE(0x5EBAE5DD), HN_ULONG_TO_UBASE(0x984050B7), + HN_ULONG_TO_UBASE(0xDC083E67), HN_ULONG_TO_UBASE(0x77FC94CA), HN_ULONG_TO_UBASE(0xE7C1AC4D), HN_ULONG_TO_UBASE(0x2BF2C7B9), + HN_ULONG_TO_UBASE(0x7F1117A7), HN_ULONG_TO_UBASE(0x8B9AC8B5), HN_ULONG_TO_UBASE(0x0A2EF1C9), HN_ULONG_TO_UBASE(0xA8253AA1), + HN_ULONG_TO_UBASE(0x2DED5D5A), HN_ULONG_TO_UBASE(0xEA9863BC), HN_ULONG_TO_UBASE(0xA83441CA), HN_ULONG_TO_UBASE(0x3DF91610) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp512r1_gx[] = +{ + HN_ULONG_TO_UBASE(0xBCB9F822), HN_ULONG_TO_UBASE(0x8B352209), HN_ULONG_TO_UBASE(0x406A5E68), HN_ULONG_TO_UBASE(0x7C6D5047), + HN_ULONG_TO_UBASE(0x93B97D5F), HN_ULONG_TO_UBASE(0x50D1687B), HN_ULONG_TO_UBASE(0xE2D0D48D), HN_ULONG_TO_UBASE(0xFF3B1F78), + HN_ULONG_TO_UBASE(0xF4D0098E), HN_ULONG_TO_UBASE(0xB43B62EE), HN_ULONG_TO_UBASE(0xB5D916C1), HN_ULONG_TO_UBASE(0x85ED9F70), + HN_ULONG_TO_UBASE(0x9C4C6A93), HN_ULONG_TO_UBASE(0x5A21322E), HN_ULONG_TO_UBASE(0xD82ED964), HN_ULONG_TO_UBASE(0x81AEE4BD) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp512r1_gy[] = +{ + HN_ULONG_TO_UBASE(0x3AD80892), HN_ULONG_TO_UBASE(0x78CD1E0F), HN_ULONG_TO_UBASE(0xA8F05406), HN_ULONG_TO_UBASE(0xD1CA2B2F), + HN_ULONG_TO_UBASE(0x8A2763AE), HN_ULONG_TO_UBASE(0x5BCA4BD8), HN_ULONG_TO_UBASE(0x4A5F485E), HN_ULONG_TO_UBASE(0xB2DCDE49), + HN_ULONG_TO_UBASE(0x881F8111), HN_ULONG_TO_UBASE(0xA000C55B), HN_ULONG_TO_UBASE(0x24A57B1A), HN_ULONG_TO_UBASE(0xF209F700), + HN_ULONG_TO_UBASE(0xCF7822FD), HN_ULONG_TO_UBASE(0xC0EABFA9), HN_ULONG_TO_UBASE(0x566332EC), HN_ULONG_TO_UBASE(0x7DDE385D) +}; +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpoolp512r1_n[] = +{ + HN_ULONG_TO_UBASE(0x9CA90069), HN_ULONG_TO_UBASE(0xB5879682), HN_ULONG_TO_UBASE(0x085DDADD), HN_ULONG_TO_UBASE(0x1DB1D381), + HN_ULONG_TO_UBASE(0x7FAC1047), HN_ULONG_TO_UBASE(0x41866119), HN_ULONG_TO_UBASE(0x4CA92619), HN_ULONG_TO_UBASE(0x553E5C41), + HN_ULONG_TO_UBASE(0x70330870), HN_ULONG_TO_UBASE(0xD6639CCA), HN_ULONG_TO_UBASE(0xB3C9D20E), HN_ULONG_TO_UBASE(0xCB308DB3), + HN_ULONG_TO_UBASE(0x33C9FC07), HN_ULONG_TO_UBASE(0x3FD4E6AE), HN_ULONG_TO_UBASE(0xDBE9C48B), HN_ULONG_TO_UBASE(0xAADD9DB8) +}; + extern NX_CRYPTO_CONST NX_CRYPTO_EC_FIXED_POINTS _nx_crypto_ec_secp192r1_fixed_points; extern NX_CRYPTO_CONST NX_CRYPTO_EC_FIXED_POINTS _nx_crypto_ec_secp224r1_fixed_points; extern NX_CRYPTO_CONST NX_CRYPTO_EC_FIXED_POINTS _nx_crypto_ec_secp256r1_fixed_points; @@ -685,6 +801,189 @@ NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp521r1 = _nx_crypto_ec_fp_projective_multiple, _nx_crypto_ec_secp521r1_reduce }; +/* Prime-field Brainpool curves use the generic reduction path. */ +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_brainpool_h[] = { HN_ULONG_TO_UBASE(1) }; + +/* RFC 5639 brainpoolp256r1 curve for ECDH and ECDSA. */ +NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_brainpoolp256r1 = +{ + "brainpoolP256r1", + NX_CRYPTO_EC_BRAINPOOLP256r1, + 4, + 256, + { .fp = { + (HN_UBASE *)_nx_crypto_ec_brainpoolp256r1_p, + sizeof(_nx_crypto_ec_brainpoolp256r1_p) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp256r1_p), + (UINT)NX_CRYPTO_FALSE + } }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp256r1_a, + sizeof(_nx_crypto_ec_brainpoolp256r1_a) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp256r1_a), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp256r1_b, + sizeof(_nx_crypto_ec_brainpoolp256r1_b) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp256r1_b), + (UINT)NX_CRYPTO_FALSE + }, + { + NX_CRYPTO_EC_POINT_AFFINE, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp256r1_gx, + sizeof(_nx_crypto_ec_brainpoolp256r1_gx) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp256r1_gx), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp256r1_gy, + sizeof(_nx_crypto_ec_brainpoolp256r1_gy) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp256r1_gy), + (UINT)NX_CRYPTO_FALSE + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u} + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp256r1_n, + sizeof(_nx_crypto_ec_brainpoolp256r1_n) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp256r1_n), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpool_h, + sizeof(_nx_crypto_ec_brainpool_h) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpool_h), + (UINT)NX_CRYPTO_FALSE + }, + NX_CRYPTO_NULL, + _nx_crypto_ec_fp_affine_add, + _nx_crypto_ec_fp_affine_subtract, + _nx_crypto_ec_fp_projective_multiple, + _nx_crypto_ec_fp_reduce +}; + +/* RFC 5639 brainpoolp384r1 curve for ECDH and ECDSA. */ +NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_brainpoolp384r1 = +{ + "brainpoolP384r1", + NX_CRYPTO_EC_BRAINPOOLP384r1, + 4, + 384, + { .fp = { + (HN_UBASE *)_nx_crypto_ec_brainpoolp384r1_p, + sizeof(_nx_crypto_ec_brainpoolp384r1_p) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp384r1_p), + (UINT)NX_CRYPTO_FALSE + } }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp384r1_a, + sizeof(_nx_crypto_ec_brainpoolp384r1_a) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp384r1_a), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp384r1_b, + sizeof(_nx_crypto_ec_brainpoolp384r1_b) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp384r1_b), + (UINT)NX_CRYPTO_FALSE + }, + { + NX_CRYPTO_EC_POINT_AFFINE, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp384r1_gx, + sizeof(_nx_crypto_ec_brainpoolp384r1_gx) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp384r1_gx), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp384r1_gy, + sizeof(_nx_crypto_ec_brainpoolp384r1_gy) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp384r1_gy), + (UINT)NX_CRYPTO_FALSE + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u} + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp384r1_n, + sizeof(_nx_crypto_ec_brainpoolp384r1_n) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp384r1_n), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpool_h, + sizeof(_nx_crypto_ec_brainpool_h) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpool_h), + (UINT)NX_CRYPTO_FALSE + }, + NX_CRYPTO_NULL, + _nx_crypto_ec_fp_affine_add, + _nx_crypto_ec_fp_affine_subtract, + _nx_crypto_ec_fp_projective_multiple, + _nx_crypto_ec_fp_reduce +}; + +/* RFC 5639 brainpoolp512r1 curve for ECDH and ECDSA. */ +NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_brainpoolp512r1 = +{ + "brainpoolP512r1", + NX_CRYPTO_EC_BRAINPOOLP512r1, + 4, + 512, + { .fp = { + (HN_UBASE *)_nx_crypto_ec_brainpoolp512r1_p, + sizeof(_nx_crypto_ec_brainpoolp512r1_p) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp512r1_p), + (UINT)NX_CRYPTO_FALSE + } }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp512r1_a, + sizeof(_nx_crypto_ec_brainpoolp512r1_a) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp512r1_a), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp512r1_b, + sizeof(_nx_crypto_ec_brainpoolp512r1_b) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp512r1_b), + (UINT)NX_CRYPTO_FALSE + }, + { + NX_CRYPTO_EC_POINT_AFFINE, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp512r1_gx, + sizeof(_nx_crypto_ec_brainpoolp512r1_gx) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp512r1_gx), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp512r1_gy, + sizeof(_nx_crypto_ec_brainpoolp512r1_gy) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp512r1_gy), + (UINT)NX_CRYPTO_FALSE + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u} + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpoolp512r1_n, + sizeof(_nx_crypto_ec_brainpoolp512r1_n) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpoolp512r1_n), + (UINT)NX_CRYPTO_FALSE + }, + { + (HN_UBASE *)_nx_crypto_ec_brainpool_h, + sizeof(_nx_crypto_ec_brainpool_h) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_brainpool_h), + (UINT)NX_CRYPTO_FALSE + }, + NX_CRYPTO_NULL, + _nx_crypto_ec_fp_affine_add, + _nx_crypto_ec_fp_affine_subtract, + _nx_crypto_ec_fp_projective_multiple, + _nx_crypto_ec_fp_reduce +}; + #ifndef NX_CRYPTO_SELF_TEST static NX_CRYPTO_CONST NX_CRYPTO_EC *_nx_crypto_ec_named_curves[] = { @@ -692,7 +991,10 @@ static NX_CRYPTO_CONST NX_CRYPTO_EC *_nx_crypto_ec_named_curves[] = &_nx_crypto_ec_secp224r1, &_nx_crypto_ec_secp256r1, &_nx_crypto_ec_secp384r1, - &_nx_crypto_ec_secp521r1 + &_nx_crypto_ec_secp521r1, + &_nx_crypto_ec_brainpoolp256r1, + &_nx_crypto_ec_brainpoolp384r1, + &_nx_crypto_ec_brainpoolp512r1 }; #endif /**************************************************************************/ @@ -1903,7 +2205,6 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_subtract_digit_reduce(NX_CRYPTO_EC *curve, /* Application Code */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_SELF_TEST NX_CRYPTO_KEEP VOID _nx_crypto_ec_fp_reduce(NX_CRYPTO_EC *curve, NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE *scratch) @@ -1912,7 +2213,6 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_fp_reduce(NX_CRYPTO_EC *curve, _nx_crypto_huge_number_modulus(value, &curve -> nx_crypto_ec_field.fp); } -#endif /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -2273,15 +2573,30 @@ UINT buffer_size; NX_CRYPTO_EC_SQUARE_REDUCE(curve, &temp3, &temp2, scratch); NX_CRYPTO_EC_SHIFT_LEFT_REDUCE(curve, &temp2, 3, scratch); - /* C = 3 * (X1 - Z1 ^ 2) * (X1 + Z1 ^ 2) */ + /* C = 3 * X1^2 + a * Z1^4; use the shorter form for a = -3 curves. */ NX_CRYPTO_EC_SQUARE_REDUCE(curve, &projective_point -> nx_crypto_ec_point_z, &temp3, scratch); - NX_CRYPTO_HUGE_NUMBER_COPY(&temp4, &projective_point -> nx_crypto_ec_point_x); - NX_CRYPTO_HUGE_NUMBER_COPY(&temp5, &projective_point -> nx_crypto_ec_point_x); - _nx_crypto_ec_subtract_reduce(curve, &temp4, &temp3, scratch); - _nx_crypto_ec_add_reduce(curve, &temp5, &temp3, scratch); - NX_CRYPTO_EC_MULTIPLE_REDUCE(curve, &temp4, &temp5, &temp3, scratch); - NX_CRYPTO_EC_MULTIPLE_DIGIT_REDUCE(curve, &temp3, 3, &temp4, scratch); + if ((curve -> nx_crypto_ec_id >= NX_CRYPTO_EC_BRAINPOOLP256r1) && + (curve -> nx_crypto_ec_id <= NX_CRYPTO_EC_BRAINPOOLP512r1)) + { + NX_CRYPTO_EC_SQUARE_REDUCE(curve, &temp3, &temp4, scratch); + NX_CRYPTO_EC_MULTIPLE_REDUCE(curve, &temp4, &curve -> nx_crypto_ec_a, + &temp3, scratch); + NX_CRYPTO_EC_SQUARE_REDUCE(curve, &projective_point -> nx_crypto_ec_point_x, + &temp4, scratch); + NX_CRYPTO_EC_MULTIPLE_DIGIT_REDUCE(curve, &temp4, 3, &temp5, scratch); + _nx_crypto_ec_add_reduce(curve, &temp5, &temp3, scratch); + NX_CRYPTO_HUGE_NUMBER_COPY(&temp4, &temp5); + } + else + { + NX_CRYPTO_HUGE_NUMBER_COPY(&temp4, &projective_point -> nx_crypto_ec_point_x); + NX_CRYPTO_HUGE_NUMBER_COPY(&temp5, &projective_point -> nx_crypto_ec_point_x); + _nx_crypto_ec_subtract_reduce(curve, &temp4, &temp3, scratch); + _nx_crypto_ec_add_reduce(curve, &temp5, &temp3, scratch); + NX_CRYPTO_EC_MULTIPLE_REDUCE(curve, &temp4, &temp5, &temp3, scratch); + NX_CRYPTO_EC_MULTIPLE_DIGIT_REDUCE(curve, &temp3, 3, &temp4, scratch); + } /* Z3 = 2 * Y1 * Z1 */ NX_CRYPTO_EC_MULTIPLE_REDUCE(curve, &projective_point -> nx_crypto_ec_point_y, @@ -3931,6 +4246,57 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ec_secp521r1_operation(UINT op, return(NX_CRYPTO_SUCCESS); } +/* Return the RFC 5639 curve selected by the Brainpool crypto method. */ +NX_CRYPTO_KEEP UINT _nx_crypto_method_ec_brainpool_operation(UINT op, + VOID *handle, + struct NX_CRYPTO_METHOD_STRUCT *method, + UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits, + UCHAR *input, ULONG input_length_in_byte, + UCHAR *iv_ptr, + UCHAR *output, ULONG output_length_in_byte, + VOID *crypto_metadata, ULONG crypto_metadata_size, + VOID *packet_ptr, + VOID (*nx_crypto_hw_process_callback)(VOID *, UINT)) +{ +NX_CRYPTO_EC *curve; + + NX_CRYPTO_PARAMETER_NOT_USED(handle); + NX_CRYPTO_PARAMETER_NOT_USED(key); + NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits); + NX_CRYPTO_PARAMETER_NOT_USED(input); + NX_CRYPTO_PARAMETER_NOT_USED(input_length_in_byte); + NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr); + NX_CRYPTO_PARAMETER_NOT_USED(output_length_in_byte); + NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata); + NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata_size); + NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr); + NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback); + + if ((op != NX_CRYPTO_EC_CURVE_GET) || (method == NX_CRYPTO_NULL) || + (output == NX_CRYPTO_NULL)) + { + return(NX_CRYPTO_NOT_SUCCESSFUL); + } + + switch (method -> nx_crypto_algorithm) + { + case NX_CRYPTO_EC_BRAINPOOLP256r1: + curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_brainpoolp256r1; + break; + case NX_CRYPTO_EC_BRAINPOOLP384r1: + curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_brainpoolp384r1; + break; + case NX_CRYPTO_EC_BRAINPOOLP512r1: + curve = (NX_CRYPTO_EC *)&_nx_crypto_ec_brainpoolp512r1; + break; + default: + return(NX_CRYPTO_NOT_SUCCESSFUL); + } + + *((NX_CRYPTO_EC **)output) = curve; + return(NX_CRYPTO_SUCCESS); +} + /**************************************************************************/ /* */ diff --git a/crypto_libraries/src/nx_crypto_generic_ciphersuites.c b/crypto_libraries/src/nx_crypto_generic_ciphersuites.c index fcad19eaa..0e47e7ccc 100644 --- a/crypto_libraries/src/nx_crypto_generic_ciphersuites.c +++ b/crypto_libraries/src/nx_crypto_generic_ciphersuites.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -80,6 +82,9 @@ extern NX_CRYPTO_METHOD crypto_method_auth_psk; extern NX_CRYPTO_METHOD crypto_method_ec_secp256; extern NX_CRYPTO_METHOD crypto_method_ec_secp384; extern NX_CRYPTO_METHOD crypto_method_ec_secp521; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp384; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp512; extern NX_CRYPTO_METHOD crypto_method_ec_x25519; extern NX_CRYPTO_METHOD crypto_method_ec_x448; extern NX_CRYPTO_METHOD crypto_method_md5; @@ -294,6 +299,9 @@ const USHORT nx_crypto_ecc_supported_groups[] = #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ (USHORT)NX_CRYPTO_EC_SECP384R1, (USHORT)NX_CRYPTO_EC_SECP521R1, + (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1, + (USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1, + (USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1, }; const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[] = @@ -305,6 +313,9 @@ const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[] = #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ &crypto_method_ec_secp384, &crypto_method_ec_secp521, + &crypto_method_ec_brainpoolp256, + &crypto_method_ec_brainpoolp384, + &crypto_method_ec_brainpoolp512, }; const UINT nx_crypto_ecc_supported_groups_size = sizeof(nx_crypto_ecc_supported_groups) / sizeof(USHORT); @@ -616,6 +627,9 @@ const NX_CRYPTO_METHOD *supported_crypto[] = #endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ &crypto_method_ec_secp384, &crypto_method_ec_secp521, + &crypto_method_ec_brainpoolp256, + &crypto_method_ec_brainpoolp384, + &crypto_method_ec_brainpoolp512, }; const UINT supported_crypto_size = sizeof(supported_crypto) / sizeof(NX_CRYPTO_METHOD*); @@ -649,4 +663,3 @@ const UINT ciphersuite_map_size = sizeof(ciphersuite_map) / sizeof(NX_CRYPTO_CIP - diff --git a/crypto_libraries/src/nx_crypto_methods.c b/crypto_libraries/src/nx_crypto_methods.c index c1304c441..8f9aaf905 100644 --- a/crypto_libraries/src/nx_crypto_methods.c +++ b/crypto_libraries/src/nx_crypto_methods.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -505,6 +507,27 @@ NX_CRYPTO_METHOD crypto_method_ec_secp521 = _nx_crypto_method_ec_secp521r1_operation, /* Operation */ }; +/* Declare the Brainpool P256r1 curve method. */ +NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256 = +{ + NX_CRYPTO_EC_BRAINPOOLP256r1, 256, 0, 0, 0, 0, + NX_CRYPTO_NULL, NX_CRYPTO_NULL, _nx_crypto_method_ec_brainpool_operation +}; + +/* Declare the Brainpool P384r1 curve method. */ +NX_CRYPTO_METHOD crypto_method_ec_brainpoolp384 = +{ + NX_CRYPTO_EC_BRAINPOOLP384r1, 384, 0, 0, 0, 0, + NX_CRYPTO_NULL, NX_CRYPTO_NULL, _nx_crypto_method_ec_brainpool_operation +}; + +/* Declare the Brainpool P512r1 curve method. */ +NX_CRYPTO_METHOD crypto_method_ec_brainpoolp512 = +{ + NX_CRYPTO_EC_BRAINPOOLP512r1, 512, 0, 0, 0, 0, + NX_CRYPTO_NULL, NX_CRYPTO_NULL, _nx_crypto_method_ec_brainpool_operation +}; + #ifdef NX_CRYPTO_ENABLE_CURVE25519_448 /* Declare a placeholder for EC x25519. */ diff --git a/nx_secure/inc/nx_secure_tls.h b/nx_secure/inc/nx_secure_tls.h index 912a6d38f..91396c372 100644 --- a/nx_secure/inc/nx_secure_tls.h +++ b/nx_secure/inc/nx_secure_tls.h @@ -560,6 +560,9 @@ typedef struct NX_SECURE_VERSIONS_LIST_STRUCT #define NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256 (((UINT)NX_SECURE_TLS_HASH_ALGORITHM_SHA256 << 8) + (UINT)NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA) #define NX_SECURE_TLS_SIGNATURE_ECDSA_SHA384 (((UINT)NX_SECURE_TLS_HASH_ALGORITHM_SHA384 << 8) + (UINT)NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA) #define NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512 (((UINT)NX_SECURE_TLS_HASH_ALGORITHM_SHA512 << 8) + (UINT)NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA) +#define NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256 0x081Au +#define NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384 0x081Bu +#define NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512 0x081Cu /* Session key generation and assignment constants. */ @@ -1636,6 +1639,8 @@ UINT _nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciph VOID *public_auth_metadata, ULONG public_auth_metadata_size); UINT _nx_secure_tls_find_curve_method(NX_SECURE_TLS_ECC *tls_ecc, USHORT named_curve, const NX_CRYPTO_METHOD **curve_method, UINT *curve_priority); +USHORT _nx_secure_tls_brainpool_group_to_wire(USHORT named_curve); +USHORT _nx_secure_tls_brainpool_group_from_wire(USHORT named_group); UINT _nx_secure_tls_proc_clienthello_sec_sa_extension(NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_TLS_HELLO_EXTENSION *exts, UINT num_extensions, diff --git a/nx_secure/inc/nx_secure_x509.h b/nx_secure/inc/nx_secure_x509.h index 6029375ae..afb87062e 100644 --- a/nx_secure/inc/nx_secure_x509.h +++ b/nx_secure/inc/nx_secure_x509.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -367,6 +369,9 @@ extern "C" { #define NX_SECURE_TLS_X509_EC_SECP256R1 0x00060017 #define NX_SECURE_TLS_X509_EC_SECP384R1 0x00060018 #define NX_SECURE_TLS_X509_EC_SECP521R1 0x00060019 +#define NX_SECURE_TLS_X509_EC_BRAINPOOLP256R1 0x0006001A +#define NX_SECURE_TLS_X509_EC_BRAINPOOLP384R1 0x0006001B +#define NX_SECURE_TLS_X509_EC_BRAINPOOLP512R1 0x0006001C /* Bitfield mappings for Distinguished name comparison. When using nx_secure_x509_distinguished_name_compare, these values are used for the "compare_fields" parameter - bitwise OR these values together to compare @@ -1045,4 +1050,3 @@ UINT nx_secure_x509_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate, #endif #endif /* SRC_NX_SECURE_X509_H_ */ - diff --git a/nx_secure/src/nx_secure_tls_find_curve_method.c b/nx_secure/src/nx_secure_tls_find_curve_method.c index eb1057fdd..b6b174b9e 100644 --- a/nx_secure/src/nx_secure_tls_find_curve_method.c +++ b/nx_secure/src/nx_secure_tls_find_curve_method.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -26,6 +28,27 @@ #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +/* Map RFC 7027 Brainpool curve IDs to their RFC 8734 TLS 1.3 group IDs. */ +USHORT _nx_secure_tls_brainpool_group_to_wire(USHORT named_curve) +{ + if ((named_curve >= (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1) && + (named_curve <= (USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1)) + { + return((USHORT)(named_curve + 5u)); + } + return(named_curve); +} + +/* Map RFC 8734 TLS 1.3 group IDs to the corresponding crypto curve IDs. */ +USHORT _nx_secure_tls_brainpool_group_from_wire(USHORT named_group) +{ + if ((named_group >= 0x001Fu) && (named_group <= 0x0021u)) + { + return((USHORT)(named_group - 5u)); + } + return(named_group); +} + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/nx_secure/src/nx_secure_tls_process_certificate_request.c b/nx_secure/src/nx_secure_tls_process_certificate_request.c index ac7f1c060..161fd3a3b 100644 --- a/nx_secure/src/nx_secure_tls_process_certificate_request.c +++ b/nx_secure/src/nx_secure_tls_process_certificate_request.c @@ -150,6 +150,15 @@ UINT extension_type; case NX_CRYPTO_EC_SECP521R1: expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512; break; + case NX_CRYPTO_EC_BRAINPOOLP256r1: + expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256; + break; + case NX_CRYPTO_EC_BRAINPOOLP384r1: + expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384; + break; + case NX_CRYPTO_EC_BRAINPOOLP512r1: + expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512; + break; default: return(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG); } @@ -337,4 +346,3 @@ UINT extension_type; return(NX_NOT_SUPPORTED); #endif /* NX_SECURE_DISABLE_X509 */ } - diff --git a/nx_secure/src/nx_secure_tls_process_certificate_verify.c b/nx_secure/src/nx_secure_tls_process_certificate_verify.c index 1fcbaa928..b408855ee 100644 --- a/nx_secure/src/nx_secure_tls_process_certificate_verify.c +++ b/nx_secure/src/nx_secure_tls_process_certificate_verify.c @@ -110,6 +110,9 @@ UCHAR *pss_scratch; #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE const NX_CRYPTO_METHOD *curve_method_cert; NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +UINT brainpool_expected_curve = 0u; +#endif #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ /* @@ -184,6 +187,24 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512: signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256: + signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256; +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + brainpool_expected_curve = NX_CRYPTO_EC_BRAINPOOLP256r1; +#endif + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384: + signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384; +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + brainpool_expected_curve = NX_CRYPTO_EC_BRAINPOOLP384r1; +#endif + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512: + signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + brainpool_expected_curve = NX_CRYPTO_EC_BRAINPOOLP512r1; +#endif + break; case 0x0804u: /* rsa_pss_rsae_sha256 */ signature_algorithm = NX_SECURE_TLS_X509_TYPE_RSA_SHA_256; break; @@ -824,6 +845,17 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; ec_pubkey = &client_certificate -> nx_secure_x509_public_key.ec_public_key; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if (tls_session -> nx_secure_tls_1_3 && + ((brainpool_expected_curve != 0u) || + ((ec_pubkey -> nx_secure_ec_named_curve >= NX_CRYPTO_EC_BRAINPOOLP256r1) && + (ec_pubkey -> nx_secure_ec_named_curve <= NX_CRYPTO_EC_BRAINPOOLP512r1))) && + (brainpool_expected_curve != ec_pubkey -> nx_secure_ec_named_curve)) + { + return(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG); + } +#endif + /* Find out which named curve the remote certificate is using. */ status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); @@ -950,4 +982,3 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; return(NX_NOT_SUPPORTED); #endif } - diff --git a/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c index ef5e70fa3..5be3ec854 100644 --- a/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c +++ b/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -533,6 +535,12 @@ UCHAR expected_signature = 0; for (j = 0; j < groups_len; j += 2) { group = (USHORT)((groups[j] << 8) + groups[j + 1]); +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if (tls_session -> nx_secure_tls_1_3) + { + group = _nx_secure_tls_brainpool_group_from_wire(group); + } +#endif status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, group, &curve_method, &new_curve_priority); @@ -780,6 +788,7 @@ NX_SECURE_TLS_ECC *ecc_info; /* Get the key group. */ key_group = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]); + key_group = _nx_secure_tls_brainpool_group_from_wire(key_group); offset = (USHORT)(offset + 2); /* Get the key length. */ @@ -1116,6 +1125,15 @@ NX_SECURE_X509_CERT *local_certificate = NX_NULL; case NX_CRYPTO_EC_SECP521R1: expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512; break; + case NX_CRYPTO_EC_BRAINPOOLP256r1: + expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256; + break; + case NX_CRYPTO_EC_BRAINPOOLP384r1: + expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384; + break; + case NX_CRYPTO_EC_BRAINPOOLP512r1: + expected_sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512; + break; default: return; } @@ -1216,6 +1234,15 @@ VOID _nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm, USHORT case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512: *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256: + *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256; + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384: + *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384; + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512: + *signature_algorithm_id = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; + break; /* RSASSA-PSS schemes (RFC 8446 ยง4.2.3). Mapped to the same internal IDs as PKCS#1 v1.5 so the certificate cipher table lookup finds the (RSA, SHA-x) pair. PSS-vs-PKCS1 dispatch is done at signature-verify time. */ @@ -1571,6 +1598,3 @@ NX_SECURE_TLS_PSK_STORE *psk_store; return(NX_SUCCESS); } #endif - - - diff --git a/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c b/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c index d09a85ddd..6ef394358 100644 --- a/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c +++ b/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -805,6 +807,7 @@ NX_SECURE_TLS_ECC *ecc_info; /* Check the key group. */ key_group = (USHORT)((ULONG)key_group | NX_CRYPTO_EC_MASK); + key_group = _nx_secure_tls_brainpool_group_from_wire(key_group); /* Loop through all supported ECC curves in this session. */ diff --git a/nx_secure/src/nx_secure_tls_send_certificate_request.c b/nx_secure/src/nx_secure_tls_send_certificate_request.c index 1a33b4d8b..9d8c15616 100644 --- a/nx_secure/src/nx_secure_tls_send_certificate_request.c +++ b/nx_secure/src/nx_secure_tls_send_certificate_request.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -177,6 +179,15 @@ UINT sign_alg; case (NX_CRYPTO_EC_SECP521R1 & 0x00FF): sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512; break; + case (NX_CRYPTO_EC_BRAINPOOLP256r1 & 0x00FF): + sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256; + break; + case (NX_CRYPTO_EC_BRAINPOOLP384r1 & 0x00FF): + sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384; + break; + case (NX_CRYPTO_EC_BRAINPOOLP512r1 & 0x00FF): + sign_alg = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512; + break; default: continue; } @@ -265,4 +276,3 @@ UINT sign_alg; return(NX_SUCCESS); } - diff --git a/nx_secure/src/nx_secure_tls_send_certificate_verify.c b/nx_secure/src/nx_secure_tls_send_certificate_verify.c index f9eb41226..f50e93f7e 100644 --- a/nx_secure/src/nx_secure_tls_send_certificate_verify.c +++ b/nx_secure/src/nx_secure_tls_send_certificate_verify.c @@ -123,6 +123,9 @@ const CHAR client_context[] = "TLS 1.3, client CertificateVerify\0"; /* Includes #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE const NX_CRYPTO_METHOD *curve_method_cert; NX_SECURE_EC_PRIVATE_KEY *ec_privkey; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +UINT brainpool_expected_curve = 0u; +#endif NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; NX_SECURE_EC_PRIVATE_KEY ec_hardware_privkey; NX_CRYPTO_EXTENDED_OUTPUT extended_output; @@ -211,6 +214,15 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512: signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256: + signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256; + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384: + signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384; + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512: + signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; + break; case NX_SECURE_TLS_SIGNATURE_RSA_PSS_RSAE_SHA256: signature_algorithm = NX_SECURE_TLS_X509_TYPE_RSA_SHA_256; break; @@ -850,6 +862,7 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; { data_size = handshake_hash_length; current_buffer[length] = (UCHAR)((tls_session -> nx_secure_tls_signature_algorithm) >> 8); + current_buffer[length + 1] = (UCHAR)(tls_session -> nx_secure_tls_signature_algorithm); } else #endif @@ -857,8 +870,8 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; /* Hash size is SHA-256 hash size (32). */ data_size = 32; current_buffer[length] = NX_SECURE_TLS_HASH_ALGORITHM_SHA256; /* We only support SHA-256 right now. */ + current_buffer[length + 1] = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; } - current_buffer[length + 1] = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; /* ECDSA */ length += 2; } #endif @@ -894,6 +907,33 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; { ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key; } + +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if (tls_session -> nx_secure_tls_1_3) + { + switch (tls_session -> nx_secure_tls_signature_algorithm) + { + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256: + brainpool_expected_curve = NX_CRYPTO_EC_BRAINPOOLP256r1; + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384: + brainpool_expected_curve = NX_CRYPTO_EC_BRAINPOOLP384r1; + break; + case NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512: + brainpool_expected_curve = NX_CRYPTO_EC_BRAINPOOLP512r1; + break; + default: + break; + } + if (((brainpool_expected_curve != 0u) || + ((ec_privkey -> nx_secure_ec_named_curve >= NX_CRYPTO_EC_BRAINPOOLP256r1) && + (ec_privkey -> nx_secure_ec_named_curve <= NX_CRYPTO_EC_BRAINPOOLP512r1))) && + (brainpool_expected_curve != ec_privkey -> nx_secure_ec_named_curve)) + { + return(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG); + } + } +#endif ec_pubkey = &local_certificate -> nx_secure_x509_public_key.ec_public_key; /* Find out which named curve the local certificate is using. */ @@ -1018,4 +1058,3 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; return(NX_NOT_SUPPORTED); #endif } - diff --git a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c index c4ec02547..4fc0f3bb7 100644 --- a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c +++ b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c @@ -30,6 +30,47 @@ #ifndef NX_SECURE_DISABLE_X509 #define NX_SECURE_TLS_SIGNATURE_ALGORITHMS_LIST_MAX_LENGTH (0xFFFFu - 6u) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) +/* Select the TLS 1.3 signature scheme for a supported Brainpool curve. */ +static USHORT _nx_secure_tls_brainpool_signature_scheme(NX_SECURE_TLS_SESSION *tls_session, + USHORT named_curve) +{ + UINT i; + USHORT x509_type; + USHORT signature_scheme; + + switch (named_curve) + { + case (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1: + x509_type = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256; + signature_scheme = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256; + break; + case (USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1: + x509_type = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384; + signature_scheme = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384; + break; + case (USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1: + x509_type = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512; + signature_scheme = NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512; + break; + default: + return(0u); + } + + for (i = 0; i < tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table_size; i++) + { + NX_SECURE_X509_CRYPTO *method = &tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table[i]; + if ((method -> nx_secure_x509_crypto_identifier == x509_type) && + (method -> nx_secure_x509_public_cipher_method != NX_NULL) && + (method -> nx_secure_x509_public_cipher_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)) + { + return(signature_scheme); + } + } + return(0u); +} +#endif + static VOID _nx_secure_tls_get_signature_algorithm(NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_X509_CRYPTO *crypto_method, USHORT *signature_algorithm); @@ -351,6 +392,21 @@ NX_SECURE_X509_CRYPTO *cipher_table; } } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) + if (tls_session -> nx_secure_tls_1_3) + { + for (i = 0; i < tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count; i++) + { + signature_algorithm = _nx_secure_tls_brainpool_signature_scheme(tls_session, + tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups[i]); + if (signature_algorithm != 0u) + { + signature_algorithms_length += 2u; + } + } + } +#endif + if ((signature_algorithms_length > NX_SECURE_TLS_SIGNATURE_ALGORITHMS_LIST_MAX_LENGTH) || (*packet_offset > available_size) || ((available_size - *packet_offset) < (6u + signature_algorithms_length))) @@ -396,6 +452,23 @@ NX_SECURE_X509_CRYPTO *cipher_table; #endif } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) + if (tls_session -> nx_secure_tls_1_3) + { + for (i = 0; i < tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count; i++) + { + signature_algorithm = _nx_secure_tls_brainpool_signature_scheme(tls_session, + tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups[i]); + if (signature_algorithm != 0u) + { + packet_buffer[offset] = (UCHAR)(signature_algorithm >> 8); + packet_buffer[offset + 1] = (UCHAR)signature_algorithm; + offset += 2; + } + } + } +#endif + ext = NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS; /* Signature algorithms */ ext_len = (USHORT)(ext_len + 2); @@ -851,6 +924,7 @@ USHORT named_curve; /* Get the curve for the key we are sending. */ named_curve = (USHORT)ecdhe_data->nx_secure_tls_ecdhe_named_curve; + named_curve = _nx_secure_tls_brainpool_group_to_wire(named_curve); /* Key length will differ for each curve. For p256, 32 octets per coordinate, plus the "legacy_form" byte. */ key_length = ecdhe_data->nx_secure_tls_ecdhe_public_key_length; @@ -1758,8 +1832,15 @@ NX_SECURE_TLS_ECC *ecc_info; for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++) { - packet_buffer[offset] = (UCHAR)((ecc_info -> nx_secure_tls_ecc_supported_groups[i] & 0xFF00) >> 8); - packet_buffer[offset + 1] = (UCHAR)(ecc_info -> nx_secure_tls_ecc_supported_groups[i] & 0x00FF); + USHORT named_group = ecc_info -> nx_secure_tls_ecc_supported_groups[i]; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if (tls_session -> nx_secure_tls_1_3) + { + named_group = _nx_secure_tls_brainpool_group_to_wire(named_group); + } +#endif + packet_buffer[offset] = (UCHAR)((named_group & 0xFF00) >> 8); + packet_buffer[offset + 1] = (UCHAR)(named_group & 0x00FF); offset += 2; } diff --git a/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c b/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c index c6132beb9..52d279e1e 100644 --- a/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c +++ b/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -603,6 +605,7 @@ USHORT named_curve; i = tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected; ecdhe_data = &(tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i]); named_curve = (USHORT)(ecdhe_data -> nx_secure_tls_ecdhe_named_curve); + named_curve = _nx_secure_tls_brainpool_group_to_wire(named_curve); if (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY) { @@ -825,4 +828,3 @@ USHORT ext; } #endif - diff --git a/nx_secure/src/nx_secure_x509_oid_parse.c b/nx_secure/src/nx_secure_x509_oid_parse.c index c063a387e..e04f5a8fb 100644 --- a/nx_secure/src/nx_secure_x509_oid_parse.c +++ b/nx_secure/src/nx_secure_x509_oid_parse.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -136,6 +138,9 @@ static const UCHAR NX_SECURE_X509_OID_SECP224R1[] = {0x2B, 0x81, 0x04, 0x static const UCHAR NX_SECURE_X509_OID_SECP256R1[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}; /* ISO.USA.10045.3.1.7 - Named curve: secp256r1. */ static const UCHAR NX_SECURE_X509_OID_SECP384R1[] = {0x2B, 0x81, 0x04, 0x00, 0x22}; /* ISO.Identified Organization.Certicom.curve.34 - Named curve: secp384r1. */ static const UCHAR NX_SECURE_X509_OID_SECP521R1[] = {0x2B, 0x81, 0x04, 0x00, 0x23}; /* ISO.Identified Organization.Certicom.curve.35 - Named curve: secp521r1. */ +static const UCHAR NX_SECURE_X509_OID_BRAINPOOLP256R1[] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}; /* RFC 5639 brainpoolP256r1. */ +static const UCHAR NX_SECURE_X509_OID_BRAINPOOLP384R1[] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}; /* RFC 5639 brainpoolP384r1. */ +static const UCHAR NX_SECURE_X509_OID_BRAINPOOLP512R1[] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}; /* RFC 5639 brainpoolP512r1. */ static const UCHAR NX_SECURE_X509_OID_ECDSA_SHA1[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01}; /* ISO.USA.10045.4.1 - ecdsa-with-SHA1. */ static const UCHAR NX_SECURE_X509_OID_ECDSA_SHA224[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01}; /* ISO.USA.10045.4.3.1 - ecdsa-with-SHA224. */ static const UCHAR NX_SECURE_X509_OID_ECDSA_SHA256[] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02}; /* ISO.USA.10045.4.3.2 - ecdsa-with-SHA256. */ @@ -216,6 +221,9 @@ NX_SECURE_X509_OID_MAP _nx_secure_x509_oid_map[] = {NX_SECURE_TLS_X509_EC_SECP256R1 , NX_SECURE_X509_OID_SECP256R1 , sizeof(NX_SECURE_X509_OID_SECP256R1)}, {NX_SECURE_TLS_X509_EC_SECP384R1 , NX_SECURE_X509_OID_SECP384R1 , sizeof(NX_SECURE_X509_OID_SECP384R1)}, {NX_SECURE_TLS_X509_EC_SECP521R1 , NX_SECURE_X509_OID_SECP521R1 , sizeof(NX_SECURE_X509_OID_SECP521R1)}, + {NX_SECURE_TLS_X509_EC_BRAINPOOLP256R1 , NX_SECURE_X509_OID_BRAINPOOLP256R1 , sizeof(NX_SECURE_X509_OID_BRAINPOOLP256R1)}, + {NX_SECURE_TLS_X509_EC_BRAINPOOLP384R1 , NX_SECURE_X509_OID_BRAINPOOLP384R1 , sizeof(NX_SECURE_X509_OID_BRAINPOOLP384R1)}, + {NX_SECURE_TLS_X509_EC_BRAINPOOLP512R1 , NX_SECURE_X509_OID_BRAINPOOLP512R1 , sizeof(NX_SECURE_X509_OID_BRAINPOOLP512R1)}, {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_1 , NX_SECURE_X509_OID_ECDSA_SHA1 , sizeof(NX_SECURE_X509_OID_ECDSA_SHA1)}, {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_224 , NX_SECURE_X509_OID_ECDSA_SHA224 , sizeof(NX_SECURE_X509_OID_ECDSA_SHA224)}, {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256 , NX_SECURE_X509_OID_ECDSA_SHA256 , sizeof(NX_SECURE_X509_OID_ECDSA_SHA256)}, @@ -296,4 +304,3 @@ UINT i; *oid_value = NX_SECURE_TLS_X509_TYPE_UNKNOWN; } - diff --git a/test/cmake/crypto/regression/CMakeLists.txt b/test/cmake/crypto/regression/CMakeLists.txt index e46ebb4b9..dd7b9b28c 100644 --- a/test/cmake/crypto/regression/CMakeLists.txt +++ b/test/cmake/crypto/regression/CMakeLists.txt @@ -34,6 +34,7 @@ set(crypto_test_cases ${SOURCE_DIR}/nx_secure_ecdh_error_checking_test.c ${SOURCE_DIR}/nx_secure_ecdh_self_test.c ${SOURCE_DIR}/nx_secure_ecdsa_test.c + ${SOURCE_DIR}/nx_secure_brainpool_test.c ${SOURCE_DIR}/nx_secure_ecdsa_error_checking_test.c ${SOURCE_DIR}/nx_secure_ecjpake_self_test.c ${SOURCE_DIR}/nx_secure_huge_number_test.c @@ -55,7 +56,7 @@ endif() target_include_directories(test_utility PUBLIC ${SOURCE_DIR}/test) target_compile_definitions(test_utility PUBLIC BATCH_TEST CTEST) -if(("${CMAKE_BUILD_TYPE}" STREQUAL "fips_build_coverage") OR ("${CMAKE_BUILD_TYPE}" STREQUAL "standalone_build")) +if("${CMAKE_BUILD_TYPE}" STREQUAL "fips_build_coverage") target_link_libraries(test_utility PUBLIC crypto) endif() diff --git a/test/regression/nx_secure_test/brainpool_certs.c b/test/regression/nx_secure_test/brainpool_certs.c new file mode 100644 index 000000000..197eac0be --- /dev/null +++ b/test/regression/nx_secure_test/brainpool_certs.c @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + ***************************************************************************/ + +/* DER test certificates use the RFC 5639 brainpoolP256r1 curve. */ +static UCHAR brainpool_root_der[] = { + 0x30, 0x82, 0x01, 0xa1, 0x30, 0x82, 0x01, 0x48, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x02, 0x85, 0x49, 0xb8, 0x01, 0xcb, 0x51, 0x9c, 0x5c, + 0xfc, 0x84, 0x37, 0x3b, 0x7f, 0x06, 0x98, 0xa3, 0x84, 0xfe, 0xfc, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, + 0x1e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, + 0x42, 0x72, 0x61, 0x69, 0x6e, 0x70, 0x6f, 0x6f, 0x6c, 0x20, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, + 0x36, 0x30, 0x39, 0x32, 0x38, 0x32, 0x30, 0x30, 0x39, 0x34, 0x38, 0x5a, + 0x17, 0x0d, 0x34, 0x36, 0x30, 0x39, 0x32, 0x33, 0x32, 0x30, 0x30, 0x39, + 0x34, 0x38, 0x5a, 0x30, 0x1e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x13, 0x42, 0x72, 0x61, 0x69, 0x6e, 0x70, 0x6f, 0x6f, + 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, + 0x5a, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, + 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x3a, 0xa8, 0x08, 0x1b, 0xc5, 0xd0, 0x2a, 0x94, 0xe8, + 0x40, 0x29, 0xd3, 0x1d, 0x4d, 0x31, 0xdd, 0xed, 0x68, 0x5d, 0xe4, 0x96, + 0x91, 0xb5, 0x44, 0x23, 0xaa, 0xab, 0x2b, 0x25, 0xaf, 0x50, 0x8c, 0x80, + 0xc7, 0x5d, 0xf3, 0x88, 0xb7, 0x47, 0x74, 0xe7, 0x9b, 0x14, 0x8b, 0x39, + 0xaa, 0xa5, 0x7e, 0x44, 0x7e, 0xdc, 0x3d, 0x12, 0xa3, 0xe9, 0xeb, 0x98, + 0x57, 0x7a, 0xdc, 0x42, 0xeb, 0xbb, 0xb2, 0xa3, 0x63, 0x30, 0x61, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfb, 0xe0, + 0xaf, 0x37, 0xf0, 0x64, 0x59, 0x03, 0xef, 0x21, 0x7e, 0x33, 0x5a, 0xc8, + 0xf8, 0x7c, 0x38, 0x2f, 0x33, 0xc9, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, + 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfb, 0xe0, 0xaf, 0x37, 0xf0, + 0x64, 0x59, 0x03, 0xef, 0x21, 0x7e, 0x33, 0x5a, 0xc8, 0xf8, 0x7c, 0x38, + 0x2f, 0x33, 0xc9, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, + 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, + 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, + 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x4e, 0x4a, 0xf1, 0xee, 0x8b, + 0x94, 0x25, 0x3f, 0xeb, 0x69, 0xf0, 0x0d, 0x19, 0x8a, 0x9b, 0xe2, 0x17, + 0x86, 0xca, 0x04, 0xe9, 0x81, 0xee, 0x4c, 0x94, 0xea, 0x14, 0x7c, 0x63, + 0xc2, 0x5c, 0xec, 0x02, 0x20, 0x01, 0xe2, 0xdb, 0x48, 0x8a, 0xbf, 0x0c, + 0x38, 0xd6, 0x50, 0x54, 0x69, 0xab, 0xf8, 0xbe, 0xcf, 0x09, 0x0f, 0x91, + 0x47, 0xff, 0x99, 0xb2, 0x44, 0x55, 0x20, 0x47, 0xd2, 0x56, 0x80, 0xba, + 0x4b, +}; + +static UCHAR brainpool_server_der[] = { + 0x30, 0x82, 0x01, 0xc1, 0x30, 0x82, 0x01, 0x68, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x14, 0x61, 0x86, 0x04, 0x63, 0xb6, 0x79, 0x20, 0xa0, 0x62, + 0x5e, 0x23, 0xb6, 0xac, 0x54, 0x87, 0x5d, 0xba, 0x3c, 0x68, 0xca, 0x30, + 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, + 0x1e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x13, + 0x42, 0x72, 0x61, 0x69, 0x6e, 0x70, 0x6f, 0x6f, 0x6c, 0x20, 0x54, 0x65, + 0x73, 0x74, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, + 0x36, 0x30, 0x39, 0x32, 0x38, 0x32, 0x30, 0x30, 0x39, 0x34, 0x38, 0x5a, + 0x17, 0x0d, 0x34, 0x36, 0x30, 0x39, 0x32, 0x33, 0x32, 0x30, 0x30, 0x39, + 0x34, 0x38, 0x5a, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0c, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, + 0x74, 0x30, 0x5a, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x02, 0x01, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, + 0x07, 0x03, 0x42, 0x00, 0x04, 0xa3, 0xee, 0x68, 0x8c, 0xd8, 0xc0, 0x62, + 0x1f, 0x16, 0xf0, 0x26, 0xc8, 0xea, 0xac, 0x9b, 0x4e, 0xfd, 0x5b, 0x31, + 0xeb, 0xd9, 0x6a, 0x8b, 0xdf, 0xe7, 0x55, 0x10, 0xae, 0xb8, 0xfb, 0xc1, + 0x76, 0x38, 0x3c, 0xf9, 0xac, 0x68, 0xaa, 0xbf, 0x37, 0xac, 0x6f, 0x1a, + 0xa8, 0x7d, 0x03, 0xf5, 0xc1, 0x12, 0x38, 0x23, 0x0d, 0x24, 0xcd, 0xa0, + 0x3c, 0x2b, 0x06, 0x3b, 0xa3, 0x7d, 0xee, 0x3c, 0x4c, 0xa3, 0x81, 0x8c, + 0x30, 0x81, 0x89, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x13, 0x06, + 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x14, 0x06, 0x03, 0x55, 0x1d, + 0x11, 0x04, 0x0d, 0x30, 0x0b, 0x82, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x68, 0x6f, 0x73, 0x74, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x80, 0x53, 0x8e, 0xc5, 0x05, 0x58, 0x9f, 0xb3, 0xc5, + 0x17, 0xd5, 0x34, 0xb7, 0x7d, 0x67, 0x9e, 0xf7, 0xdf, 0x79, 0x8a, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0xfb, 0xe0, 0xaf, 0x37, 0xf0, 0x64, 0x59, 0x03, 0xef, 0x21, 0x7e, 0x33, + 0x5a, 0xc8, 0xf8, 0x7c, 0x38, 0x2f, 0x33, 0xc9, 0x30, 0x0a, 0x06, 0x08, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, + 0x44, 0x02, 0x20, 0x33, 0x80, 0x19, 0xe0, 0x26, 0xd2, 0x9b, 0x14, 0xab, + 0x70, 0x6c, 0x70, 0xb7, 0xe4, 0x9c, 0x25, 0xc9, 0x1e, 0xee, 0x7c, 0x98, + 0xf7, 0x91, 0xc3, 0xc4, 0x09, 0x52, 0x78, 0x4b, 0x9f, 0xf5, 0xbe, 0x02, + 0x20, 0x07, 0x9e, 0xd4, 0x2c, 0x7f, 0x22, 0x7c, 0x65, 0xd1, 0xd9, 0x1f, + 0x32, 0x53, 0x29, 0x28, 0x13, 0x51, 0x0d, 0x97, 0xa9, 0x0a, 0xec, 0x05, + 0xc2, 0xeb, 0xdf, 0x32, 0x7b, 0xfa, 0x0f, 0x83, 0xde, +}; + +static UCHAR brainpool_server_key_der[] = { + 0x30, 0x78, 0x02, 0x01, 0x01, 0x04, 0x20, 0xa6, 0x66, 0xf2, 0xa2, 0x01, + 0x1a, 0xb3, 0xda, 0x05, 0x35, 0xe6, 0xf9, 0xb0, 0xe1, 0xae, 0x02, 0x80, + 0xe9, 0x4c, 0xe7, 0x5a, 0x51, 0xc5, 0xe3, 0x4b, 0x38, 0x65, 0x4d, 0xd6, + 0x42, 0x20, 0x62, 0xa0, 0x0b, 0x06, 0x09, 0x2b, 0x24, 0x03, 0x03, 0x02, + 0x08, 0x01, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xa3, 0xee, + 0x68, 0x8c, 0xd8, 0xc0, 0x62, 0x1f, 0x16, 0xf0, 0x26, 0xc8, 0xea, 0xac, + 0x9b, 0x4e, 0xfd, 0x5b, 0x31, 0xeb, 0xd9, 0x6a, 0x8b, 0xdf, 0xe7, 0x55, + 0x10, 0xae, 0xb8, 0xfb, 0xc1, 0x76, 0x38, 0x3c, 0xf9, 0xac, 0x68, 0xaa, + 0xbf, 0x37, 0xac, 0x6f, 0x1a, 0xa8, 0x7d, 0x03, 0xf5, 0xc1, 0x12, 0x38, + 0x23, 0x0d, 0x24, 0xcd, 0xa0, 0x3c, 0x2b, 0x06, 0x3b, 0xa3, 0x7d, 0xee, + 0x3c, 0x4c, +}; diff --git a/test/regression/nx_secure_test/nx_secure_brainpool_test.c b/test/regression/nx_secure_test/nx_secure_brainpool_test.c new file mode 100644 index 000000000..86698a9f4 --- /dev/null +++ b/test/regression/nx_secure_test/nx_secure_brainpool_test.c @@ -0,0 +1,394 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + ***************************************************************************/ + +#include +#include +#include "nx_crypto_ecdsa.h" +#include "nx_crypto_ecdh.h" +#include "nx_crypto_ec.h" +#include "tls_test_utility.h" +#ifndef NX_CRYPTO_STANDALONE_ENABLE +#include "nx_secure_tls.h" +static TX_THREAD thread_0; +#endif + +extern NX_CRYPTO_METHOD crypto_method_ecdh; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp384; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp512; + +static UCHAR brainpool_256_hash[] = { + 0xcd, 0x73, 0x02, 0x24, 0x10, 0x0b, 0x5e, 0x46, 0x5c, 0x36, 0x8d, 0xaf, + 0x27, 0x2a, 0x81, 0x7a, 0xe3, 0x7b, 0x8f, 0x55, 0x84, 0xec, 0x84, 0x69, + 0x3c, 0x1d, 0xfe, 0x44, 0x85, 0xa8, 0xa7, 0xe1, +}; +static UCHAR brainpool_256_pub[] = { + 0x04, 0xa6, 0x06, 0x7e, 0x83, 0x3f, 0x60, 0xfa, 0x95, 0x87, 0x91, 0xea, + 0xbf, 0xdb, 0xb0, 0x47, 0x7d, 0xd4, 0x6c, 0x02, 0xcf, 0x1b, 0xe0, 0xbf, + 0x13, 0xa4, 0x9e, 0xeb, 0xb2, 0x06, 0x49, 0xca, 0xbb, 0x01, 0x31, 0xaa, + 0x4d, 0x28, 0x4e, 0xca, 0x96, 0xee, 0xfa, 0xf0, 0x88, 0x73, 0x4a, 0x01, + 0x8a, 0xfa, 0x1a, 0x9c, 0x47, 0x17, 0x55, 0xa4, 0x72, 0x76, 0x79, 0xcb, + 0x31, 0x44, 0x96, 0x53, 0xcc, +}; +static UCHAR brainpool_256_sig[] = { + 0x30, 0x44, 0x02, 0x20, 0x7b, 0xde, 0x18, 0xee, 0x45, 0x51, 0x9a, 0x14, + 0x8f, 0x01, 0xfc, 0x12, 0xfa, 0x71, 0x4a, 0xb0, 0xa0, 0x7c, 0x88, 0xf3, + 0xae, 0xdc, 0xfc, 0xd4, 0x38, 0x68, 0x7c, 0x02, 0x85, 0x8d, 0x84, 0x3b, + 0x02, 0x20, 0x23, 0x1c, 0x78, 0xe1, 0x0e, 0x63, 0x7a, 0x8a, 0xca, 0x31, + 0x08, 0x7f, 0x5a, 0xc7, 0x5e, 0x27, 0x4e, 0xa6, 0x17, 0x9a, 0xe5, 0xa9, + 0x42, 0x28, 0x7e, 0x6d, 0x01, 0xfe, 0xc5, 0x94, 0x06, 0xba, +}; +static UCHAR brainpool_384_hash[] = { + 0xce, 0x13, 0xda, 0xf1, 0x2c, 0xba, 0x05, 0x40, 0x26, 0x3b, 0x6b, 0x9b, + 0x90, 0xbb, 0x5f, 0xf8, 0x4e, 0x25, 0xc6, 0x1f, 0x85, 0x07, 0x6d, 0xca, + 0x97, 0x69, 0xc6, 0xc8, 0x96, 0x59, 0x71, 0xe0, 0x7b, 0xa0, 0x4f, 0x00, + 0x69, 0xdb, 0x98, 0x0b, 0xed, 0x38, 0xc7, 0xe0, 0xce, 0x51, 0x01, 0xe6, +}; +static UCHAR brainpool_384_pub[] = { + 0x04, 0x6c, 0xf4, 0xaa, 0x40, 0xd8, 0xc5, 0x47, 0xdb, 0x5f, 0xb9, 0xbe, + 0xab, 0x0e, 0xa1, 0x5a, 0xa9, 0xdc, 0xfb, 0x29, 0x18, 0x37, 0x36, 0x6f, + 0x17, 0x70, 0x11, 0x5a, 0x4c, 0x90, 0x49, 0x0b, 0xf2, 0xb3, 0xfc, 0x6a, + 0x82, 0x03, 0x87, 0x6b, 0xb1, 0x7d, 0x58, 0x65, 0x48, 0x3e, 0x89, 0x7c, + 0xd0, 0x69, 0xde, 0x3f, 0xed, 0x85, 0x77, 0xa7, 0x2f, 0x35, 0x8a, 0x5b, + 0x27, 0xb3, 0x0a, 0x20, 0x95, 0x14, 0x9c, 0xc5, 0x19, 0x27, 0xf6, 0xf3, + 0x07, 0x79, 0x3b, 0x4e, 0xb5, 0xe7, 0x62, 0x07, 0x18, 0xb1, 0x39, 0x8f, + 0xfa, 0xa0, 0x2b, 0x1a, 0x5e, 0x10, 0x90, 0x66, 0x91, 0x95, 0x77, 0xbb, + 0x2d, +}; +static UCHAR brainpool_384_sig[] = { + 0x30, 0x65, 0x02, 0x30, 0x57, 0x99, 0x3a, 0x6d, 0x6d, 0xb9, 0x2c, 0x7f, + 0x75, 0x8a, 0xc9, 0x5d, 0x43, 0x5c, 0x50, 0x0a, 0x89, 0x00, 0x73, 0x98, + 0x6b, 0xf0, 0x30, 0x5f, 0xad, 0xeb, 0xcc, 0x85, 0x01, 0x90, 0x00, 0x83, + 0x1e, 0x38, 0xeb, 0x7e, 0xe8, 0x66, 0xb3, 0x2b, 0x00, 0x5c, 0xcf, 0x76, + 0x95, 0xc8, 0x30, 0xe4, 0x02, 0x31, 0x00, 0x82, 0xd7, 0xd1, 0x7a, 0x57, + 0x6d, 0x78, 0xc1, 0x5a, 0xbb, 0xd1, 0xcf, 0x44, 0xbb, 0x18, 0x1a, 0x60, + 0x68, 0x56, 0x1c, 0x59, 0x73, 0x5d, 0x74, 0xb1, 0x97, 0x26, 0xc6, 0xf7, + 0x64, 0xcb, 0xd0, 0xba, 0x09, 0xd6, 0xc0, 0x1e, 0x1a, 0x54, 0x6e, 0x41, + 0xdb, 0x88, 0x7f, 0xda, 0x89, 0xff, 0x2d, +}; +static UCHAR brainpool_512_hash[] = { + 0x70, 0x5c, 0xab, 0x16, 0x5b, 0x5f, 0x41, 0x9f, 0xfe, 0xcd, 0x74, 0x0e, + 0x4c, 0x3d, 0x04, 0x2c, 0x42, 0xd8, 0xe1, 0x41, 0x84, 0x62, 0x81, 0x69, + 0xaf, 0xa1, 0x3d, 0x79, 0xf8, 0x40, 0x45, 0x2e, 0x17, 0xeb, 0xdb, 0x8a, + 0x60, 0x08, 0x6b, 0xa8, 0xee, 0xe4, 0x5b, 0xf5, 0x5e, 0x52, 0x06, 0x0e, + 0x36, 0x7b, 0xe5, 0x18, 0x7b, 0x6e, 0x08, 0x3b, 0x6f, 0x4f, 0x6c, 0x7f, + 0xf0, 0xf7, 0x98, 0x72, +}; +static UCHAR brainpool_512_pub[] = { + 0x04, 0x2a, 0x72, 0x5e, 0x1c, 0xd1, 0xf6, 0x67, 0x5e, 0xd0, 0x4d, 0x9b, + 0x25, 0x3b, 0x37, 0x48, 0x38, 0xf6, 0x77, 0x21, 0xb3, 0x14, 0x76, 0xaa, + 0xe3, 0x90, 0x28, 0xd3, 0xd7, 0xfc, 0x08, 0xd6, 0xb1, 0x00, 0x12, 0x2c, + 0xab, 0xec, 0xa7, 0x60, 0xc7, 0xb0, 0xab, 0xc8, 0x01, 0xa7, 0xe7, 0x08, + 0x22, 0x2f, 0x3f, 0xf0, 0xc9, 0x38, 0xcf, 0x70, 0xe1, 0x3f, 0xda, 0x83, + 0x74, 0x02, 0x2d, 0x0e, 0x72, 0x58, 0x9a, 0x3c, 0x4c, 0x62, 0xb1, 0xe7, + 0xd2, 0xb6, 0xdd, 0x7c, 0xfc, 0x6d, 0x06, 0xf1, 0xf2, 0xd1, 0x9b, 0xc4, + 0xdc, 0xf0, 0x53, 0x52, 0xb4, 0x83, 0xe8, 0x6c, 0xcd, 0x0c, 0x9e, 0x7f, + 0xef, 0x26, 0x3a, 0xc0, 0x9e, 0x54, 0x5d, 0xec, 0x59, 0x06, 0xa4, 0xdc, + 0x5d, 0x0f, 0x39, 0x6e, 0x5e, 0x2e, 0xa9, 0xc9, 0xf0, 0xa7, 0x8e, 0x20, + 0x2c, 0x03, 0xce, 0x13, 0x4a, 0x44, 0xea, 0xbc, 0xc8, +}; +static UCHAR brainpool_512_sig[] = { + 0x30, 0x81, 0x84, 0x02, 0x40, 0x2b, 0x6f, 0x08, 0xe0, 0xbe, 0x4d, 0x90, + 0x52, 0x97, 0x0a, 0x5f, 0x03, 0xba, 0xf1, 0x7c, 0x89, 0xbe, 0x00, 0x34, + 0x33, 0x63, 0xb0, 0x3b, 0x33, 0x60, 0x6d, 0x7b, 0xcd, 0xcb, 0x3c, 0x62, + 0x73, 0xdb, 0xfd, 0x73, 0xbb, 0xc6, 0x2e, 0x93, 0x12, 0x99, 0xdd, 0x03, + 0xeb, 0xe7, 0x90, 0xfb, 0x0f, 0xc8, 0x50, 0x71, 0xba, 0x89, 0x59, 0xce, + 0x80, 0x35, 0x73, 0x10, 0x30, 0x9c, 0x00, 0x19, 0x57, 0x02, 0x40, 0x69, + 0xb2, 0xb5, 0x72, 0x5f, 0x48, 0xe6, 0xd5, 0x04, 0xdd, 0x77, 0x99, 0xc7, + 0x94, 0x75, 0x52, 0x0e, 0xf0, 0x0d, 0xc0, 0xbe, 0xb1, 0xc5, 0x62, 0x82, + 0x8c, 0xf7, 0x72, 0xa5, 0x94, 0xb0, 0x8b, 0x67, 0x5f, 0x1a, 0x6e, 0x84, + 0x14, 0xb7, 0x28, 0x6d, 0x13, 0x20, 0xdb, 0x49, 0x3f, 0xbc, 0x66, 0xf2, + 0x68, 0x28, 0x88, 0x7b, 0x68, 0x32, 0x98, 0xe1, 0x14, 0xce, 0x59, 0xa8, + 0x15, 0x53, 0x21, +}; + +static UCHAR brainpool_256_ecdh_priv[] = { + 0x5b, 0xf6, 0xb8, 0xf9, 0x17, 0xa0, 0xe2, 0x51, 0x41, 0xa2, 0xe0, 0x3e, + 0x13, 0xef, 0xb1, 0xf0, 0x79, 0x47, 0xe5, 0x92, 0x21, 0x01, 0x2a, 0xd8, + 0x23, 0x42, 0xf3, 0x12, 0x93, 0x44, 0xdc, 0x06, +}; +static UCHAR brainpool_256_ecdh_local_pub[] = { + 0x04, 0x3a, 0xbe, 0x53, 0xb4, 0xfd, 0x2b, 0x0b, 0xc5, 0x60, 0xca, 0x34, + 0x8d, 0xdb, 0xb6, 0x4c, 0xdc, 0x4f, 0x73, 0xd2, 0x01, 0xd9, 0xb0, 0x76, + 0x75, 0x65, 0x4c, 0xa5, 0x6c, 0xb4, 0xc5, 0xda, 0xf2, 0x46, 0xd0, 0xbc, + 0x5e, 0xec, 0x93, 0x7b, 0x66, 0xd5, 0x58, 0xe8, 0x8a, 0x00, 0x6b, 0x74, + 0x61, 0xc4, 0x34, 0x3b, 0x3a, 0x36, 0xaf, 0xb8, 0xf3, 0xad, 0xf2, 0x9d, + 0xc8, 0x8e, 0xde, 0x24, 0x80, +}; +static UCHAR brainpool_256_ecdh_remote_pub[] = { + 0x04, 0xa8, 0x95, 0x6a, 0x68, 0xdc, 0x7e, 0x8a, 0xde, 0xdb, 0xe4, 0xa1, + 0x07, 0xe1, 0x0a, 0x86, 0x86, 0x5c, 0x2f, 0xc3, 0x2f, 0x6f, 0xa1, 0x5e, + 0x82, 0x27, 0x1d, 0x2b, 0x27, 0x8e, 0xf1, 0x84, 0xfc, 0x5c, 0x8d, 0x6a, + 0x6c, 0xcb, 0xd0, 0xc6, 0xe5, 0x90, 0xd6, 0xe6, 0xe6, 0xc0, 0x71, 0x4a, + 0x9d, 0x0e, 0x6a, 0x09, 0xef, 0xab, 0xdd, 0xb6, 0x90, 0xa4, 0xde, 0x95, + 0x46, 0x3b, 0xe7, 0x8d, 0x4a, +}; +static UCHAR brainpool_256_ecdh_secret[] = { + 0x81, 0x71, 0xd2, 0xff, 0xbb, 0x11, 0x52, 0x7d, 0x37, 0x01, 0x03, 0xa6, + 0xd5, 0x90, 0x4e, 0x1e, 0xfb, 0xa4, 0xf2, 0xcc, 0x1b, 0x52, 0x17, 0xd4, + 0xa0, 0x15, 0x57, 0xc7, 0x1c, 0x8e, 0x65, 0xae, +}; +static UCHAR brainpool_384_ecdh_priv[] = { + 0x19, 0x7a, 0xf4, 0x20, 0xe9, 0x3c, 0x5d, 0x87, 0xc3, 0x08, 0xb1, 0xac, + 0x37, 0xef, 0xcc, 0x95, 0xd6, 0x9d, 0x75, 0xd3, 0x69, 0x6e, 0x9d, 0xae, + 0xca, 0x13, 0xa3, 0x88, 0x56, 0xa3, 0x57, 0x28, 0x2a, 0xf2, 0x10, 0x06, + 0xdc, 0x07, 0x99, 0xf9, 0x49, 0xd0, 0x3f, 0xab, 0x1b, 0xf6, 0xf4, 0xf5, +}; +static UCHAR brainpool_384_ecdh_local_pub[] = { + 0x04, 0x52, 0xf1, 0xc3, 0xb7, 0x2a, 0xd2, 0xd5, 0x8c, 0x6b, 0x1f, 0x94, + 0x82, 0xce, 0x3c, 0xa5, 0x28, 0xcd, 0x68, 0x98, 0xb3, 0xd2, 0xa8, 0xd5, + 0x3a, 0x3a, 0xa8, 0xfb, 0x0a, 0x68, 0x1b, 0xeb, 0xff, 0x3a, 0xb1, 0x9b, + 0xc8, 0xf7, 0xde, 0x0f, 0xdd, 0xed, 0xed, 0xf9, 0x58, 0x7d, 0x64, 0x9c, + 0x90, 0x6f, 0xcb, 0x83, 0x16, 0x47, 0x04, 0xcd, 0x44, 0xe7, 0x8b, 0xfc, + 0x07, 0xe4, 0xfd, 0x8d, 0xac, 0x37, 0x12, 0xed, 0xb0, 0xed, 0x13, 0x74, + 0xae, 0x25, 0x82, 0xd9, 0xcd, 0xde, 0x6d, 0xe4, 0x97, 0x7e, 0xb1, 0x30, + 0xc5, 0x99, 0x28, 0xd2, 0x5f, 0x8d, 0x1c, 0x01, 0x26, 0x96, 0x32, 0x82, + 0xec, +}; +static UCHAR brainpool_384_ecdh_remote_pub[] = { + 0x04, 0x83, 0x41, 0x46, 0x10, 0x60, 0x42, 0x72, 0x7a, 0xb9, 0x99, 0xfd, + 0x5d, 0x14, 0x4e, 0xa3, 0x59, 0x04, 0x04, 0x01, 0x65, 0x76, 0x53, 0xda, + 0x03, 0xbd, 0x16, 0x2c, 0x9f, 0xbb, 0x3f, 0xd0, 0x7f, 0xde, 0xbf, 0x8b, + 0xb0, 0x1b, 0xa4, 0xe0, 0xce, 0xf9, 0x79, 0xd9, 0x04, 0xbb, 0x19, 0xdd, + 0x3a, 0x08, 0xb5, 0xcf, 0x87, 0xcc, 0x7b, 0xd2, 0x04, 0xb6, 0x58, 0x8c, + 0xfe, 0xdf, 0xb7, 0xe8, 0x0b, 0x9d, 0x11, 0x41, 0x92, 0xdc, 0x84, 0xe8, + 0x87, 0x5b, 0xc9, 0x69, 0x17, 0x95, 0x4e, 0x27, 0xe2, 0x13, 0xe1, 0x2b, + 0x98, 0xd9, 0xdf, 0x71, 0x65, 0xb7, 0x56, 0x82, 0x50, 0x3b, 0x93, 0x2d, + 0x88, +}; +static UCHAR brainpool_384_ecdh_secret[] = { + 0x8b, 0x32, 0xf9, 0x18, 0x1b, 0x8a, 0xde, 0xc5, 0xe0, 0x82, 0xa5, 0xc1, + 0x00, 0xd7, 0x2c, 0x22, 0xa0, 0x07, 0xb4, 0x87, 0x1c, 0x46, 0xd4, 0xc9, + 0xdc, 0x42, 0x4f, 0x18, 0x90, 0x61, 0x51, 0x70, 0xd4, 0xb0, 0xcc, 0x48, + 0xb7, 0x56, 0x9d, 0xd4, 0x90, 0x2b, 0x19, 0x0a, 0xc7, 0xa9, 0xcd, 0xd8, +}; +static UCHAR brainpool_512_ecdh_priv[] = { + 0x36, 0x26, 0x8f, 0x91, 0x92, 0x50, 0xaf, 0xa3, 0x13, 0xa2, 0x00, 0xe4, + 0x50, 0xc6, 0x96, 0xcf, 0x24, 0xd1, 0x7b, 0x39, 0xcc, 0x7e, 0x34, 0x20, + 0xbb, 0xbb, 0x86, 0x21, 0xa2, 0xe7, 0x99, 0x26, 0x14, 0xbb, 0xb8, 0xbf, + 0x87, 0xd1, 0xaa, 0x4f, 0x77, 0xdd, 0xfe, 0x48, 0x37, 0x4b, 0x74, 0x46, + 0xe1, 0x1e, 0x0d, 0x7e, 0xca, 0xac, 0x13, 0x6a, 0xc3, 0x4c, 0x55, 0x12, + 0x39, 0xfc, 0x21, 0x8e, +}; +static UCHAR brainpool_512_ecdh_local_pub[] = { + 0x04, 0x0b, 0x3b, 0x66, 0xbc, 0x99, 0xf0, 0xc1, 0x3d, 0x57, 0xd1, 0x73, + 0xf7, 0x45, 0x85, 0xf0, 0x4e, 0x4d, 0x70, 0xe7, 0xe2, 0x3b, 0x06, 0x36, + 0x36, 0xe1, 0x11, 0x0e, 0x14, 0x50, 0xdd, 0x2d, 0xcf, 0xf4, 0xc7, 0x3a, + 0x7d, 0xa2, 0x35, 0x9a, 0x6c, 0x53, 0xb9, 0x5b, 0x84, 0xdc, 0x23, 0x2b, + 0x8a, 0x77, 0x92, 0xf4, 0x1f, 0x8e, 0xfe, 0x3d, 0xab, 0x84, 0xb4, 0xf4, + 0xba, 0x68, 0x0a, 0x6e, 0xf0, 0x0e, 0xf3, 0x0d, 0x2d, 0x28, 0x70, 0x34, + 0xfa, 0x48, 0x3f, 0x75, 0x4d, 0xea, 0xa5, 0x8c, 0xcf, 0xae, 0xc9, 0x13, + 0x80, 0x8d, 0x6d, 0x78, 0xdd, 0x43, 0xda, 0xa2, 0x39, 0xc0, 0xae, 0x24, + 0x19, 0xa4, 0x25, 0x1d, 0x7e, 0x47, 0xa4, 0x25, 0x2e, 0xf9, 0x19, 0x28, + 0x26, 0x4d, 0xa4, 0x9c, 0x7b, 0xe0, 0x87, 0x24, 0x0c, 0xfd, 0x01, 0x11, + 0x55, 0x19, 0xb2, 0x17, 0x56, 0x68, 0xc9, 0x0b, 0xf4, +}; +static UCHAR brainpool_512_ecdh_remote_pub[] = { + 0x04, 0x4f, 0x02, 0x44, 0x64, 0x87, 0xcd, 0x03, 0x48, 0x98, 0xea, 0x6d, + 0xca, 0xf7, 0xf6, 0x31, 0x97, 0x5d, 0x7c, 0x85, 0xf4, 0x35, 0x60, 0x30, + 0xc8, 0xb6, 0x0b, 0x15, 0x48, 0x5c, 0x79, 0x69, 0x73, 0x54, 0xc8, 0xd9, + 0xac, 0x00, 0x85, 0x71, 0x57, 0x65, 0x19, 0x82, 0x4b, 0x44, 0x9b, 0xa7, + 0x3d, 0xdc, 0x5f, 0xed, 0xe0, 0xc1, 0x28, 0xe8, 0x6f, 0x2c, 0x86, 0xc9, + 0xef, 0x49, 0x4a, 0x79, 0x56, 0x9f, 0xe0, 0x74, 0xb3, 0x79, 0x58, 0x67, + 0xde, 0x83, 0xec, 0x55, 0x86, 0x4a, 0x16, 0x74, 0xc0, 0xed, 0x8f, 0x0e, + 0xbd, 0x2c, 0x9f, 0x94, 0x3a, 0xa7, 0x7f, 0xf8, 0xa2, 0x05, 0x34, 0xf1, + 0xab, 0x16, 0xdd, 0x0c, 0x54, 0xf3, 0xc6, 0x15, 0x6c, 0xf5, 0xe7, 0x87, + 0xcb, 0xd3, 0x78, 0x4a, 0xb1, 0x9c, 0x63, 0xa0, 0x68, 0x19, 0x29, 0xda, + 0x26, 0x58, 0x1b, 0x62, 0x2f, 0xd1, 0x97, 0xbf, 0xda, +}; +static UCHAR brainpool_512_ecdh_secret[] = { + 0x5a, 0x88, 0x9c, 0x08, 0xb5, 0xb8, 0x6a, 0x5a, 0x0c, 0xdf, 0x0d, 0x7c, + 0x7a, 0x36, 0xfb, 0xe3, 0x92, 0x26, 0x39, 0xc6, 0x02, 0x93, 0xa9, 0xcb, + 0xae, 0xbe, 0x7c, 0x24, 0xe5, 0x8c, 0x96, 0x07, 0x30, 0x21, 0xf7, 0x04, + 0xbe, 0x7a, 0xbe, 0xbe, 0x4c, 0x4c, 0xc8, 0x9d, 0x99, 0x16, 0xc5, 0xdd, + 0xf0, 0xe8, 0x78, 0x5e, 0x76, 0x2f, 0x3b, 0x41, 0xa8, 0xaf, 0x06, 0xcb, + 0xe1, 0x1e, 0x97, 0x4d, +}; + +/* Verification vectors generated using OpenSSL from RFC 5639 domains. */ +typedef struct BRAINPOOL_TEST_VECTOR_STRUCT +{ + NX_CRYPTO_METHOD *method; + UINT curve_id; + UCHAR *hash; + UINT hash_length; + UCHAR *public_key; + UINT public_key_length; + UCHAR *signature; + UINT signature_length; +} BRAINPOOL_TEST_VECTOR; + +static BRAINPOOL_TEST_VECTOR vectors[] = +{ + {&crypto_method_ec_brainpoolp256, NX_CRYPTO_EC_BRAINPOOLP256r1, + brainpool_256_hash, sizeof(brainpool_256_hash), brainpool_256_pub, sizeof(brainpool_256_pub), + brainpool_256_sig, sizeof(brainpool_256_sig)}, + {&crypto_method_ec_brainpoolp384, NX_CRYPTO_EC_BRAINPOOLP384r1, + brainpool_384_hash, sizeof(brainpool_384_hash), brainpool_384_pub, sizeof(brainpool_384_pub), + brainpool_384_sig, sizeof(brainpool_384_sig)}, + {&crypto_method_ec_brainpoolp512, NX_CRYPTO_EC_BRAINPOOLP512r1, + brainpool_512_hash, sizeof(brainpool_512_hash), brainpool_512_pub, sizeof(brainpool_512_pub), + brainpool_512_sig, sizeof(brainpool_512_sig)} +}; + +/* ECDH vectors generated using OpenSSL from RFC 5639 domains. */ +typedef struct BRAINPOOL_ECDH_VECTOR_STRUCT +{ + UCHAR *private_key; + UCHAR *local_public_key; + UCHAR *remote_public_key; + UCHAR *shared_secret; + UINT key_length; + UINT public_key_length; +} BRAINPOOL_ECDH_VECTOR; + +static BRAINPOOL_ECDH_VECTOR ecdh_vectors[] = +{ + {brainpool_256_ecdh_priv, brainpool_256_ecdh_local_pub, + brainpool_256_ecdh_remote_pub, brainpool_256_ecdh_secret, + sizeof(brainpool_256_ecdh_priv), sizeof(brainpool_256_ecdh_local_pub)}, + {brainpool_384_ecdh_priv, brainpool_384_ecdh_local_pub, + brainpool_384_ecdh_remote_pub, brainpool_384_ecdh_secret, + sizeof(brainpool_384_ecdh_priv), sizeof(brainpool_384_ecdh_local_pub)}, + {brainpool_512_ecdh_priv, brainpool_512_ecdh_local_pub, + brainpool_512_ecdh_remote_pub, brainpool_512_ecdh_secret, + sizeof(brainpool_512_ecdh_priv), sizeof(brainpool_512_ecdh_local_pub)} +}; + +/* Verify valid signatures and reject damaged points and signatures. */ +static VOID thread_0_entry(ULONG thread_input) +{ + UINT i; + UINT status; + NX_CRYPTO_EC *curve; + HN_UBASE scratch[1000]; + UCHAR damaged_signature[160]; + UCHAR damaged_key[129]; + UCHAR shared_secret[64]; + NX_CRYPTO_ECDH ecdh; + NX_CRYPTO_EXTENDED_OUTPUT extended_output; + + (void)thread_input; + printf("NetX Secure Test: Brainpool ECDSA Test.............................."); + + for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) + { + curve = NX_CRYPTO_NULL; + status = vectors[i].method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET, + NX_CRYPTO_NULL, vectors[i].method, NX_CRYPTO_NULL, 0, + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, (UCHAR *)&curve, sizeof(curve), + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if ((status != NX_CRYPTO_SUCCESS) || (curve == NX_CRYPTO_NULL) || + (curve -> nx_crypto_ec_id != vectors[i].curve_id)) + { + printf("curve method failed for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + + status = _nx_crypto_ecdsa_verify(curve, vectors[i].hash, vectors[i].hash_length, + vectors[i].public_key, vectors[i].public_key_length, + vectors[i].signature, vectors[i].signature_length, scratch); + if (status != NX_CRYPTO_SUCCESS) + { + printf("signature verification failed for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + + memcpy(damaged_signature, vectors[i].signature, vectors[i].signature_length); + damaged_signature[vectors[i].signature_length - 1u] ^= 1u; + status = _nx_crypto_ecdsa_verify(curve, vectors[i].hash, vectors[i].hash_length, + vectors[i].public_key, vectors[i].public_key_length, + damaged_signature, vectors[i].signature_length, scratch); + if (status == NX_CRYPTO_SUCCESS) + { + printf("damaged signature accepted for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + + memcpy(damaged_key, vectors[i].public_key, vectors[i].public_key_length); + damaged_key[0] = 0x05u; + status = _nx_crypto_ecdsa_verify(curve, vectors[i].hash, vectors[i].hash_length, + damaged_key, vectors[i].public_key_length, + vectors[i].signature, vectors[i].signature_length, scratch); + if (status == NX_CRYPTO_SUCCESS) + { + printf("damaged public key accepted for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + status = crypto_method_ecdh.nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, + NX_CRYPTO_NULL, &crypto_method_ecdh, NX_CRYPTO_NULL, 0, + (UCHAR *)vectors[i].method, sizeof(NX_CRYPTO_METHOD *), NX_CRYPTO_NULL, + NX_CRYPTO_NULL, 0, &ecdh, sizeof(ecdh), NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + printf("ECDH curve setup failed for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + + status = crypto_method_ecdh.nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, + NX_CRYPTO_NULL, &crypto_method_ecdh, + ecdh_vectors[i].private_key, (NX_CRYPTO_KEY_SIZE)(ecdh_vectors[i].key_length << 3), + ecdh_vectors[i].local_public_key, ecdh_vectors[i].public_key_length, + NX_CRYPTO_NULL, NX_CRYPTO_NULL, 0, &ecdh, sizeof(ecdh), + NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + printf("ECDH key import failed for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + + extended_output.nx_crypto_extended_output_data = shared_secret; + extended_output.nx_crypto_extended_output_length_in_byte = sizeof(shared_secret); + status = crypto_method_ecdh.nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, + NX_CRYPTO_NULL, &crypto_method_ecdh, NX_CRYPTO_NULL, 0, + ecdh_vectors[i].remote_public_key, ecdh_vectors[i].public_key_length, + NX_CRYPTO_NULL, (UCHAR *)&extended_output, sizeof(extended_output), + &ecdh, sizeof(ecdh), NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if ((status != NX_CRYPTO_SUCCESS) || + (extended_output.nx_crypto_extended_output_actual_size != ecdh_vectors[i].key_length) || + (memcmp(shared_secret, ecdh_vectors[i].shared_secret, ecdh_vectors[i].key_length) != 0)) + { + printf("ECDH shared secret mismatch for %u\n", vectors[i].curve_id); + test_control_return(1); + return; + } + } + + printf("SUCCESS!\n"); + test_control_return(0); +} + +/* Start the regression test in a ThreadX thread or standalone process. */ +#ifdef CTEST +void test_application_define(void *first_unused_memory); +void test_application_define(void *first_unused_memory) +#else +void nx_secure_brainpool_test_application_define(void *first_unused_memory) +#endif +{ +#ifndef NX_CRYPTO_STANDALONE_ENABLE + tx_thread_create(&thread_0, "Thread 0", thread_0_entry, 0, + first_unused_memory, 4096, 16, 16, 4, TX_AUTO_START); +#else + (void)first_unused_memory; + thread_0_entry(0); +#endif +} diff --git a/test/regression/nx_secure_test/nx_secure_tls_1_3_provisioned_psk_test.c b/test/regression/nx_secure_test/nx_secure_tls_1_3_provisioned_psk_test.c index fc8775122..7ee056058 100644 --- a/test/regression/nx_secure_test/nx_secure_tls_1_3_provisioned_psk_test.c +++ b/test/regression/nx_secure_test/nx_secure_tls_1_3_provisioned_psk_test.c @@ -9,7 +9,9 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -/* This test concentrates on TLS ECC ciphersuites negotiation. */ +/* Portions of this file were generated with AI assistance. */ + +/* This test negotiates TLS 1.3 key exchange with a Brainpool group. */ #include "nx_api.h" #include "nx_secure_tls_api.h" @@ -79,11 +81,22 @@ static UCHAR response_buffer[BUFFER_SIZE]; static UCHAR tls_packet_buffer[2][4000]; extern NX_SECURE_TLS_CIPHERSUITE_INFO _nx_crypto_ciphersuite_lookup_table_ecc[]; -extern const USHORT nx_crypto_ecc_supported_groups[]; -extern const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[]; -extern const UINT nx_crypto_ecc_supported_groups_size; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256; +extern NX_CRYPTO_METHOD crypto_method_ec_secp256; extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers_ecc; +static const USHORT brainpool_groups[] = +{ + (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1, + (USHORT)NX_CRYPTO_EC_SECP256R1 +}; + +static const NX_CRYPTO_METHOD *brainpool_curves[] = +{ + &crypto_method_ec_brainpoolp256, + &crypto_method_ec_secp256 +}; + static CERTIFICATE test_certs[] = { CERTIFICATE_INIT(ECTestServer2_der, ECTestServer2_key_der, ECCA2_der, NX_SECURE_X509_KEY_TYPE_EC_DER), @@ -178,9 +191,9 @@ UINT status; status = nx_secure_tls_client_psk_set(tls_session_ptr, tls_psk, sizeof(tls_psk), "Client_identity", 15, "12345678", 8); do_something_if_fail(NX_SECURE_TLS_SUCCESS == status); - status = nx_secure_tls_ecc_initialize(tls_session_ptr, nx_crypto_ecc_supported_groups, - nx_crypto_ecc_supported_groups_size, - nx_crypto_ecc_curves); + status = nx_secure_tls_ecc_initialize(tls_session_ptr, brainpool_groups, + sizeof(brainpool_groups) / sizeof(brainpool_groups[0]), + brainpool_curves); do_something_if_fail(NX_SECURE_TLS_SUCCESS == status); memset(&client_remote_cert, 0, sizeof(client_remote_cert)); @@ -217,9 +230,9 @@ UINT status; status = nx_secure_tls_psk_add(tls_session_ptr, tls_psk, sizeof(tls_psk), "Client_identity", 15, "12345678", 8); do_something_if_fail(NX_SECURE_TLS_SUCCESS == status); - status = nx_secure_tls_ecc_initialize(tls_session_ptr, nx_crypto_ecc_supported_groups, - nx_crypto_ecc_supported_groups_size, - nx_crypto_ecc_curves); + status = nx_secure_tls_ecc_initialize(tls_session_ptr, brainpool_groups, + sizeof(brainpool_groups) / sizeof(brainpool_groups[0]), + brainpool_curves); do_something_if_fail(NX_SECURE_TLS_SUCCESS == status); memset(&server_local_certificate, 0, sizeof(server_local_certificate)); @@ -268,6 +281,9 @@ NX_PACKET *packet_ptr; status = nx_secure_tls_session_start(&tls_server_session_0, &server_socket_0, NX_WAIT_FOREVER); do_something_if_fail(NX_SECURE_TLS_SUCCESS == status); + do_something_if_fail((USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1 == + tls_server_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[ + tls_server_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected].nx_secure_tls_ecdhe_named_curve); nx_secure_tls_session_end(&tls_server_session_0, NX_IP_PERIODIC_RATE); nx_secure_tls_session_delete(&tls_server_session_0); @@ -329,6 +345,9 @@ NXD_ADDRESS server_address; /* Start TLS session. */ status = nx_secure_tls_session_start(&tls_client_session_0, &client_socket_0, NX_WAIT_FOREVER); do_something_if_fail(NX_SECURE_TLS_SUCCESS == status); + do_something_if_fail((USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1 == + tls_client_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[ + tls_client_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected].nx_secure_tls_ecdhe_named_curve); if (!status) { diff --git a/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c b/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c index ad9d2f3f6..dd5c4f0e1 100644 --- a/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c +++ b/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c @@ -25,12 +25,12 @@ extern VOID test_control_return(UINT status); #if !defined(NX_SECURE_TLS_CLIENT_DISABLED) && !defined(NX_SECURE_DISABLE_X509) && \ - (NX_SECURE_TLS_TLS_1_3_ENABLED) + defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && (NX_SECURE_TLS_TLS_1_3_ENABLED) #define TEST_PACKET_OFFSET 3u #define TEST_PACKET_SIZE 32u -#define TLS_1_3_EXTENSION_SIZE 20u -#define TLS_1_2_EXTENSION_SIZE 14u +#define TLS_1_3_EXTENSION_SIZE 26u +#define TLS_1_2_EXTENSION_SIZE 18u #define OVERSIZED_TABLE_ENTRY_COUNT 16383u static NX_CRYPTO_METHOD rsa_method = @@ -68,7 +68,9 @@ static NX_SECURE_X509_CRYPTO signature_methods[] = {0, &rsa_method, &sha256_method}, {0, &rsa_method, &sha384_method}, {0, &rsa_method, &sha512_method}, - {0, &ecdsa_method, &sha256_method}, + {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256, &ecdsa_method, &sha256_method}, + {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384, &ecdsa_method, &sha384_method}, + {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512, &ecdsa_method, &sha512_method}, {0, &unsupported_method, &sha256_method} }; @@ -76,22 +78,46 @@ static NX_SECURE_X509_CRYPTO oversized_signature_methods[OVERSIZED_TABLE_ENTRY_C static const USHORT supported_groups[] = { - (USHORT)NX_CRYPTO_EC_SECP256R1 + (USHORT)NX_CRYPTO_EC_SECP256R1, + (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1, + (USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1, + (USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1 +}; + +extern NX_CRYPTO_METHOD crypto_method_ec_secp256; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp384; +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp512; + +static const NX_CRYPTO_METHOD *supported_curve_methods[] = +{ + &crypto_method_ec_secp256, + &crypto_method_ec_brainpoolp256, + &crypto_method_ec_brainpoolp384, + &crypto_method_ec_brainpoolp512 +}; + +static const UCHAR brainpool_oids[3][9] = +{ + {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}, + {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}, + {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D} }; static const UCHAR expected_tls_1_3_extension[TLS_1_3_EXTENSION_SIZE] = { - 0x00, 0x0D, 0x00, 0x10, 0x00, 0x0E, + 0x00, 0x0D, 0x00, 0x16, 0x00, 0x14, 0x08, 0x04, 0x04, 0x01, 0x08, 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, - 0x04, 0x03 + 0x04, 0x03, 0x08, 0x1A, 0x08, 0x1B, 0x08, 0x1C }; static const UCHAR expected_tls_1_2_extension[TLS_1_2_EXTENSION_SIZE] = { - 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x08, - 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x04, 0x03 + 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0C, + 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, + 0x04, 0x03, 0x05, 0x03, 0x06, 0x03 }; #endif @@ -115,7 +141,7 @@ void nx_secure_tls_clienthello_signature_algorithms_test_application_define(void #endif { #if !defined(NX_SECURE_TLS_CLIENT_DISABLED) && !defined(NX_SECURE_DISABLE_X509) && \ - (NX_SECURE_TLS_TLS_1_3_ENABLED) + defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && (NX_SECURE_TLS_TLS_1_3_ENABLED) NX_SECURE_TLS_SESSION tls_session; NX_SECURE_TLS_CRYPTO crypto_table; UCHAR packet_buffer[TEST_PACKET_SIZE]; @@ -123,6 +149,12 @@ ULONG packet_offset; USHORT extension_length; UINT status; UINT i; +UINT selected_curve; +UINT cert_curve_supported; +UINT oid_value; +USHORT ecdhe_signature_algorithm; +UCHAR groups_wire[4] = {0x00, 0x02, 0x00, 0x1F}; +NX_SECURE_TLS_HELLO_EXTENSION groups_extension; NX_PARAMETER_NOT_USED(first_unused_memory); @@ -138,6 +170,31 @@ UINT i; tls_session.nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups = supported_groups; tls_session.nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count = (USHORT)(sizeof(supported_groups) / sizeof(supported_groups[0])); + tls_session.nx_secure_tls_ecc.nx_secure_tls_ecc_curves = supported_curve_methods; + + /* RFC 8734 groups differ from the TLS 1.2 Brainpool identifiers. */ + EXPECT_EQ(0x001Fu, _nx_secure_tls_brainpool_group_to_wire((USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1)); + EXPECT_EQ(0x0020u, _nx_secure_tls_brainpool_group_to_wire((USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1)); + EXPECT_EQ(0x0021u, _nx_secure_tls_brainpool_group_to_wire((USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1)); + EXPECT_EQ((USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1, _nx_secure_tls_brainpool_group_from_wire(0x001Fu)); + EXPECT_EQ((USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1, _nx_secure_tls_brainpool_group_from_wire(0x0020u)); + EXPECT_EQ((USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1, _nx_secure_tls_brainpool_group_from_wire(0x0021u)); + + groups_extension.nx_secure_tls_extension_id = NX_SECURE_TLS_EXTENSION_EC_GROUPS; + groups_extension.nx_secure_tls_extension_data_length = sizeof(groups_wire); + groups_extension.nx_secure_tls_extension_data = groups_wire; + for (i = 0; i < 3u; i++) + { + _nx_secure_x509_oid_parse(brainpool_oids[i], sizeof(brainpool_oids[i]), &oid_value); + EXPECT_EQ((UINT)(NX_SECURE_TLS_X509_EC_BRAINPOOLP256R1 + i), oid_value); + + groups_wire[3] = (UCHAR)(0x1Fu + i); + status = _nx_secure_tls_proc_clienthello_sec_sa_extension(&tls_session, + &groups_extension, 1u, &selected_curve, 0u, &cert_curve_supported, + &ecdhe_signature_algorithm, NX_NULL); + EXPECT_EQ(NX_SUCCESS, status); + EXPECT_EQ((UINT)supported_groups[i + 1u], selected_curve); + } /* The old two-bytes-per-table-entry check accepted this buffer even though the RSA-PSS entries now require paired TLS 1.2 algorithms. */ diff --git a/test/regression/nx_secure_test/nx_secure_tls_ecc_basic_test.c b/test/regression/nx_secure_test/nx_secure_tls_ecc_basic_test.c index 884adaa06..37df5f33e 100644 --- a/test/regression/nx_secure_test/nx_secure_tls_ecc_basic_test.c +++ b/test/regression/nx_secure_test/nx_secure_tls_ecc_basic_test.c @@ -9,11 +9,16 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -/* This test concentrates on TLS ciphersuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA. The curve used in this demo is P256. */ +/* Portions of this file were generated with AI assistance. */ + +/* This test exchanges data using an ECC certificate and key share. */ #include "nx_api.h" #include "nx_secure_tls_api.h" #include "ecc_certs.c" +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#include "brainpool_certs.c" +#endif #include "nx_crypto_ecdh.h" extern VOID test_control_return(UINT status); @@ -62,6 +67,12 @@ static UCHAR tls_packet_buffer[2][4000]; extern const USHORT nx_crypto_ecc_supported_groups[]; extern const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[]; extern const UINT nx_crypto_ecc_supported_groups_size; + +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +extern NX_CRYPTO_METHOD crypto_method_ec_brainpoolp256; +static const USHORT brainpool_groups[] = {(USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1}; +static const NX_CRYPTO_METHOD *brainpool_curves[] = {&crypto_method_ec_brainpoolp256}; +#endif extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers_ecc; /* Define thread prototypes. */ @@ -156,9 +167,15 @@ UINT status; ERROR_COUNTER(); } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + status = nx_secure_tls_ecc_initialize(tls_session_ptr, brainpool_groups, + sizeof(brainpool_groups) / sizeof(brainpool_groups[0]), + brainpool_curves); +#else status = nx_secure_tls_ecc_initialize(tls_session_ptr, nx_crypto_ecc_supported_groups, nx_crypto_ecc_supported_groups_size, nx_crypto_ecc_curves); +#endif if (status) { ERROR_COUNTER(); @@ -174,7 +191,12 @@ UINT status; ERROR_COUNTER(); } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + status = nx_secure_x509_certificate_initialize(&client_trusted_ca, + brainpool_root_der, sizeof(brainpool_root_der), +#else status = nx_secure_x509_certificate_initialize(&client_trusted_ca, ECCA2_der, ECCA2_der_len, +#endif NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE); if (status) @@ -210,19 +232,32 @@ UINT status; ERROR_COUNTER(); } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + status = nx_secure_tls_ecc_initialize(tls_session_ptr, brainpool_groups, + sizeof(brainpool_groups) / sizeof(brainpool_groups[0]), + brainpool_curves); +#else status = nx_secure_tls_ecc_initialize(tls_session_ptr, nx_crypto_ecc_supported_groups, nx_crypto_ecc_supported_groups_size, nx_crypto_ecc_curves); +#endif if (status) { ERROR_COUNTER(); } memset(&server_local_certificate, 0, sizeof(server_local_certificate)); +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + status = nx_secure_x509_certificate_initialize(&server_local_certificate, + brainpool_server_der, sizeof(brainpool_server_der), + NX_NULL, 0, brainpool_server_key_der, + sizeof(brainpool_server_key_der), +#else status = nx_secure_x509_certificate_initialize(&server_local_certificate, ECTestServer2_der, ECTestServer2_der_len, NX_NULL, 0, ECTestServer2_key_der, ECTestServer2_key_der_len, +#endif NX_SECURE_X509_KEY_TYPE_EC_DER); if (status) { @@ -283,6 +318,18 @@ NX_PACKET *packet_ptr; ERROR_COUNTER(); } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if ((tls_server_session_0.nx_secure_tls_1_3 != NX_TRUE) || + (tls_server_session_0.nx_secure_tls_signature_algorithm != + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256) || + (tls_server_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[ + tls_server_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected].nx_secure_tls_ecdhe_named_curve != + (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1)) + { + ERROR_COUNTER(); + } +#endif + status = nx_secure_tls_session_receive(&tls_server_session_0, &packet_ptr, NX_WAIT_FOREVER); if (status) { @@ -406,6 +453,12 @@ NXD_ADDRESS server_address; } /* Start TLS session. */ +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + tls_client_session_0.nx_secure_tls_1_3 = NX_TRUE; +#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION + tls_client_session_0.nx_secure_tls_renegotation_enabled = NX_FALSE; +#endif +#endif status = nx_secure_tls_session_start(&tls_client_session_0, &client_socket_0, NX_WAIT_FOREVER); if (status) @@ -413,6 +466,16 @@ NXD_ADDRESS server_address; ERROR_COUNTER(); } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if ((tls_client_session_0.nx_secure_tls_1_3 != NX_TRUE) || + (tls_client_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[ + tls_client_session_0.nx_secure_tls_key_material.nx_secure_tls_ecc_key_data_selected].nx_secure_tls_ecdhe_named_curve != + (USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1)) + { + ERROR_COUNTER(); + } +#endif + /* Prepare packet to send. */ status = nx_packet_allocate(&pool_0, &packet_ptr, NX_TCP_PACKET, NX_NO_WAIT); if (status) From eb82f84249facbb7ac0fd018590b3574dd600389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 16 Oct 2026 12:36:24 -0400 Subject: [PATCH 2/4] Removed duplicate AI disclosure from EC source The integrated EC source carried two disclosure lines, causing the repository disclosure check to fail. Keep the existing line once in the file header. The disclosure check passed. Assisted-by: Codex (gpt-6.1-sol) --- crypto_libraries/src/nx_crypto_ec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/crypto_libraries/src/nx_crypto_ec.c b/crypto_libraries/src/nx_crypto_ec.c index 0c1cd0f2f..39890a39d 100644 --- a/crypto_libraries/src/nx_crypto_ec.c +++ b/crypto_libraries/src/nx_crypto_ec.c @@ -10,8 +10,6 @@ **************************************************************************/ // Portions of this file were generated with AI assistance. -/* Portions of this file were generated with AI assistance. */ - /**************************************************************************/ /**************************************************************************/ From f71a9181c4463124c2689b94ad9344ae5d14fcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 16 Oct 2026 13:25:42 -0400 Subject: [PATCH 3/4] Covered Brainpool signature paths and guarded missing methods Brainpool signature selection and curve matching lacked regression coverage. A cipher table entry with a missing method could also dereference a null pointer while building the ClientHello signature list. Exercise Brainpool signature schemes, mismatched curves, and invalid crypto method requests. Skip incomplete cipher table entries before reading their methods. GCC 14 CMake/Ninja runs passed: 35/35 standalone crypto, 35/35 crypto coverage, 188/188 default Secure, and 164/164 TLS 1.3 Secure. Changed production code reached 175/175 lines and 77/78 branches; the untested branch requires a prime-field curve ID above Brainpool P512, while registered higher IDs use separate curve implementations. Assisted-by: Codex (gpt-6.1-sol) --- ...x_secure_tls_send_clienthello_extensions.c | 6 ++ .../nx_secure_test/nx_secure_brainpool_test.c | 41 ++++++++ ..._tls_1_3_certverify_transcript_hash_test.c | 49 ++++++++- ...ls_clienthello_signature_algorithms_test.c | 99 +++++++++++++++++++ ...cure_tls_process_certificate_verify_test.c | 62 +++++++++++- 5 files changed, 254 insertions(+), 3 deletions(-) diff --git a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c index 1259fbc26..b5b305f7a 100644 --- a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c +++ b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c @@ -585,6 +585,12 @@ UCHAR sig_algo = 0; *signature_algorithm = 0; + if ((crypto_method -> nx_secure_x509_public_cipher_method == NX_NULL) || + (crypto_method -> nx_secure_x509_hash_method == NX_NULL)) + { + return; + } + switch (crypto_method -> nx_secure_x509_public_cipher_method -> nx_crypto_algorithm) { case NX_CRYPTO_KEY_EXCHANGE_RSA: diff --git a/test/regression/nx_secure_test/nx_secure_brainpool_test.c b/test/regression/nx_secure_test/nx_secure_brainpool_test.c index 86698a9f4..2e40ef817 100644 --- a/test/regression/nx_secure_test/nx_secure_brainpool_test.c +++ b/test/regression/nx_secure_test/nx_secure_brainpool_test.c @@ -279,10 +279,51 @@ static VOID thread_0_entry(ULONG thread_input) UCHAR shared_secret[64]; NX_CRYPTO_ECDH ecdh; NX_CRYPTO_EXTENDED_OUTPUT extended_output; + NX_CRYPTO_METHOD unsupported_curve_method; (void)thread_input; printf("NetX Secure Test: Brainpool ECDSA Test.............................."); + /* Reject invalid curve requests before returning a domain pointer. */ + status = vectors[0].method -> nx_crypto_operation(NX_CRYPTO_VERIFY, + NX_CRYPTO_NULL, vectors[0].method, NX_CRYPTO_NULL, 0, + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, (UCHAR *)&curve, sizeof(curve), + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if (status != NX_CRYPTO_NOT_SUCCESSFUL) + { + test_control_return(1); + return; + } + status = vectors[0].method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET, + NX_CRYPTO_NULL, NX_CRYPTO_NULL, NX_CRYPTO_NULL, 0, + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, (UCHAR *)&curve, sizeof(curve), + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if (status != NX_CRYPTO_NOT_SUCCESSFUL) + { + test_control_return(1); + return; + } + status = vectors[0].method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET, + NX_CRYPTO_NULL, vectors[0].method, NX_CRYPTO_NULL, 0, + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, NX_CRYPTO_NULL, sizeof(curve), + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if (status != NX_CRYPTO_NOT_SUCCESSFUL) + { + test_control_return(1); + return; + } + unsupported_curve_method = *vectors[0].method; + unsupported_curve_method.nx_crypto_algorithm = NX_CRYPTO_EC_SECP256R1; + status = vectors[0].method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_GET, + NX_CRYPTO_NULL, &unsupported_curve_method, NX_CRYPTO_NULL, 0, + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, (UCHAR *)&curve, sizeof(curve), + NX_CRYPTO_NULL, 0, NX_CRYPTO_NULL, NX_CRYPTO_NULL); + if (status != NX_CRYPTO_NOT_SUCCESSFUL) + { + test_control_return(1); + return; + } + for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { curve = NX_CRYPTO_NULL; diff --git a/test/regression/nx_secure_test/nx_secure_tls_1_3_certverify_transcript_hash_test.c b/test/regression/nx_secure_test/nx_secure_tls_1_3_certverify_transcript_hash_test.c index fc95ea8eb..391358c36 100644 --- a/test/regression/nx_secure_test/nx_secure_tls_1_3_certverify_transcript_hash_test.c +++ b/test/regression/nx_secure_test/nx_secure_tls_1_3_certverify_transcript_hash_test.c @@ -65,6 +65,7 @@ extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers_ecc; static ULONG spy_captured_length; static UINT spy_call_count; +static UINT spy_hash_succeeds; /* Stand-in for the signature scheme's hash (SHA-384, 48-byte ICV). The caller drives hashing through three separate nx_crypto_operation calls -- HASH_INITIALIZE, HASH_UPDATE, @@ -90,6 +91,10 @@ static UINT spy_hash_operation(UINT op, VOID *handler, struct NX_CRYPTO_METHOD_S spy_captured_length = input_length_in_byte; spy_call_count++; } + if (spy_hash_succeeds) + { + return(NX_CRYPTO_SUCCESS); + } return(NX_CRYPTO_NOT_SUCCESSFUL); } @@ -120,7 +125,9 @@ static NX_CRYPTO_METHOD dummy_public_cipher_method = {0}; static NX_SECURE_X509_CRYPTO mismatched_hash_cipher_table[] = { /* OID identifier, public cipher, hash method */ + {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256, &dummy_public_cipher_method, &spy_hash_method_sha384}, {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384, &dummy_public_cipher_method, &spy_hash_method_sha384}, + {NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512, &dummy_public_cipher_method, &spy_hash_method_sha384}, }; /* Copy of TLS_AES_128_GCM_SHA256 with a SHA-384 hash, for configuration 2. See the header @@ -176,6 +183,15 @@ NX_SECURE_X509_CERT local_certificate; NX_SECURE_X509_CERT remote_certificate; const NX_SECURE_TLS_CIPHERSUITE_INFO *sha256_ciphersuite; USHORT priority; +UINT scheme_index; +const USHORT brainpool_schemes[] = +{ + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256, + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384, + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512, + NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256 +}; +NX_PACKET *packet; printf("NetX Secure Test: TLS 1.3 CertificateVerify Transcript Hash Length Test.."); @@ -224,7 +240,7 @@ USHORT priority; certificate_get(..., NX_NULL, ...) only matches identity certificates -- force it. */ local_certificate.nx_secure_x509_certificate_is_identity_cert = NX_CRYPTO_TRUE; local_certificate.nx_secure_x509_cipher_table = mismatched_hash_cipher_table; - local_certificate.nx_secure_x509_cipher_table_size = 1; + local_certificate.nx_secure_x509_cipher_table_size = sizeof(mismatched_hash_cipher_table) / sizeof(mismatched_hash_cipher_table[0]); tls_session.nx_secure_tls_credentials.nx_secure_tls_certificate_store = store; tls_session.nx_secure_tls_socket_type = NX_SECURE_TLS_SESSION_TYPE_CLIENT; @@ -236,6 +252,35 @@ USHORT priority; tls_session.nx_secure_tls_session_ciphersuite = &sha384_ciphersuite; check_send_side(&tls_session, 48); + /* A certificate's private key must use the curve named by its signature scheme. */ + local_certificate.nx_secure_x509_public_algorithm = NX_SECURE_TLS_X509_TYPE_EC; + local_certificate.nx_secure_x509_private_key.ec_private_key.nx_secure_ec_named_curve = 19; + tls_session.nx_secure_tls_session_ciphersuite = sha256_ciphersuite; + spy_hash_succeeds = NX_TRUE; + status = nx_packet_allocate(&pool_0, &packet, NX_TCP_PACKET, NX_WAIT_FOREVER); + EXPECT_EQ(NX_SUCCESS, status); + for (scheme_index = 0; scheme_index < 3u; scheme_index++) + { + tls_session.nx_secure_tls_signature_algorithm = brainpool_schemes[scheme_index]; + status = _nx_secure_tls_send_certificate_verify(&tls_session, packet); + EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG, status); + } + local_certificate.nx_secure_x509_private_key.ec_private_key.nx_secure_ec_named_curve = NX_CRYPTO_EC_BRAINPOOLP256r1; + tls_session.nx_secure_tls_signature_algorithm = brainpool_schemes[3]; + status = _nx_secure_tls_send_certificate_verify(&tls_session, packet); + EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG, status); + local_certificate.nx_secure_x509_private_key.ec_private_key.nx_secure_ec_named_curve = NX_CRYPTO_EC_BRAINPOOLP512r1 + 1u; + status = _nx_secure_tls_send_certificate_verify(&tls_session, packet); + EXPECT_EQ(NX_CRYTPO_MISSING_ECC_CURVE, status); + + tls_session.nx_secure_tls_1_3 = NX_FALSE; + tls_session.nx_secure_tls_protocol_version = NX_SECURE_TLS_VERSION_TLS_1_2; + status = _nx_secure_tls_send_certificate_verify(&tls_session, packet); + EXPECT_EQ(NX_CRYTPO_MISSING_ECC_CURVE, status); + tls_session.nx_secure_tls_1_3 = NX_TRUE; + nx_packet_release(packet); + spy_hash_succeeds = NX_FALSE; + /* ---- Process side: _nx_secure_tls_process_certificate_verify (TLS 1.3 server). ---- */ memset(&remote_certificate, 0, sizeof(remote_certificate)); @@ -246,7 +291,7 @@ USHORT priority; status = _nx_secure_x509_store_certificate_add(&remote_certificate, &store, NX_SECURE_X509_CERT_LOCATION_REMOTE); EXPECT_EQ(NX_SUCCESS, status); remote_certificate.nx_secure_x509_cipher_table = mismatched_hash_cipher_table; - remote_certificate.nx_secure_x509_cipher_table_size = 1; + remote_certificate.nx_secure_x509_cipher_table_size = sizeof(mismatched_hash_cipher_table) / sizeof(mismatched_hash_cipher_table[0]); tls_session.nx_secure_tls_credentials.nx_secure_tls_certificate_store = store; tls_session.nx_secure_tls_socket_type = NX_SECURE_TLS_SESSION_TYPE_SERVER; diff --git a/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c b/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c index dd5c4f0e1..915c4b627 100644 --- a/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c +++ b/test/regression/nx_secure_test/nx_secure_tls_clienthello_signature_algorithms_test.c @@ -120,6 +120,36 @@ static const UCHAR expected_tls_1_2_extension[TLS_1_2_EXTENSION_SIZE] = 0x04, 0x03, 0x05, 0x03, 0x06, 0x03 }; +static const UCHAR expected_certificate_request[] = +{ + 0x00, 0x00, 0x0E, 0x00, 0x0D, 0x00, 0x0A, 0x00, 0x08, + 0x04, 0x03, 0x08, 0x1A, 0x08, 0x1B, 0x08, 0x1C +}; + +static NX_SECURE_X509_CERT local_brainpool_cert; +static const UINT brainpool_curve_ids[] = +{ + NX_CRYPTO_EC_BRAINPOOLP256r1, + NX_CRYPTO_EC_BRAINPOOLP384r1, + NX_CRYPTO_EC_BRAINPOOLP512r1 +}; +static const UINT expected_brainpool_signatures[] = +{ + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256, + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384, + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512 +}; +static const USHORT expected_brainpool_x509_types[] = +{ + NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256, + NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384, + NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512 +}; +static UCHAR brainpool_signature_wire[] = +{ + 0x00, 0x06, 0x08, 0x1A, 0x08, 0x1B, 0x08, 0x1C +}; + #endif /**************************************************************************/ @@ -155,6 +185,10 @@ UINT oid_value; USHORT ecdhe_signature_algorithm; UCHAR groups_wire[4] = {0x00, 0x02, 0x00, 0x1F}; NX_SECURE_TLS_HELLO_EXTENSION groups_extension; +NX_SECURE_TLS_HELLO_EXTENSION signature_extension; +NX_PACKET certificate_request_packet; +UCHAR certificate_request_data[64]; +USHORT signature_id; NX_PARAMETER_NOT_USED(first_unused_memory); @@ -172,10 +206,47 @@ NX_SECURE_TLS_HELLO_EXTENSION groups_extension; (USHORT)(sizeof(supported_groups) / sizeof(supported_groups[0])); tls_session.nx_secure_tls_ecc.nx_secure_tls_ecc_curves = supported_curve_methods; + /* A TLS 1.3 certificate request advertises each supported Brainpool scheme. */ + memset(&certificate_request_packet, 0, sizeof(certificate_request_packet)); + certificate_request_packet.nx_packet_prepend_ptr = certificate_request_data; + certificate_request_packet.nx_packet_append_ptr = certificate_request_data; + certificate_request_packet.nx_packet_data_end = certificate_request_data + sizeof(certificate_request_data); + tls_session.nx_secure_tls_protocol_version = NX_SECURE_TLS_VERSION_TLS_1_2; + status = _nx_secure_tls_send_certificate_request(&tls_session, &certificate_request_packet); + EXPECT_EQ(NX_SUCCESS, status); + EXPECT_EQ(sizeof(expected_certificate_request), certificate_request_packet.nx_packet_length); + EXPECT_EQ(0, memcmp(certificate_request_data, expected_certificate_request, + sizeof(expected_certificate_request))); + memset(&local_brainpool_cert, 0, sizeof(local_brainpool_cert)); + local_brainpool_cert.nx_secure_x509_public_algorithm = NX_SECURE_TLS_X509_TYPE_EC; + tls_session.nx_secure_tls_credentials.nx_secure_tls_active_certificate = &local_brainpool_cert; + signature_extension.nx_secure_tls_extension_id = NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS; + signature_extension.nx_secure_tls_extension_data_length = sizeof(brainpool_signature_wire); + signature_extension.nx_secure_tls_extension_data = brainpool_signature_wire; + for (i = 0; i < 3U; i++) + { + local_brainpool_cert.nx_secure_x509_private_key.ec_private_key.nx_secure_ec_named_curve = + brainpool_curve_ids[i]; + status = _nx_secure_tls_process_certificate_request(&tls_session, certificate_request_data, + sizeof(expected_certificate_request)); + EXPECT_EQ(NX_SUCCESS, status); + EXPECT_EQ(expected_brainpool_signatures[i], tls_session.nx_secure_tls_signature_algorithm); + status = _nx_secure_tls_proc_clienthello_sec_sa_extension(&tls_session, &signature_extension, + 1U, &selected_curve, 0U, &cert_curve_supported, &ecdhe_signature_algorithm, NX_NULL); + EXPECT_EQ(NX_SUCCESS, status); + EXPECT_EQ(expected_brainpool_signatures[i], tls_session.nx_secure_tls_signature_algorithm); + signature_id = 0; + _nx_secure_tls_get_signature_algorithm_id(expected_brainpool_signatures[i], &signature_id); + EXPECT_EQ(expected_brainpool_x509_types[i], signature_id); + } + tls_session.nx_secure_tls_credentials.nx_secure_tls_active_certificate = NX_NULL; + tls_session.nx_secure_tls_protocol_version = 0; + /* RFC 8734 groups differ from the TLS 1.2 Brainpool identifiers. */ EXPECT_EQ(0x001Fu, _nx_secure_tls_brainpool_group_to_wire((USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1)); EXPECT_EQ(0x0020u, _nx_secure_tls_brainpool_group_to_wire((USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1)); EXPECT_EQ(0x0021u, _nx_secure_tls_brainpool_group_to_wire((USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1)); + EXPECT_EQ(0x0022u, _nx_secure_tls_brainpool_group_to_wire(0x0022u)); EXPECT_EQ((USHORT)NX_CRYPTO_EC_BRAINPOOLP256r1, _nx_secure_tls_brainpool_group_from_wire(0x001Fu)); EXPECT_EQ((USHORT)NX_CRYPTO_EC_BRAINPOOLP384r1, _nx_secure_tls_brainpool_group_from_wire(0x0020u)); EXPECT_EQ((USHORT)NX_CRYPTO_EC_BRAINPOOLP512r1, _nx_secure_tls_brainpool_group_from_wire(0x0021u)); @@ -233,6 +304,34 @@ NX_SECURE_TLS_HELLO_EXTENSION groups_extension; EXPECT_EQ(0xA5u, packet_buffer[TEST_PACKET_OFFSET - 1u]); EXPECT_EQ(0xA5u, packet_buffer[TEST_PACKET_OFFSET + TLS_1_3_EXTENSION_SIZE]); + /* Only usable ECDSA methods may advertise Brainpool signature schemes. */ + signature_methods[3].nx_secure_x509_public_cipher_method = NX_NULL; + packet_offset = TEST_PACKET_OFFSET; + extension_length = 0; + status = _nx_secure_tls_send_clienthello_sig_extension(&tls_session, packet_buffer, + &packet_offset, &extension_length, + sizeof(packet_buffer)); + EXPECT_EQ(NX_SUCCESS, status); + signature_methods[3].nx_secure_x509_public_cipher_method = &ecdsa_method; + + signature_methods[3].nx_secure_x509_hash_method = NX_NULL; + packet_offset = TEST_PACKET_OFFSET; + extension_length = 0; + status = _nx_secure_tls_send_clienthello_sig_extension(&tls_session, packet_buffer, + &packet_offset, &extension_length, + sizeof(packet_buffer)); + EXPECT_EQ(NX_SUCCESS, status); + signature_methods[3].nx_secure_x509_hash_method = &sha256_method; + + signature_methods[4].nx_secure_x509_public_cipher_method = &unsupported_method; + packet_offset = TEST_PACKET_OFFSET; + extension_length = 0; + status = _nx_secure_tls_send_clienthello_sig_extension(&tls_session, packet_buffer, + &packet_offset, &extension_length, + sizeof(packet_buffer)); + EXPECT_EQ(NX_SUCCESS, status); + signature_methods[4].nx_secure_x509_public_cipher_method = &ecdsa_method; + /* Disabling TLS 1.3 retains the original TLS 1.2-only list. */ memset(packet_buffer, 0xA5, sizeof(packet_buffer)); tls_session.nx_secure_tls_1_3 = NX_FALSE; diff --git a/test/regression/nx_secure_test/nx_secure_tls_process_certificate_verify_test.c b/test/regression/nx_secure_test/nx_secure_tls_process_certificate_verify_test.c index cb3dac5a8..800d849f7 100644 --- a/test/regression/nx_secure_test/nx_secure_tls_process_certificate_verify_test.c +++ b/test/regression/nx_secure_test/nx_secure_tls_process_certificate_verify_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Portions of this file were generated with AI assistance. + /* This test concentrates on TLS ECC ciphersuites negotiation. */ #include "nx_api.h" @@ -114,7 +116,7 @@ static UINT test_crypto_operation_success(UINT op, /* Encrypt, Decrypt, Au VOID *packet_ptr, VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status)) { - if(output) + if(output && output_length_in_byte >= 2u) { output[0] = 1; output[1] = 1; @@ -161,6 +163,16 @@ NX_SECURE_TLS_SESSION tls_session; UCHAR buffer[256]; NX_SECURE_X509_CERTIFICATE_STORE store; NX_SECURE_X509_CERT certificate; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +UINT i; +UINT saved_curve; +const USHORT brainpool_schemes[] = +{ + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256, + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP384R1_SHA384, + NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP512R1_SHA512 +}; +#endif /* Print out test information banner. */ printf("NetX Secure Test: TLS Process Certificate Verify Test...................."); @@ -193,6 +205,19 @@ NX_SECURE_X509_CERT certificate; certificate.nx_secure_x509_cipher_table_size = 1; tls_session.nx_secure_tls_credentials.nx_secure_tls_certificate_store = store; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + /* Unsupported Brainpool schemes must fail before signature decoding. */ + tls_session.nx_secure_tls_1_3 = NX_TRUE; + for (i = 0; i < sizeof(brainpool_schemes) / sizeof(brainpool_schemes[0]); i++) + { + buffer[0] = (UCHAR)(brainpool_schemes[i] >> 8); + buffer[1] = (UCHAR)brainpool_schemes[i]; + status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); + EXPECT_EQ(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM, status); + } + tls_session.nx_secure_tls_1_3 = NX_FALSE; +#endif + status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION, status); @@ -242,6 +267,41 @@ NX_SECURE_X509_CERT certificate; certificate.nx_secure_x509_cipher_table_size = 1; test_x509_cipher_table->nx_secure_x509_crypto_identifier = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + /* A Brainpool signature scheme must match the certificate's named curve. */ + tls_session.nx_secure_tls_1_3 = NX_TRUE; + test_x509_hash_method.nx_crypto_ICV_size_in_bits = 256; + test_x509_hash_method.nx_crypto_operation = test_crypto_operation_success; + buffer[0] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256 >> 8); + buffer[1] = (UCHAR)NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256; + buffer[2] = 0; + buffer[3] = 0; + status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); + EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG, status); + + saved_curve = certificate.nx_secure_x509_public_key.ec_public_key.nx_secure_ec_named_curve; + certificate.nx_secure_x509_public_key.ec_public_key.nx_secure_ec_named_curve = NX_CRYPTO_EC_BRAINPOOLP256r1; + buffer[0] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256 >> 8); + buffer[1] = (UCHAR)NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256; + status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); + EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG, status); + + buffer[0] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256 >> 8); + buffer[1] = (UCHAR)NX_SECURE_TLS_SIGNATURE_ECDSA_BRAINPOOLP256R1_SHA256; + status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); + EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE, status); + + certificate.nx_secure_x509_public_key.ec_public_key.nx_secure_ec_named_curve = NX_CRYPTO_EC_BRAINPOOLP512r1 + 1u; + buffer[0] = (UCHAR)(NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256 >> 8); + buffer[1] = (UCHAR)NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256; + status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); + EXPECT_EQ(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE, status); + + certificate.nx_secure_x509_public_key.ec_public_key.nx_secure_ec_named_curve = saved_curve; + test_x509_hash_method.nx_crypto_operation = NX_NULL; + tls_session.nx_secure_tls_1_3 = NX_FALSE; + buffer[2] = 1; +#endif buffer[0] = 0; buffer[1] = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; status = _nx_secure_tls_process_certificate_verify(&tls_session, buffer, sizeof(buffer)); From 5c14d2c0d11e23306453559331bb6cd254783adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 16 Oct 2026 17:00:08 -0400 Subject: [PATCH 4/4] Selected Brainpool doubling by explicit curve IDs The projective doubling path selected the general formula by a numeric curve ID range. That range depended on the current ID assignments and left an unreachable upper-bound branch in the available prime-field curves. Match each supported Brainpool curve ID explicitly. This keeps future curve IDs from selecting the general formula solely because they fall in that range. GCC 14 CMake/Ninja suites passed 35/35 standalone crypto, 35/35 crypto coverage, 188/188 default Secure, and 164/164 TLS 1.3 Secure. Changed production code reached 176/176 lines and 80/80 branches. Not run on hardware. Assisted-by: Codex (GPT-6) --- crypto_libraries/src/nx_crypto_ec.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crypto_libraries/src/nx_crypto_ec.c b/crypto_libraries/src/nx_crypto_ec.c index 39890a39d..8da364742 100644 --- a/crypto_libraries/src/nx_crypto_ec.c +++ b/crypto_libraries/src/nx_crypto_ec.c @@ -2575,8 +2575,9 @@ UINT buffer_size; /* C = 3 * X1^2 + a * Z1^4; use the shorter form for a = -3 curves. */ NX_CRYPTO_EC_SQUARE_REDUCE(curve, &projective_point -> nx_crypto_ec_point_z, &temp3, scratch); - if ((curve -> nx_crypto_ec_id >= NX_CRYPTO_EC_BRAINPOOLP256r1) && - (curve -> nx_crypto_ec_id <= NX_CRYPTO_EC_BRAINPOOLP512r1)) + if ((curve -> nx_crypto_ec_id == NX_CRYPTO_EC_BRAINPOOLP256r1) || + (curve -> nx_crypto_ec_id == NX_CRYPTO_EC_BRAINPOOLP384r1) || + (curve -> nx_crypto_ec_id == NX_CRYPTO_EC_BRAINPOOLP512r1)) { NX_CRYPTO_EC_SQUARE_REDUCE(curve, &temp3, &temp4, scratch); NX_CRYPTO_EC_MULTIPLE_REDUCE(curve, &temp4, &curve -> nx_crypto_ec_a,