From: Tim Perry Date: Thu, 6 Mar 2025 13:33:17 +0000 (+0100) Subject: Add SSL_CTX_set_ec_point_formats() and SSL_set_ec_point_formats() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03541d7302d016aa28d436364d72d58baa3e2114;p=thirdparty%2Fopenssl.git Add SSL_CTX_set_ec_point_formats() and SSL_set_ec_point_formats() The internal fields and implementation for configuration of this parameter already existed, but was not exposed. This change adds simple setters to allow configuration of this field. Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/26990) --- diff --git a/CHANGES.md b/CHANGES.md index 7fe2e3b2b20..a66ce7654dc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -57,6 +57,12 @@ OpenSSL 3.6 *Adrian Stanciu* + * Change default EC point formats configuration to support only 'uncompressed' + format, and add SSL_OP_LEGACY_EC_POINT_FORMATS flag and options to re-enable + previous default if required. + + *Tim Perry* + OpenSSL 3.5 ----------- diff --git a/doc/man3/SSL_CTX_set_options.pod b/doc/man3/SSL_CTX_set_options.pod index a6c922ecf92..c9733525811 100644 --- a/doc/man3/SSL_CTX_set_options.pod +++ b/doc/man3/SSL_CTX_set_options.pod @@ -228,6 +228,12 @@ For more information on shutting down a connection, see L. Allow legacy insecure renegotiation between OpenSSL and unpatched servers B. See the B section for more details. +=item SSL_OP_LEGACY_EC_POINT_FORMATS + +Enable use of the legacy point formats for elliptic curves. This option enables +support for the deprecated ANSI X9.62 prime and char2 compressed point formats, +in addition to the uncompressed format that is enabled by default. + =item SSL_OP_NO_ANTI_REPLAY By default, when a server is configured for early data (i.e., max_early_data > 0), diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in index b3420799683..54e00623f98 100644 --- a/include/openssl/ssl.h.in +++ b/include/openssl/ssl.h.in @@ -423,8 +423,8 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg); # define SSL_OP_NO_RX_CERTIFICATE_COMPRESSION SSL_OP_BIT(33) /* Enable KTLS TX zerocopy on Linux */ # define SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE SSL_OP_BIT(34) - -#define SSL_OP_PREFER_NO_DHE_KEX SSL_OP_BIT(35) +# define SSL_OP_PREFER_NO_DHE_KEX SSL_OP_BIT(35) +# define SSL_OP_LEGACY_EC_POINT_FORMATS SSL_OP_BIT(36) /* * Option "collections." diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c index 946d20be527..070ab73f82b 100644 --- a/ssl/ssl_conf.c +++ b/ssl/ssl_conf.c @@ -408,6 +408,7 @@ static int cmd_Options(SSL_CONF_CTX *cctx, const char *value) SSL_FLAG_TBL_INV("RxCertificateCompression", SSL_OP_NO_RX_CERTIFICATE_COMPRESSION), SSL_FLAG_TBL("KTLSTxZerocopySendfile", SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE), SSL_FLAG_TBL("IgnoreUnexpectedEOF", SSL_OP_IGNORE_UNEXPECTED_EOF), + SSL_FLAG_TBL("LegacyECPointFormats", SSL_OP_LEGACY_EC_POINT_FORMATS), }; if (value == NULL) return -3; @@ -771,6 +772,7 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = { SSL_CONF_CMD_SWITCH("no_anti_replay", SSL_CONF_FLAG_SERVER), SSL_CONF_CMD_SWITCH("no_etm", 0), SSL_CONF_CMD_SWITCH("no_ems", 0), + SSL_CONF_CMD_SWITCH("legacy_ec_point_formats", 0), SSL_CONF_CMD_STRING(SignatureAlgorithms, "sigalgs", 0), SSL_CONF_CMD_STRING(ClientSignatureAlgorithms, "client_sigalgs", 0), SSL_CONF_CMD_STRING(Curves, "curves", 0), @@ -870,6 +872,8 @@ static const ssl_switch_tbl ssl_cmd_switches[] = { {SSL_OP_NO_ENCRYPT_THEN_MAC, 0}, /* no Extended master secret */ {SSL_OP_NO_EXTENDED_MASTER_SECRET, 0}, + /* enable legacy EC point formats */ + {SSL_OP_LEGACY_EC_POINT_FORMATS, 0} }; static int ssl_conf_cmd_skip_prefix(SSL_CONF_CTX *cctx, const char **pcmd) diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index 8d0c2647b79..5a7201b7a24 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -194,6 +194,10 @@ static const struct { }; static const unsigned char ecformats_default[] = { + TLSEXT_ECPOINTFORMAT_uncompressed +}; + +static const unsigned char ecformats_all[] = { TLSEXT_ECPOINTFORMAT_uncompressed, TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime, TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 @@ -1767,13 +1771,16 @@ void tls1_get_formatlist(SSL_CONNECTION *s, const unsigned char **pformats, if (s->ext.ecpointformats) { *pformats = s->ext.ecpointformats; *num_formats = s->ext.ecpointformats_len; - } else { - *pformats = ecformats_default; + } else if ((s->options & SSL_OP_LEGACY_EC_POINT_FORMATS) != 0) { + *pformats = ecformats_all; /* For Suite B we don't support char2 fields */ if (tls1_suiteb(s)) - *num_formats = sizeof(ecformats_default) - 1; + *num_formats = sizeof(ecformats_all) - 1; else - *num_formats = sizeof(ecformats_default); + *num_formats = sizeof(ecformats_all); + } else { + *pformats = ecformats_default; + *num_formats = sizeof(ecformats_default); } } diff --git a/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt b/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt index 44b0aef74b3..d36d58772b8 100644 --- a/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt +++ b/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt @@ -19,10 +19,8 @@ Header: 000f - 01 02 04 04 80 0c 00 00-05 04 80 08 00 00 06 ............... 001e - 04 80 08 00 00 07 04 80-08 00 00 08 02 40 64 .............@d 002d - 09 02 40 64 ..@d - extension_type=ec_point_formats(11), length=4 + extension_type=ec_point_formats(11), length=2 uncompressed (0) - ansiX962_compressed_prime (1) - ansiX962_compressed_char2 (2) extension_type=supported_groups(10), length=18 X25519MLKEM768 (4588) ecdh_x25519 (29) diff --git a/test/recipes/75-test_quicapi_data/ssltraceref.txt b/test/recipes/75-test_quicapi_data/ssltraceref.txt index 2a625ae5069..7b7fa28c088 100644 --- a/test/recipes/75-test_quicapi_data/ssltraceref.txt +++ b/test/recipes/75-test_quicapi_data/ssltraceref.txt @@ -19,10 +19,8 @@ Header: 000f - 01 02 04 04 80 0c 00 00-05 04 80 08 00 00 06 ............... 001e - 04 80 08 00 00 07 04 80-08 00 00 08 02 40 64 .............@d 002d - 09 02 40 64 ..@d - extension_type=ec_point_formats(11), length=4 + extension_type=ec_point_formats(11), length=2 uncompressed (0) - ansiX962_compressed_prime (1) - ansiX962_compressed_char2 (2) extension_type=supported_groups(10), length=18 X25519MLKEM768 (4588) ecdh_x25519 (29) diff --git a/test/ssl-tests/20-cert-select.cnf b/test/ssl-tests/20-cert-select.cnf index d43a44282c5..12c0de1e790 100644 --- a/test/ssl-tests/20-cert-select.cnf +++ b/test/ssl-tests/20-cert-select.cnf @@ -334,10 +334,12 @@ CipherString = DEFAULT ECDSA.Certificate = ${ENV::TEST_CERTS_DIR}/server-cecdsa-cert.pem ECDSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/server-cecdsa-key.pem MaxProtocol = TLSv1.2 +Options = LegacyECPointFormats PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem [8-ECDSA Signature Algorithm Selection compressed point-client] CipherString = DEFAULT +Options = LegacyECPointFormats SignatureAlgorithms = EcDsA+SHA256 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem VerifyMode = Peer diff --git a/test/ssl-tests/20-cert-select.cnf.in b/test/ssl-tests/20-cert-select.cnf.in index af47842fd86..c3d00620502 100644 --- a/test/ssl-tests/20-cert-select.cnf.in +++ b/test/ssl-tests/20-cert-select.cnf.in @@ -207,10 +207,12 @@ our @tests = ( server => { "ECDSA.Certificate" => test_pem("server-cecdsa-cert.pem"), "ECDSA.PrivateKey" => test_pem("server-cecdsa-key.pem"), - "MaxProtocol" => "TLSv1.2" + "MaxProtocol" => "TLSv1.2", + "Options" => "LegacyECPointFormats" }, client => { "SignatureAlgorithms" => randcase("ECDSA+SHA256"), + "Options" => "LegacyECPointFormats" }, test => { "ExpectedServerCertType" => "P-256", diff --git a/test/sslapitest.c b/test/sslapitest.c index 38d58e93874..7b13b799bf0 100644 --- a/test/sslapitest.c +++ b/test/sslapitest.c @@ -10995,6 +10995,55 @@ end: return testresult; } +#if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_TLS1_2) +/* + * Complete a connection with legacy EC point format configuration + */ +static int test_legacy_ec_point_formats(void) +{ + SSL_CTX *cctx = NULL, *sctx = NULL; + SSL *clientssl = NULL, *serverssl = NULL; + const char *pformats = NULL; + int nformats; + int testresult = 0; + + if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(), + TLS1_2_VERSION, TLS1_2_VERSION, &sctx, &cctx, cert, + privkey))) + goto end; + + if (!TEST_true(SSL_CTX_set_options(sctx, SSL_OP_LEGACY_EC_POINT_FORMATS))) + goto end; + + if (!TEST_true(SSL_CTX_set_options(cctx, SSL_OP_LEGACY_EC_POINT_FORMATS))) + goto end; + + if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL, NULL))) + goto end; + + if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) + goto end; + + /* Check server received all 3 point formats */ + nformats = SSL_get0_ec_point_formats(serverssl, &pformats); + if (!TEST_int_eq(nformats, 3)) + goto end; + if (!TEST_int_eq(pformats[0], TLSEXT_ECPOINTFORMAT_uncompressed) || + !TEST_int_eq(pformats[1], TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime) || + !TEST_int_eq(pformats[2], TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2)) + goto end; + + testresult = 1; + +end: + SSL_free(serverssl); + SSL_free(clientssl); + SSL_CTX_free(sctx); + SSL_CTX_free(cctx); + return testresult; +} +#endif + /* * Test SSL_CTX_set1_verify/chain_cert_store and SSL_CTX_get_verify/chain_cert_store. */ @@ -13341,6 +13390,9 @@ int setup_tests(void) #endif ADD_TEST(test_inherit_verify_param); ADD_TEST(test_set_alpn); +#if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_TLS1_2) + ADD_TEST(test_legacy_ec_point_formats); +#endif ADD_TEST(test_set_verify_cert_store_ssl_ctx); ADD_TEST(test_set_verify_cert_store_ssl); ADD_ALL_TESTS(test_session_timeout, 1);