]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: ssl: add FIPS elliptic curve check for AWS-LC
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 30 Jun 2026 13:28:03 +0000 (13:28 +0000)
committerWilliam Lallemand <wlallemand@haproxy.com>
Tue, 30 Jun 2026 14:02:50 +0000 (14:02 +0000)
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.

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

index d4c39a99f2bbee9eab9bdbf675d72a13d8c838ff..2dc9594145bda182d1dc9d866b4f621e45af6729 100644 (file)
@@ -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
 
index 731abd4f8aa68f52b3f02c21f96719c77ac0650b..cbc8102de919dc81ee7601d48917027e5e53e8bd 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <stdlib.h>
 
+#include <openssl/ec.h>
+
 #include <haproxy/errors.h>
 #include <haproxy/obj_type.h>
 #include <haproxy/openssl-compat.h>
@@ -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 <curves> 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 <ctx> is FIPS-compliant. */
 int ssl_fips_check_ciphers(SSL_CTX *ctx, const enum obj_type *obj)
 {
index 8b58f8662af82dff49e3e1c722ed59c34e4bab75..1fe6c3274a564ff8525487636d0d126646a39170 100644 (file)
@@ -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;