]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
fips: add self-tests for HKDF
authorDaiki Ueno <ueno@gnu.org>
Mon, 5 Oct 2020 14:12:46 +0000 (16:12 +0200)
committerDaiki Ueno <ueno@gnu.org>
Tue, 6 Oct 2020 12:15:32 +0000 (14:15 +0200)
FIPS140-2 IG D.8 mandates self-test on approved KDF algorithms.  As
the guidance only requires running a single instance of each KDF
mechanism, this only exercises HKDF-Extract and HKDF-Expand operations
with HMAC-SHA-256 as the underlying MAC.

Although HKDF is non-approved, it would be sensible to do that as it
will be approved in FIPS140-3.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
devel/libgnutls-latest-x86_64.abi
lib/crypto-selftests.c
lib/fips.c
lib/includes/gnutls/self-test.h
lib/libgnutls.map

index 7f0ddd46c71f108cc9e7a78ad92046d8c0e61d77..7ad5dc71f2ddb5ae09b7b08d493b7227235c99ca 100644 (file)
     <elf-symbol name='gnutls_hex_encode' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_hkdf_expand' version='GNUTLS_3_6_13' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_hkdf_extract' version='GNUTLS_3_6_13' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+    <elf-symbol name='gnutls_hkdf_self_test' version='GNUTLS_FIPS140_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_hmac' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_hmac_copy' version='GNUTLS_3_6_9' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
     <elf-symbol name='gnutls_hmac_deinit' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
index 7a1c7729c8c1a5823dd8044f9fc9c0404c62be01..bd148b6af19d6435440eb0fdfcb67553bd9b87e1 100644 (file)
@@ -2917,3 +2917,162 @@ int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest)
 
        return 0;
 }
