]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
pkcs12: mark MAC generation and verification as FIPS non-approved
authorDaiki Ueno <ueno@gnu.org>
Thu, 10 Feb 2022 15:43:08 +0000 (16:43 +0100)
committerDaiki Ueno <ueno@gnu.org>
Tue, 15 Feb 2022 19:52:38 +0000 (20:52 +0100)
Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/x509/pkcs12.c
tests/pkcs12_encode.c

index a8f7d8f9562af96132995a624b88ff34bc17c626..11b9da3ac98594b8b55e63c7ade85f5788ae9b02 100644 (file)
@@ -286,13 +286,26 @@ gnutls_pkcs12_export(gnutls_pkcs12_t pkcs12,
                     gnutls_x509_crt_fmt_t format, void *output_data,
                     size_t * output_data_size)
 {
+       int ret;
+
        if (pkcs12 == NULL) {
                gnutls_assert();
                return GNUTLS_E_INVALID_REQUEST;
        }
 
-       return _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12,
-                                      output_data, output_data_size);
+       ret = _gnutls_x509_export_int(pkcs12->pkcs12, format, PEM_PKCS12,
+                                     output_data, output_data_size);
+
+       if (ret < 0) {
+               _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+       } else {
+               /* PKCS#12 export is always non-approved, because the MAC
+                * calculation involves non-approved KDF (PKCS#12 KDF) and
+                * without MAC the protection is insufficient.
+                */
+               _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+       }
+       return ret;
 }
 
 /**
@@ -317,13 +330,25 @@ int
 gnutls_pkcs12_export2(gnutls_pkcs12_t pkcs12,
                      gnutls_x509_crt_fmt_t format, gnutls_datum_t * out)
 {
+       int ret;
+
        if (pkcs12 == NULL) {
                gnutls_assert();
                return GNUTLS_E_INVALID_REQUEST;
        }
 
-       return _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12,
-                                       out);
+       ret = _gnutls_x509_export_int2(pkcs12->pkcs12, format, PEM_PKCS12,
+                                      out);
+       if (ret < 0) {
+               _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+       } else {
+               /* PKCS#12 export is always non-approved, because the MAC
+                * calculation involves non-approved KDF (PKCS#12 KDF) and
+                * without MAC the protection is insufficient.
+                */
+               _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+       }
+       return ret;
 }
 
 static int oid2bag(const char *oid)
@@ -1025,9 +1050,12 @@ int gnutls_pkcs12_generate_mac2(gnutls_pkcs12_t pkcs12, gnutls_mac_algorithm_t m
                goto cleanup;
        }
 
+       /* _gnutls_pkcs12_string_to_key is not a FIPS approved operation */
+       _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
        return 0;
 
       cleanup:
+       _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
        _gnutls_free_datum(&tmp);
        return result;
 }
@@ -1203,8 +1231,11 @@ pkcs12_try_gost:
                goto cleanup;
        }
 
+       /* _gnutls_pkcs12_string_to_key is not a FIPS approved operation */
+       _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
        result = 0;
  cleanup:
+       _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
        _gnutls_free_datum(&tmp);
        _gnutls_free_datum(&salt);
        return result;
index 3b0e84ef13fd50493e4ef5c0e3dd5809a45496df..b8f7d172671423b8935da5ed131415e9e58d0875 100644 (file)
@@ -70,6 +70,29 @@ static void tls_log_func(int level, const char *str)
        fprintf(stderr, "|<%d>| %s", level, str);
 }
 
+#define FIPS_PUSH_CONTEXT() do {                                       \
+       if (gnutls_fips140_mode_enabled()) {                            \
+               ret = gnutls_fips140_push_context(fips_context);        \
+               if (ret < 0) {                                          \
+                       fail("gnutls_fips140_push_context failed\n");   \
+               }                                                       \
+       }                                                               \
+} while (0)
+
+#define FIPS_POP_CONTEXT(state) do {                                   \
+       if (gnutls_fips140_mode_enabled()) {                            \
+               ret = gnutls_fips140_pop_context();                     \
+               if (ret < 0) {                                          \
+                       fail("gnutls_fips140_context_pop failed\n");    \
+               }                                                       \
+               fips_state = gnutls_fips140_get_operation_state(fips_context); \
+               if (fips_state != GNUTLS_FIPS140_OP_ ## state) {        \
+                       fail("operation state is not " # state " (%d)\n", \
+                            fips_state);                               \
+               }                                                       \
+       }                                                               \
+} while (0)
+
 void doit(void)
 {
        gnutls_pkcs12_t pkcs12;
@@ -82,6 +105,8 @@ void doit(void)
        char outbuf[10240];
        size_t size;
        unsigned tests, i;
+       gnutls_fips140_context_t fips_context;
+       gnutls_fips140_operation_state_t fips_state;
 
        ret = global_init();
        if (ret < 0) {
@@ -93,6 +118,11 @@ void doit(void)
        if (debug)
                gnutls_global_set_log_level(4711);
 
+       ret = gnutls_fips140_context_init(&fips_context);
+       if (ret < 0) {
+               fail("Cannot initialize FIPS context\n");
+       }
+
        /* Read certs. */
        ret = gnutls_x509_crt_init(&client);
        if (ret < 0) {
@@ -196,6 +226,8 @@ void doit(void)
                gnutls_pkcs12_bag_deinit(bag);
        }
 
+       FIPS_PUSH_CONTEXT();
+
        /* MAC the structure, export and print. */
        ret = gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA1, "pass");
        if (ret < 0) {
@@ -203,36 +235,60 @@ void doit(void)
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
+       FIPS_PUSH_CONTEXT();
+
        ret = gnutls_pkcs12_verify_mac(pkcs12, "pass");
        if (ret < 0) {
                fprintf(stderr, "verify_mac: %s (%d)\n", gnutls_strerror(ret), ret);
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
+       FIPS_PUSH_CONTEXT();
+
        ret = gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA256, "passwd");
        if (ret < 0) {
                fprintf(stderr, "generate_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
+       FIPS_PUSH_CONTEXT();
+
        ret = gnutls_pkcs12_verify_mac(pkcs12, "passwd");
        if (ret < 0) {
                fprintf(stderr, "verify_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
+       FIPS_PUSH_CONTEXT();
+
        ret = gnutls_pkcs12_generate_mac2(pkcs12, GNUTLS_MAC_SHA512, "passwd1");
        if (ret < 0) {
                fprintf(stderr, "generate_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
+       FIPS_PUSH_CONTEXT();
+
        ret = gnutls_pkcs12_verify_mac(pkcs12, "passwd1");
        if (ret < 0) {
                fprintf(stderr, "verify_mac2: %s (%d)\n", gnutls_strerror(ret), ret);
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
+       FIPS_PUSH_CONTEXT();
+
        size = sizeof(outbuf);
        ret =
            gnutls_pkcs12_export(pkcs12, GNUTLS_X509_FMT_PEM, outbuf,
@@ -242,10 +298,13 @@ void doit(void)
                exit(1);
        }
 
+       FIPS_POP_CONTEXT(NOT_APPROVED);
+
        if (debug)
                fwrite(outbuf, size, 1, stdout);
 
        /* Cleanup. */
+       gnutls_fips140_context_deinit(fips_context);
        gnutls_pkcs12_deinit(pkcs12);
        gnutls_x509_crt_deinit(client);
        gnutls_x509_crt_deinit(ca);