[PATCH 2 of 2] SSL: add $ssl_curve when using AWS-LC

Sergey Kandaurov pluknet at nginx.com
Mon Mar 25 15:45:05 UTC 2024


On Wed, Feb 28, 2024 at 01:22:15AM +0000, Piotr Sikora via nginx-devel wrote:
> # HG changeset patch
> # User Piotr Sikora <piotr at aviatrix.com>
> # Date 1708977632 0
> #      Mon Feb 26 20:00:32 2024 +0000
> # Branch patch009
> # Node ID dfffc67d286b788204f60701ef4179566d933a1b
> # Parent  5e923992006199748e79b08b1e65c4ef41f07495
> SSL: add $ssl_curve when using AWS-LC.
> 
> Signed-off-by: Piotr Sikora <piotr at aviatrix.com>

Not sure nginx needs such complexity.
Instead, I'd expect the missing API to be added to the library,
especially that both parent and grandparent implement it.

BoringSSL didn't have such API for quite some time until recently.
Since AWS-LC is a fork of BoringSSL, it is welcome to sync up.
As far as I can see, they used to sync quite often, so it is ought
to be resolved automagically after the next sync.  To ease to task,
here I provide certain git hashes:

6cf98208371e5c2c8b9d34ce3b8c452ea90e2963 - SSL_get_negotiated_group
28c24092e39bfd70852afa2923a3d12d2e9be2f5 - TLSEXT_nid_unknown

Minimalistic version of the patch for AWS-LC would be:

diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 7bcef522c..40075bc0a 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2622,6 +2622,10 @@ OPENSSL_EXPORT int SSL_CTX_set1_groups_list(SSL_CTX *ctx, const char *groups);
 // failure.
 OPENSSL_EXPORT int SSL_set1_groups_list(SSL *ssl, const char *groups);
 
+// SSL_get_negotiated_group returns the NID of the group used by |ssl|'s most
+// recently completed handshake, or |NID_undef| if not applicable.
+OPENSSL_EXPORT int SSL_get_negotiated_group(const SSL *ssl);
+
 // SSL_GROUP_* define TLS group IDs.
 #define SSL_GROUP_SECP224R1 21
 #define SSL_GROUP_SECP256R1 23
@@ -5627,6 +5631,11 @@ OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
 #define SSL_CURVE_SECP256R1_KYBER768_DRAFT00 SSL_GROUP_SECP256R1_KYBER768_DRAFT00
 #define SSL_CURVE_X25519_KYBER768_DRAFT00 SSL_GROUP_X25519_KYBER768_DRAFT00
 
+// TLSEXT_nid_unknown is a constant used in OpenSSL for
+// |SSL_get_negotiated_group| to return an unrecognized group. BoringSSL never
+// returns this value, but we define this constant for compatibility.
+#define TLSEXT_nid_unknown 0x1000000
+
 // SSL_get_curve_id calls |SSL_get_group_id|.
 OPENSSL_EXPORT uint16_t SSL_get_curve_id(const SSL *ssl);
 
@@ -5784,6 +5793,7 @@ OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
 #define SSL_get0_chain_certs SSL_get0_chain_certs
 #define SSL_get_max_cert_list SSL_get_max_cert_list
 #define SSL_get_mode SSL_get_mode
+#define SSL_get_negotiated_group SSL_get_negotiated_group
 #define SSL_get_options SSL_get_options
 #define SSL_get_secure_renegotiation_support \
   SSL_get_secure_renegotiation_support
diff --git a/ssl/internal.h b/ssl/internal.h
index 573613f72..3ce6387b5 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1237,6 +1237,10 @@ bool ssl_nid_to_group_id(uint16_t *out_group_id, int nid);
 // true. Otherwise, it returns false.
 bool ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len);
 
+// ssl_group_id_to_nid returns the NID corresponding to |group_id| or
+// |NID_undef| if unknown.
+int ssl_group_id_to_nid(uint16_t group_id);
+
 
 // Handshake messages.
 
