From: William Lallemand Date: Tue, 30 Jun 2026 13:39:14 +0000 (+0000) Subject: MEDIUM: ssl: add FIPS signature algorithm check for AWS-LC X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/postgres_fdw.c?a=commitdiff_plain;h=e411ea32a434a618b559eac0bf7a3da43ea9bc7f;p=haproxy.git MEDIUM: ssl: add FIPS signature algorithm check for AWS-LC 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. --- diff --git a/include/haproxy/fips.h b/include/haproxy/fips.h index 2dc959414..dc28e0d14 100644 --- a/include/haproxy/fips.h +++ b/include/haproxy/fips.h @@ -11,6 +11,7 @@ int ssl_fips_check_ciphers(SSL_CTX *ctx, const enum obj_type *obj); int ssl_fips_check_ciphersuites(const char *ciphersuites, const enum obj_type *obj); int ssl_fips_check_curves(const char *curves, const enum obj_type *obj); +int ssl_fips_check_sigalgs(const char *sigalgs, const enum obj_type *obj); int ssl_fips_check_version(int min_ver, const enum obj_type *obj); #endif diff --git a/src/fips.c b/src/fips.c index cbc8102de..147fd4a0f 100644 --- a/src/fips.c +++ b/src/fips.c @@ -27,6 +27,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. */ static const char *fips_approved_ciphersuites[] = { "TLS_AES_128_GCM_SHA256", @@ -66,6 +83,48 @@ static void fips_obj_info(const enum obj_type *obj, } } +/* Check that the signature algorithm list is FIPS-compliant. */ +int ssl_fips_check_sigalgs(const char *sigalgs, const enum obj_type *obj) +{ + 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) + ha_alert("[%s:%d] %s '%s/%s': FIPS mode active but non-FIPS signature algorithm(s) configured: %s.\n", + file, line, type_str, proxy_name, obj_name, list); + else + ha_alert("%s '%s/%s': FIPS mode active but non-FIPS signature algorithm(s) configured: %s.\n", + 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 is FIPS-compliant. */ int ssl_fips_check_ciphersuites(const char *ciphersuites, const enum obj_type *obj) { diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 6c09aa513..275272a2b 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -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); +#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); +#endif #endif #ifdef USE_QUIC_OPENSSL_COMPAT @@ -5313,6 +5321,9 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx) cfgerr++; } } +#if defined(OPENSSL_IS_AWSLC) + cfgerr += !!ssl_fips_check_sigalgs(conf_sigalgs, &srv->obj_type); +#endif #endif #if defined(SSL_CTX_set1_client_sigalgs_list) conf_client_sigalgs = srv->ssl_ctx.client_sigalgs; @@ -5323,6 +5334,9 @@ static int ssl_sock_prepare_srv_ssl_ctx(const struct server *srv, SSL_CTX *ctx) cfgerr++; } } +#if defined(OPENSSL_IS_AWSLC) + cfgerr += !!ssl_fips_check_sigalgs(conf_client_sigalgs, &srv->obj_type); +#endif #endif #if defined(SSL_CTX_set1_curves_list)