]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: ssl: add FIPS signature algorithm check for AWS-LC master
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 30 Jun 2026 13:39:14 +0000 (13:39 +0000)
committerWilliam Lallemand <wlallemand@haproxy.com>
Fri, 10 Jul 2026 17:42:03 +0000 (19:42 +0200)
Add ssl_fips_check_sigalgs() which validates the configured signature
algorithm list against the FIPS-approved set: ECDSA on NIST P-curves
with SHA-256/384/512, RSA-PSS (rsae and pss variants) with SHA-256/
384/512, and RSA-PKCS1 with SHA-256/384/512.  SHA-1 based algorithms
and non-FIPS primitives (ed25519, ed448) are rejected.

The check uses the same strchr-based string parsing as
ssl_fips_check_ciphersuites().  A NULL list is silently accepted since
the global defaults were already overwritten with FIPS values at init
time.

The check is called right after SSL_CTX_set1_sigalgs_list() and
SSL_CTX_set1_client_sigalgs_list() in both the bind
(ssl_sock_prepare_ctx) and server (ssl_sock_prepare_srv_ssl_ctx)
configuration paths.

include/haproxy/fips.h
src/fips.c
src/ssl_sock.c

index f92c7c644b1c0b3d547d184cafbddc1bd68423fc..574673359fc5b3b0a0e04871d177228740ac0983 100644 (file)
@@ -11,6 +11,7 @@
 int ssl_fips_check_ciphers(SSL_CTX *ctx, const enum obj_type *obj, char **err);
 int ssl_fips_check_ciphersuites(const char *ciphersuites, const enum obj_type *obj, char **err);
 int ssl_fips_check_curves(const char *curves, const enum obj_type *obj, char **err);
+int ssl_fips_check_sigalgs(const char *sigalgs, const enum obj_type *obj, char **err);
 int ssl_fips_check_version(int min_ver, const enum obj_type *obj);
 #endif
 
index 589cc224d5a80d79bd105bcf9023dea33799fc17..3b4a314189c79821189a6df7e25362472cf92e18 100644 (file)
@@ -30,6 +30,23 @@ static const int fips_approved_curve_nids[] = {
        NID_undef
 };
 
+/* FIPS-approved signature algorithm names.  NULL terminates the list. */
+static const char *fips_approved_sigalgs[] = {
+       "ecdsa_secp256r1_sha256",
+       "ecdsa_secp384r1_sha384",
+       "ecdsa_secp521r1_sha512",
+       "rsa_pss_rsae_sha256",
+       "rsa_pss_rsae_sha384",
+       "rsa_pss_rsae_sha512",
+       "rsa_pss_pss_sha256",
+       "rsa_pss_pss_sha384",
+       "rsa_pss_pss_sha512",
+       "rsa_pkcs1_sha256",
+       "rsa_pkcs1_sha384",
+       "rsa_pkcs1_sha512",
+       NULL
+};
+
 /* FIPS-approved TLS 1.3 ciphersuite names.  NULL terminates the list.
  * TLS_AES_128_CCM_SHA256 is FIPS-approved but not implemented by AWS-LC. */
 static const char *fips_approved_ciphersuites[] = {
@@ -71,6 +88,48 @@ static void fips_obj_info(const enum obj_type *obj,
        }
 }
 
+/* Check that the signature algorithm list <sigalgs> is FIPS-compliant. */
+int ssl_fips_check_sigalgs(const char *sigalgs, const enum obj_type *obj, char **err)
+{
+       const char *proxy_name, *type_str, *obj_name, *file;
+       const char *p, *end;
+       char *list = NULL;
+       int i, line;
+       size_t len;
+
+       if (!FIPS_mode() || !sigalgs)
+               return 0;
+
+       p = sigalgs;
+       while (p && *p) {
+               end = strchr(p, ':');
+               len = end ? (size_t)(end - p) : strlen(p);
+
+               for (i = 0; fips_approved_sigalgs[i]; i++) {
+                       if (strlen(fips_approved_sigalgs[i]) == len &&
+                           strncmp(p, fips_approved_sigalgs[i], len) == 0)
+                               goto next;
+               }
+               memprintf(&list, "%s%s'%.*s'", list ? list : "",
+                         list ? ", " : "", (int)len, p);
+       next:
+               p = end ? end + 1 : NULL;
+       }
+
+       if (list) {
+               fips_obj_info(obj, &proxy_name, &type_str, &obj_name, &file, &line);
+               if (file)
+                       memprintf(err, "%s[%s:%d] %s '%s/%s': FIPS mode active but non-FIPS signature algorithm(s) configured: %s.\n",
+                                 (err && *err) ? *err : "", file, line, type_str, proxy_name, obj_name, list);
+               else
+                       memprintf(err, "%s%s '%s/%s': FIPS mode active but non-FIPS signature algorithm(s) configured: %s.\n",
+                                 (err && *err) ? *err : "", type_str, proxy_name, obj_name, list);
+               free(list);
+               return ERR_ALERT | ERR_ABORT | ERR_FATAL;
+       }
+       return 0;
+}
+
 /* Check that the TLS 1.3 ciphersuite list <ciphersuites> is FIPS-compliant. */
 int ssl_fips_check_ciphersuites(const char *ciphersuites, const enum obj_type *obj, char **err)
 {
index ece8cc64f50bc1be8ac9e322f0f54028cc82e6f5..36a2d1887bac63263e5a82ee73323f796c960c21 100644 (file)
@@ -4839,6 +4839,10 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con
                        cfgerr |= ERR_ALERT | ERR_FATAL;
                }
        }
+#if defined(OPENSSL_IS_AWSLC)
+       cfgerr |= ssl_fips_check_sigalgs(conf_sigalgs,
+                                        &LIST_ELEM(bind_conf->listeners.n, struct listener *, by_bind)->obj_type, err);
+#endif
 #endif
 
 #if defined(SSL_CTX_set1_client_sigalgs_list)
@@ -4850,6 +4854,10 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con
                        cfgerr |= ERR_ALERT | ERR_FATAL;
                }
        }
+#if defined(OPENSSL_IS_AWSLC)
+       cfgerr |= ssl_fips_check_sigalgs(conf_client_sigalgs,
+                                        &LIST_ELEM(bind_conf->listeners.n, struct listener *, by_bind)->obj_type, err);
+#endif
 #endif
 
 #ifdef USE_QUIC_OPENSSL_COMPAT
@@ -5324,6 +5332,13 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
                        cfgerr++;
                }
        }
+#if defined(OPENSSL_IS_AWSLC)
+       if (ssl_fips_check_sigalgs(conf_sigalgs, &srv->obj_type, &err)) {
+               ha_alert("%s", err);
+               ha_free(&err);
+               cfgerr++;
+       }
+#endif
 #endif
 #if defined(SSL_CTX_set1_client_sigalgs_list)
        conf_client_sigalgs = srv->ssl_ctx.client_sigalgs;
@@ -5334,6 +5349,13 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx)
                        cfgerr++;
                }
        }
+#if defined(OPENSSL_IS_AWSLC)
+       if (ssl_fips_check_sigalgs(conf_client_sigalgs, &srv->obj_type, &err)) {
+               ha_alert("%s", err);
+               ha_free(&err);
+               cfgerr++;
+       }
+#endif
 #endif
 
 #if defined(SSL_CTX_set1_curves_list)