#include <haproxy/ssl_sock-t.h>
#include <haproxy/tools.h>
+/* FIPS-approved bulk cipher NIDs (TLS 1.2). NID_undef terminates the list. */
+static const int fips_approved_cipher_nids[] = {
+ NID_aes_128_gcm,
+ NID_aes_256_gcm,
+ NID_undef
+};
+
/* Fill display fields from <obj> for use in error messages. */
static void fips_obj_info(const enum obj_type *obj,
const char **proxy_name, const char **type_str,
}
}
+/* 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)
+{
+ const char *proxy_name, *type_str, *obj_name, *file;
+ STACK_OF(SSL_CIPHER) *cipher_list;
+ const SSL_CIPHER *cipher;
+ int i, j, cipher_nid, line;
+ char *list = NULL;
+
+ if (!FIPS_mode())
+ return 0;
+
+ cipher_list = SSL_CTX_get_ciphers(ctx);
+ if (!cipher_list)
+ return 0;
+
+ for (i = 0; i < sk_SSL_CIPHER_num(cipher_list); i++) {
+ cipher = sk_SSL_CIPHER_value(cipher_list, i);
+ cipher_nid = SSL_CIPHER_get_cipher_nid(cipher);
+
+ for (j = 0; fips_approved_cipher_nids[j] != NID_undef; j++) {
+ if (cipher_nid == fips_approved_cipher_nids[j])
+ goto next;
+ }
+ memprintf(&list, "%s%s'%s'", list ? list : "",
+ list ? ", " : "", SSL_CIPHER_get_name(cipher));
+ next:;
+ }
+
+ 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 cipher(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 cipher(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 minimum TLS version <min_ver> is FIPS-compliant. */
int ssl_fips_check_version(int min_ver, const enum obj_type *obj)
{
}
#endif
+#if defined(OPENSSL_IS_AWSLC)
+ cfgerr |= ssl_fips_check_ciphers(ctx,
+ &LIST_ELEM(bind_conf->listeners.n, struct listener *, by_bind)->obj_type);
+#endif
+
#ifndef OPENSSL_NO_DH
if (!local_dh_1024)
local_dh_1024 = ssl_get_dh_1024();
cfgerr++;
}
#endif
+
+#if defined(OPENSSL_IS_AWSLC)
+ cfgerr += !!ssl_fips_check_ciphers(ctx, &srv->obj_type);
+#endif
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
if (srv->ssl_ctx.npn_str)
SSL_CTX_set_next_proto_select_cb(ctx, ssl_sock_srv_select_protos, (struct server*)srv);