+
+struct hkdf_vectors_st {
+       const uint8_t *ikm;
+       unsigned int ikm_size;
+       const uint8_t *salt;
+       unsigned int salt_size;
+       const uint8_t *prk;
+       unsigned int prk_size;
+       const uint8_t *info;
+       unsigned int info_size;
+       const uint8_t *okm;
+       unsigned int okm_size;
+};
+
+const struct hkdf_vectors_st hkdf_sha256_vectors[] = {
+       /* RFC 5869: A.1. Test Case 1: Basic test case with SHA-256 */
+       {
+               STR(ikm, ikm_size,
+                   "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+                   "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"),
+               STR(salt, salt_size,
+                   "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c"),
+               STR(prk, prk_size,
+                   "\x07\x77\x09\x36\x2c\x2e\x32\xdf\x0d\xdc\x3f\x0d\xc4\x7b"
+                   "\xba\x63\x90\xb6\xc7\x3b\xb5\x0f\x9c\x31\x22\xec\x84\x4a"
+                   "\xd7\xc2\xb3\xe5"),
+               STR(info, info_size,
+                   "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9"),
+               STR(okm, okm_size,
+                   "\x3c\xb2\x5f\x25\xfa\xac\xd5\x7a\x90\x43\x4f\x64\xd0\x36"
+                   "\x2f\x2a\x2d\x2d\x0a\x90\xcf\x1a\x5a\x4c\x5d\xb0\x2d\x56"
+                   "\xec\xc4\xc5\xbf\x34\x00\x72\x08\xd5\xb8\x87\x18\x58\x65"),
+       },
+       /* RFC 5869: A.2. Test Case 2: Test with SHA-256 and longer inputs/outputs */
+       {
+               STR(ikm, ikm_size,
+                   "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d"
+                   "\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b"
+                   "\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29"
+                   "\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37"
+                   "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45"
+                   "\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"),
+               STR(salt, salt_size,
+                   "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d"
+                   "\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b"
+                   "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89"
+                   "\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97"
+                   "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5"
+                   "\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"),
+               STR(prk, prk_size,
+                   "\x06\xa6\xb8\x8c\x58\x53\x36\x1a\x06\x10\x4c\x9c\xeb\x35"
+                   "\xb4\x5c\xef\x76\x00\x14\x90\x46\x71\x01\x4a\x19\x3f\x40"
+                   "\xc1\x5f\xc2\x44"),
+               STR(info, info_size,
+                   "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd"
+                   "\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb"
+                   "\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9"
+                   "\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+                   "\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5"
+                   "\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"),
+               STR(okm, okm_size,
+                   "\xb1\x1e\x39\x8d\xc8\x03\x27\xa1\xc8\xe7\xf7\x8c\x59\x6a"
+                   "\x49\x34\x4f\x01\x2e\xda\x2d\x4e\xfa\xd8\xa0\x50\xcc\x4c"
+                   "\x19\xaf\xa9\x7c\x59\x04\x5a\x99\xca\xc7\x82\x72\x71\xcb"
+                   "\x41\xc6\x5e\x59\x0e\x09\xda\x32\x75\x60\x0c\x2f\x09\xb8"
+                   "\x36\x77\x93\xa9\xac\xa3\xdb\x71\xcc\x30\xc5\x81\x79\xec"
+                   "\x3e\x87\xc1\x4c\x01\xd5\xc1\xf3\x43\x4f\x1d\x87"),
+       },
+};
+
+static int test_hkdf(gnutls_mac_algorithm_t mac,
+                    const struct hkdf_vectors_st *vectors,
+                    size_t vectors_size, unsigned flags)
+{
+       unsigned int i;
+
+       for (i = 0; i < vectors_size; i++) {
+               gnutls_datum_t ikm, prk, salt, info;
+               uint8_t output[4096];
+               int ret;
+
+               ikm.data = (void *) vectors[i].ikm;
+               ikm.size = vectors[i].ikm_size;
+               salt.data = (void *) vectors[i].salt;
+               salt.size = vectors[i].salt_size;
+
+               ret = gnutls_hkdf_extract(mac, &ikm, &salt, output);
+               if (ret < 0) {
+                       _gnutls_debug_log("error extracting HKDF: MAC-%s\n",
+                                         gnutls_mac_get_name(mac));
+                       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+               }
+
+               if (memcmp(output, vectors[i].prk, vectors[i].prk_size) != 0) {
+                       _gnutls_debug_log
+                           ("HKDF extract: MAC-%s test vector failed!\n",
+                            gnutls_mac_get_name(mac));
+
+                       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+               }
+
+               prk.data = (void *) vectors[i].prk;
+               prk.size = vectors[i].prk_size;
+               info.data = (void *) vectors[i].info;
+               info.size = vectors[i].info_size;
+
+               ret = gnutls_hkdf_expand(mac, &prk, &info,
+                                        output, vectors[i].okm_size);
+               if (ret < 0) {
+                       _gnutls_debug_log("error extracting HKDF: MAC-%s\n",
+                                         gnutls_mac_get_name(mac));
+                       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+               }
+
+               if (memcmp(output, vectors[i].okm, vectors[i].okm_size) != 0) {
+                       _gnutls_debug_log
+                           ("HKDF expand: MAC-%s test vector failed!\n",
+                            gnutls_mac_get_name(mac));
+
+                       return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+               }
+       }
+
+       _gnutls_debug_log
+           ("HKDF: MAC-%s self check succeeded\n",
+            gnutls_mac_get_name(mac));
+
+       return 0;
+}
+
+/*-
+ * gnutls_hkdf_self_test:
+ * @flags: GNUTLS_SELF_TEST_FLAG flags
+ * @mac: the message authentication algorithm to use
+ *
+ * This function will run self tests on HKDF with the provided mac.
+ *
+ * Returns: Zero or a negative error code on error.
+ *
+ * Since: 3.3.0-FIPS140
+ -*/
+int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac)
+{
+       int ret;
+
+       if (flags & GNUTLS_SELF_TEST_FLAG_ALL)
+               mac = GNUTLS_MAC_UNKNOWN;
+
+       switch (mac) {
+       case GNUTLS_MAC_UNKNOWN:
+               CASE(GNUTLS_MAC_SHA256, test_hkdf, hkdf_sha256_vectors);
+
+               break;
+       default:
+               return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST);
+       }
+
+       return 0;
+}
index f8b10f7502ed40dd8c48230c93daa3f2a04e4f19..48891ed573b4de66764567a66afab715e48c8a6b 100644 (file)
@@ -423,6 +423,13 @@ int _gnutls_fips_perform_self_checks2(void)
                goto error;
        }
 
+       /* HKDF */
+       ret = gnutls_hkdf_self_test(0, GNUTLS_MAC_SHA256);
+       if (ret < 0) {
+               gnutls_assert();
+               goto error;
+       }
+
        if (_gnutls_rnd_ops.self_test == NULL) {
                gnutls_assert();
                goto error;
index aacbe94ca6beeb34bf30d5799a7d84b8cf87ce69..9b7be815908da08a3bd41fb2424ae87ee95c60e8 100644 (file)
@@ -34,5 +34,6 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher);
 int gnutls_mac_self_test(unsigned flags, gnutls_mac_algorithm_t mac);
 int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest);
 int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk);
+int gnutls_hkdf_self_test(unsigned flags, gnutls_mac_algorithm_t mac);
 
 #endif /* GNUTLS_SELF_TEST_H */
index 61276e53403f98af8ef6932e2766e6ff951e5eba..386b66f83e127bbea2f33efec744cc962bf70f9a 100644 (file)
@@ -1347,6 +1347,7 @@ GNUTLS_FIPS140_3_4 {
        gnutls_pk_self_test;
        gnutls_mac_self_test;
        gnutls_digest_self_test;
+       gnutls_hkdf_self_test;
        #for FIPS140-2 validation
        drbg_aes_reseed;
        drbg_aes_init;