diff --git a/ssl/ssl_key_share.cc b/ssl/ssl_key_share.cc
index 7a5b2c7bb..68f8a67c7 100644
--- a/ssl/ssl_key_share.cc
+++ b/ssl/ssl_key_share.cc
@@ -778,6 +778,15 @@ bool ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len)
   return false;
 }
 
+int ssl_group_id_to_nid(uint16_t group_id) {
+  for (const auto &group : kNamedGroups) {
+    if (group.group_id == group_id) {
+      return group.nid;
+    }
+  }
+  return NID_undef;
+}
+
 BSSL_NAMESPACE_END
 
 using namespace bssl;
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
index 1069db201..17ed5224a 100644
--- a/ssl/ssl_lib.cc
+++ b/ssl/ssl_lib.cc
@@ -2082,6 +2082,14 @@ uint16_t SSL_get_group_id(const SSL *ssl) {
   return session->group_id;
 }
 
+int SSL_get_negotiated_group(const SSL *ssl) {
+  uint16_t group_id = SSL_get_group_id(ssl);
+  if (group_id == 0) {
+    return NID_undef;
+  }
+  return ssl_group_id_to_nid(group_id);
+}
+
 int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) { return 1; }
 
 int SSL_set_tmp_dh(SSL *ssl, const DH *dh) { return 1; }

> 
> diff -r 5e9239920061 -r dfffc67d286b src/event/ngx_event_openssl.c
> --- a/src/event/ngx_event_openssl.c	Mon Feb 26 20:00:30 2024 +0000
> +++ b/src/event/ngx_event_openssl.c	Mon Feb 26 20:00:32 2024 +0000
> @@ -5163,6 +5163,72 @@
>          return NGX_OK;
>      }
>  
> +#elif defined(OPENSSL_IS_AWSLC)
> +
> +    uint16_t  curve_id;
> +
> +    curve_id = SSL_get_curve_id(c->ssl->connection);
> +
> +    /*
> +     * Hardcoded table with ANSI / SECG curve names (e.g. "prime256v1"),
> +     * which is the same format that OpenSSL returns for $ssl_curve.
> +     *
> +     * Without this table, we'd need to make 3 additional library calls
> +     * to convert from curve_id to ANSI / SECG curve name:
> +     *
> +     *     nist_name = SSL_get_curve_name(curve_id);
> +     *     nid = EC_curve_nist2nid(nist_name);
> +     *     ansi_name = OBJ_nid2sn(nid);
> +     */
> +
> +    switch (curve_id) {
> +
> +#ifdef SSL_CURVE_SECP224R1
> +    case SSL_CURVE_SECP224R1:
> +        ngx_str_set(s, "secp224r1");
> +        return NGX_OK;
> +#endif
> +
> +#ifdef SSL_CURVE_SECP256R1
> +    case SSL_CURVE_SECP256R1:
> +        ngx_str_set(s, "prime256v1");
> +        return NGX_OK;
> +#endif
> +
> +#ifdef SSL_CURVE_SECP384R1
> +    case SSL_CURVE_SECP384R1:
> +        ngx_str_set(s, "secp384r1");
> +        return NGX_OK;
> +#endif
> +
> +#ifdef SSL_CURVE_SECP521R1
> +    case SSL_CURVE_SECP521R1:
> +        ngx_str_set(s, "secp521r1");
> +        return NGX_OK;
> +#endif
> +
> +#ifdef SSL_CURVE_X25519
> +    case SSL_CURVE_X25519:
> +        ngx_str_set(s, "x25519");
> +        return NGX_OK;
> +#endif
> +
> +    case 0:
> +        break;
> +
> +    default:
> +        s->len = sizeof("0x0000") - 1;
> +
> +        s->data = ngx_pnalloc(pool, s->len);
> +        if (s->data == NULL) {
> +            return NGX_ERROR;
> +        }
> +
> +        ngx_sprintf(s->data, "0x%04xd", curve_id);
> +
> +        return NGX_OK;
> +    }
> +
>  #endif
>  
>      ngx_str_null(s);
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> https://mailman.nginx.org/mailman/listinfo/nginx-devel


More information about the nginx-devel mailing list