From: William Lallemand Date: Tue, 30 Jun 2026 13:28:03 +0000 (+0000) Subject: MEDIUM: ssl: add FIPS elliptic curve check for AWS-LC X-Git-Url: http://git.kaiwu.me/sitemap.xml?a=commitdiff_plain;h=6647a59f0632124c12db8375357be477d95b6bf7;p=haproxy.git MEDIUM: ssl: add FIPS elliptic curve check for AWS-LC Add ssl_fips_check_curves() which validates the configured curve list against the FIPS-approved NIST P-curves (P-256, P-384, P-521). Each colon-separated name is resolved to a NID via OBJ_txt2nid() so all standard aliases (P-256, prime256v1, secp256r1) are handled uniformly. 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_curves_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 d4c39a99f..2dc959414 100644 --- a/include/haproxy/fips.h +++ b/include/haproxy/fips.h @@ -10,6 +10,7 @@ #if defined(OPENSSL_IS_AWSLC) 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_version(int min_ver, const enum obj_type *obj); #endif diff --git a/src/fips.c b/src/fips.c index 731abd4f8..cbc8102de 100644 --- a/src/fips.c +++ b/src/fips.c @@ -4,6 +4,8 @@ #include +#include + #include #include #include @@ -17,6 +19,14 @@ static const int fips_approved_cipher_nids[] = { NID_undef }; +/* FIPS-approved elliptic curve NIDs (NIST P-curves). NID_undef terminates the list. */ +static const int fips_approved_curve_nids[] = { + NID_X9_62_prime256v1, /* P-256 */ + NID_secp384r1, /* P-384 */ + NID_secp521r1, /* P-521 */ + NID_undef +}; + /* FIPS-approved TLS 1.3 ciphersuite names. NULL terminates the list. */ static const char *fips_approved_ciphersuites[] = { "TLS_AES_128_GCM_SHA256", @@ -98,6 +108,55 @@ int ssl_fips_check_ciphersuites(const char *ciphersuites, const enum obj_type *o return 0; } +/* Check that the elliptic curve list is FIPS-compliant. */ +int ssl_fips_check_curves(const char *curves, const enum obj_type *obj) +{ + const char *proxy_name, *type_str, *obj_name, *file; + const char *p, *end; + char *list = NULL; + char name[64]; + int i, nid, line; + size_t len; + + if (!FIPS_mode() || !curves) + return 0; + + p = curves; + while (p && *p) { + end = strchr(p, ':'); + len = end ? (size_t)(end - p) : strlen(p); + + if (len < sizeof(name)) { + memcpy(name, p, len); + name[len] = '\0'; + nid = OBJ_txt2nid(name); + if (nid == NID_undef) + nid = EC_curve_nist2nid(name); + for (i = 0; fips_approved_curve_nids[i] != NID_undef; i++) { + if (nid == fips_approved_curve_nids[i]) + 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 curve(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 curve(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.2 cipher list configured on is FIPS-compliant. */ int ssl_fips_check_ciphers(SSL_CTX *ctx, const enum obj_type *obj) { diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 8b58f8662..1fe6c3274 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -4788,6 +4788,10 @@ static int ssl_sock_prepare_ctx(struct bind_conf *bind_conf, struct ssl_bind_con } (void)SSL_CTX_set_ecdh_auto(ctx, 1); } +#if defined(OPENSSL_IS_AWSLC) + cfgerr |= ssl_fips_check_curves(conf_curves, + &LIST_ELEM(bind_conf->listeners.n, struct listener *, by_bind)->obj_type); +#endif #endif /* defined(SSL_CTX_set1_curves_list) */ if (!conf_curves) { @@ -5330,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_curves(conf_curves, &srv->obj_type); +#endif #endif /* defined(SSL_CTX_set1_curves_list) */ return cfgerr;