#endif
#include <gnutls_int.h>
+#include "fips.h"
#include <stdlib.h>
#include <string.h>
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;
}
void doit(void)
{
+ gnutls_fips140_context_t fips_context;
+
global_init();
/* General init. */
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,
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();
}