Allow provider sigalgs in SignatureAlgorithms conf
authorAlex Bozarth <ajbozart@us.ibm.com>
Mon, 20 Nov 2023 21:20:31 +0000 (15:20 -0600)
committerDmitry Belyavskiy <beldmit@gmail.com>
Fri, 29 Mar 2024 20:54:38 +0000 (21:54 +0100)
Though support for provider-based signature algorithms was added in
ee58915 this functionality did not work with the SignatureAlgorithms
configuration command. If SignatureAlgorithms is set then the provider
sigalgs are not used and instead it used the default value.

This PR adds a check against the provider-base sigalg list when parsing
the SignatureAlgorithms value.

Based-on-patch-by: Martin Schmatz <mrt@zurich.ibm.com>
Fixes #22761

Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/22779)

ssl/s3_lib.c
ssl/ssl_lib.c
ssl/ssl_local.h
ssl/t1_lib.c

index d1497b115bc0c91a111cf70d5860406716b9a8d3..3604d282e88450706616cc1655f036d366a8e587 100644 (file)
@@ -3685,13 +3685,13 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
         return tls1_set_sigalgs(sc->cert, parg, larg, 0);
 
     case SSL_CTRL_SET_SIGALGS_LIST:
-        return tls1_set_sigalgs_list(sc->cert, parg, 0);
+        return tls1_set_sigalgs_list(s->ctx, sc->cert, parg, 0);
 
     case SSL_CTRL_SET_CLIENT_SIGALGS:
         return tls1_set_sigalgs(sc->cert, parg, larg, 1);
 
     case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
-        return tls1_set_sigalgs_list(sc->cert, parg, 1);
+        return tls1_set_sigalgs_list(s->ctx, sc->cert, parg, 1);
 
     case SSL_CTRL_GET_CLIENT_CERT_TYPES:
         {
@@ -3968,13 +3968,13 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
         return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
 
     case SSL_CTRL_SET_SIGALGS_LIST:
-        return tls1_set_sigalgs_list(ctx->cert, parg, 0);
+        return tls1_set_sigalgs_list(ctx, ctx->cert, parg, 0);
 
     case SSL_CTRL_SET_CLIENT_SIGALGS:
         return tls1_set_sigalgs(ctx->cert, parg, larg, 1);
 
     case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
-        return tls1_set_sigalgs_list(ctx->cert, parg, 1);
+        return tls1_set_sigalgs_list(ctx, ctx->cert, parg, 1);
 
     case SSL_CTRL_SET_CLIENT_CERT_TYPES:
         return ssl3_set_req_cert_type(ctx->cert, parg, larg);
index ecd105d35d7c862190ddbc33f7e3930c70b2de74..4c17576ebdee2728f5b115bc1c655538819b75c1 100644 (file)
@@ -3061,7 +3061,7 @@ long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
             return tls1_set_groups_list(ctx, NULL, NULL, parg);
         case SSL_CTRL_SET_SIGALGS_LIST:
         case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
-            return tls1_set_sigalgs_list(NULL, parg, 0);
+            return tls1_set_sigalgs_list(ctx, NULL, parg, 0);
         default:
             return 0;
         }
index cae0c1202b267d9f4651d638b87a52095213090f..5add83d1ff42798cd07fa164d40d22da87f414fa 100644 (file)
@@ -2801,7 +2801,7 @@ __owur int tls_use_ticket(SSL_CONNECTION *s);
 
 void ssl_set_sig_mask(uint32_t *pmask_a, SSL_CONNECTION *s, int op);
 
-__owur int tls1_set_sigalgs_list(CERT *c, const char *str, int client);
+__owur int tls1_set_sigalgs_list(SSL_CTX *ctx, CERT *c, const char *str, int client);
 __owur int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
                                 int client);
 __owur int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen,
