]> git.kaiwu.me - nginx.git/commitdiff
SSL: external groups support in $ssl_curve and $ssl_curves.
authorSergey Kandaurov <pluknet@nginx.com>
Thu, 3 Apr 2025 11:29:31 +0000 (15:29 +0400)
committerpluknet <pluknet@nginx.com>
Thu, 10 Apr 2025 14:51:10 +0000 (18:51 +0400)
Starting with OpenSSL 3.0, groups may be added externally with pluggable
KEM providers.  Using SSL_get_negotiated_group(), which makes lookup in a
static table with known groups, doesn't allow to list such groups by names
leaving them in hex.  Adding X25519MLKEM768 to the default group list in
OpenSSL 3.5 made this problem more visible.  SSL_get0_group_name() and,
apparently, SSL_group_to_name() allow to resolve such provider-implemented
groups, which is also "generally preferred" over SSL_get_negotiated_group()
as documented in OpenSSL git commit 93d4f6133f.

This change makes external groups listing by name using SSL_group_to_name()
available since OpenSSL 3.0.  To preserve "prime256v1" naming for the group
0x0017, and to avoid breaking BoringSSL and older OpenSSL versions support,
it is used supplementary for a group that appears to be unknown.

See https://github.com/openssl/openssl/issues/27137 for related discussion.

src/event/ngx_event_openssl.c

index 865c78540a3bf652197c37bf1522be893937b4f3..6992cc4a4697d49304413ea90e101ed07e13dce8 100644 (file)
@@ -5040,7 +5040,8 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
 {
 #ifdef SSL_get_negotiated_group
 
-    int  nid;
+    int          nid;
+    const char  *name;
 
     nid = SSL_get_negotiated_group(c->ssl->connection);
 
@@ -5052,14 +5053,24 @@ ngx_ssl_get_curve(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
             return NGX_OK;
         }
 
-        s->len = sizeof("0x0000") - 1;
+#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
+        name = SSL_group_to_name(c->ssl->connection, nid);
+#else
+        name = NULL;
+#endif
 
+        s->len = name ? ngx_strlen(name) : sizeof("0x0000") - 1;
         s->data = ngx_pnalloc(pool, s->len);
         if (s->data == NULL) {
             return NGX_ERROR;
         }
 
-        ngx_sprintf(s->data, "0x%04xd", nid & 0xffff);
+        if (name) {
+            ngx_memcpy(s->data, name, s->len);
+
+        } else {
+            ngx_sprintf(s->data, "0x%04xd", nid & 0xffff);
+        }
 
         return NGX_OK;
     }
@@ -5079,6 +5090,7 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
     int         *curves, n, i, nid;
     u_char      *p;
     size_t       len;
+    const char  *name;
 
     n = SSL_get1_curves(c->ssl->connection, NULL);
 
@@ -5099,7 +5111,13 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
         nid = curves[i];
 
         if (nid & TLSEXT_nid_unknown) {
-            len += sizeof("0x0000") - 1;
+#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
+            name = SSL_group_to_name(c->ssl->connection, nid);
+#else
+            name = NULL;
+#endif
+
+            len += name ? ngx_strlen(name) : sizeof("0x0000") - 1;
 
         } else {
             len += ngx_strlen(OBJ_nid2sn(nid));
@@ -5119,7 +5137,14 @@ ngx_ssl_get_curves(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
         nid = curves[i];
 
         if (nid & TLSEXT_nid_unknown) {
-            p = ngx_sprintf(p, "0x%04xd", nid & 0xffff);
+#if (OPENSSL_VERSION_NUMBER >= 0x3000000fL)
+            name = SSL_group_to_name(c->ssl->connection, nid);
+#else
+            name = NULL;
+#endif
+
+            p = name ? ngx_cpymem(p, name, ngx_strlen(name))
+                     : ngx_sprintf(p, "0x%04xd", nid & 0xffff);
 
         } else {
             p = ngx_sprintf(p, "%s", OBJ_nid2sn(nid));