]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add SSL_CTX_set_ec_point_formats() and SSL_set_ec_point_formats()
authorTim Perry <pimterry@gmail.com>
Thu, 6 Mar 2025 13:33:17 +0000 (14:33 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 14 Apr 2025 13:56:40 +0000 (14:56 +0100)
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 <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26990)

CHANGES.md
doc/man3/SSL_CTX_set_options.pod
include/openssl/ssl.h.in
ssl/ssl_conf.c
ssl/t1_lib.c
test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt
test/recipes/75-test_quicapi_data/ssltraceref.txt
test/ssl-tests/20-cert-select.cnf
test/ssl-tests/20-cert-select.cnf.in
test/sslapitest.c

index 7fe2e3b2b201ff7c8de148de44236603f1154dd3..a66ce7654dcdfbbe6a439858c8c43e62bad27317 100644 (file)
@@ -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
 -----------
 
index a6c922ecf92cc0013feef06c10623c416308fb42..c9733525811ff1e89790bf38526e4ecdb7149d49 100644 (file)
@@ -228,6 +228,12 @@ For more information on shutting down a connection, see L<SSL_shutdown(3)>.
 Allow legacy insecure renegotiation between OpenSSL and unpatched servers
 B<only>. See the B<SECURE RENEGOTIATION> 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),
index b3420799683b5ae8264a48ea65a9606695b97f1a..54e00623f98c5857142a767fe8d9ff6b8ad65370 100644 (file)
@@ -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."
index 946d20be527ccb33b858b5e600fab9949ee2957c..070ab73f82b91f2adf66e8e03b514118285b3145 100644 (file)
@@ -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)
index 8d0c2647b79cfa0e4f59c3092199dacc1b8351a3..5a7201b7a245b5589d2c09537d46b890e22f5ef8 100644 (file)
@@ -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);
     }
 }
 
index 44b0aef74b310dec80c8767b8da1a09ac9206eb8..d36d58772b87653138cfefd97e71140830950711 100644 (file)
@@ -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)
index 2a625ae506973ebb448a395196367e945420e601..7b7fa28c08871bc51ba4a719ed53237711871fe3 100644 (file)
@@ -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)
index d43a44282c5b9ba1ffe0c3478cee28977fffaa0e..12c0de1e790f5867120cdf03ac3075b89ba41a7a 100644 (file)
@@ -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
index af47842fd863079f83dac417eba8bfab5591d2ab..c3d006205021d5436c87980f8a6a22bdcd8bc63e 100644 (file)
@@ -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",
index 38d58e938743efa69e918c41d50db8e3052c5362..7b13b799bf04870646de6f6f15ab12aff08c94e6 100644 (file)
@@ -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);