index bfe6331aae5aee76ca29b1f7ad52d7fe96291e7c..26a838f9f2b4004c4b8ea7b3c5bd5aad05f137be 100644 (file)
@@ -714,6 +714,7 @@ int ssl_load_sigalgs(SSL_CTX *ctx)
 
     /* now populate ctx->ssl_cert_info */
     if (ctx->sigalg_list_len > 0) {
+        OPENSSL_free(ctx->ssl_cert_info);
         ctx->ssl_cert_info = OPENSSL_zalloc(sizeof(lu) * ctx->sigalg_list_len);
         if (ctx->ssl_cert_info == NULL)
             return 0;
@@ -2854,6 +2855,7 @@ typedef struct {
     size_t sigalgcnt;
     /* TLSEXT_SIGALG_XXX values */
     uint16_t sigalgs[TLS_MAX_SIGALGCNT];
+    SSL_CTX *ctx;
 } sig_cb_st;
 
 static void get_sigorhash(int *psig, int *phash, const char *str)
@@ -2878,7 +2880,7 @@ static void get_sigorhash(int *psig, int *phash, const char *str)
 static int sig_cb(const char *elem, int len, void *arg)
 {
     sig_cb_st *sarg = arg;
-    size_t i;
+    size_t i = 0;
     const SIGALG_LOOKUP *s;
     char etmp[TLS_MAX_SIGSTRING_LEN], *p;
     int sig_alg = NID_undef, hash_alg = NID_undef;
@@ -2908,16 +2910,32 @@ static int sig_cb(const char *elem, int len, void *arg)
      * in the table.
      */
     if (p == NULL) {
-        for (i = 0, s = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl);
-             i++, s++) {
-            if (s->name != NULL && strcmp(etmp, s->name) == 0) {
-                sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
-                break;
+        /* Load provider sigalgs */
+        if (sarg->ctx != NULL) {
+            /* Check if a provider supports the sigalg */
+            for (i = 0; i < sarg->ctx->sigalg_list_len; i++) {
+                if (sarg->ctx->sigalg_list[i].sigalg_name != NULL
+                    && strcmp(etmp,
+                              sarg->ctx->sigalg_list[i].sigalg_name) == 0) {
+                    sarg->sigalgs[sarg->sigalgcnt++] =
+                        sarg->ctx->sigalg_list[i].code_point;
+                    break;
+                }
             }
         }
-        if (i == OSSL_NELEM(sigalg_lookup_tbl)) {
-            /* Ignore unknown algorithms if ignore_unknown */
-            return ignore_unknown;
+        /* Check the built-in sigalgs */
+        if (sarg->ctx == NULL || i == sarg->ctx->sigalg_list_len) {
+            for (i = 0, s = sigalg_lookup_tbl;
+                 i < OSSL_NELEM(sigalg_lookup_tbl); i++, s++) {
+                if (s->name != NULL && strcmp(etmp, s->name) == 0) {
+                    sarg->sigalgs[sarg->sigalgcnt++] = s->sigalg;
+                    break;
+                }
+            }
+            if (i == OSSL_NELEM(sigalg_lookup_tbl)) {
+                /* Ignore unknown algorithms if ignore_unknown */
+                return ignore_unknown;
+            }
         }
     } else {
         *p = 0;
@@ -2957,10 +2975,14 @@ static int sig_cb(const char *elem, int len, void *arg)
  * Set supported signature algorithms based on a colon separated list of the
  * form sig+hash e.g. RSA+SHA512:DSA+SHA512
  */
-int tls1_set_sigalgs_list(CERT *c, const char *str, int client)
+int tls1_set_sigalgs_list(SSL_CTX *ctx, CERT *c, const char *str, int client)
 {
     sig_cb_st sig;
     sig.sigalgcnt = 0;
+
+    if (ctx != NULL && ssl_load_sigalgs(ctx)) {
+        sig.ctx = ctx;
+    }
     if (!CONF_parse_list(str, ':', 1, sig_cb, &sig))
         return 0;
     if (sig.sigalgcnt == 0) {