]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
tls1-prf: mark use of non-EMS PRF non-approved in FIPS
authorDaiki Ueno <ueno@gnu.org>
Thu, 29 Jun 2023 08:04:51 +0000 (10:04 +0200)
committerDaiki Ueno <ueno@gnu.org>
Mon, 10 Jul 2023 12:57:40 +0000 (14:57 +0200)
This adds service indicator transitions around the use of TLS 1.2 PRF.
As of May 16, 2023, the use of extended master secret is mandatory
according to FIPS 140-3 IG.  This patch detects the usage of non-EMS
KDF by checking the label: if it is "master secret", the service
indicator transitions to a non-approved state.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/nettle/int/tls1-prf.c
tests/tls-force-ems.c

index bc021a16587debcdc301fe2f12c13922c1eb8798..ef325bd2cf541cf96bb605aca821bc955c6baa94 100644 (file)
@@ -28,6 +28,7 @@
 #endif
 
 #include <gnutls_int.h>
+#include "fips.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -140,8 +141,26 @@ int tls12_prf(void *mac_ctx, nettle_hash_update_func *update,
              size_t label_size, const char *label, size_t seed_size,
              const uint8_t *seed, size_t length, uint8_t *dst)
 {
+#define MASTER_SECRET "master secret"
+#define MASTER_SECRET_SIZE (sizeof(MASTER_SECRET) - 1)
+
        P_hash(mac_ctx, update, digest, digest_size, seed_size, seed,
               label_size, label, length, dst);
 
+       /* Since May 16, 2023, the use of extended master secret is
+        * mandatory according to FIPS 140-3 IG D.Q.  Instead of
+        * allowing the "extended master secret" label specifically,
+        * we mark the use of non-EMS label, i.e., "master secret" as
+        * non-approved, because it is still useful to call the
+        * gnutls_prf_raw function with arbitrary label, e.g., in
+        * self-tests.
+        */
+       if (label_size == MASTER_SECRET_SIZE &&
+           memcmp(label, MASTER_SECRET, MASTER_SECRET_SIZE) == 0) {
+               _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+       } else {
+               _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+       }
+
        return 1;
 }
index 06bebe25e5eee396faf94809c3003b36ef270ee5..6bbbf5bc37aa621f4467f625bfbc5d5d5bef52c0 100644 (file)
@@ -91,6 +91,8 @@ static void try(const char *name, const char *sprio, const char *cprio,
 
 void doit(void)
 {
+       gnutls_fips140_context_t fips_context;
+
        global_init();
 
        /* General init. */
@@ -98,10 +100,20 @@ void doit(void)
        if (debug)
                gnutls_global_set_log_level(2);
 
-       try("default", AES_GCM ":%FORCE_SESSION_HASH",
-           AES_GCM ":%FORCE_SESSION_HASH", 0, 0);
+       assert(gnutls_fips140_context_init(&fips_context) >= 0);
+
+       /* Default: EMS is requested in non-FIPS mode, while it is
+        * required in FIPS mode.
+        */
+       FIPS_PUSH_CONTEXT();
+       try("default", AES_GCM, AES_GCM, 0, 0);
+       FIPS_POP_CONTEXT(APPROVED);
+
+       FIPS_PUSH_CONTEXT();
        try("both force EMS", AES_GCM ":%FORCE_SESSION_HASH",
            AES_GCM ":%FORCE_SESSION_HASH", 0, 0);
+       FIPS_POP_CONTEXT(APPROVED);
+
        if (gnutls_fips140_mode_enabled()) {
                try("neither negotiates EMS", AES_GCM ":%NO_SESSION_HASH",
                    AES_GCM ":%NO_SESSION_HASH", GNUTLS_E_INSUFFICIENT_SECURITY,
@@ -130,5 +142,7 @@ void doit(void)
            AES_GCM ":%FORCE_SESSION_HASH", AES_GCM ":%NO_SESSION_HASH",
            GNUTLS_E_INSUFFICIENT_SECURITY, GNUTLS_E_AGAIN);
 
+       gnutls_fips140_context_deinit(fips_context);
+
        gnutls_global_deinit();
 }