summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <ueno@gnu.org>2020-10-05 17:44:30 +0200
committerDaiki Ueno <ueno@gnu.org>2020-10-08 17:13:57 +0200
commitd1a3235e8c829855969d00364d8b5456fce2c78c (patch)
treed1921227f26d51acea9e87a8060a7456174e10b7
parent31cc94275cd267f4e0db60999cc932fd76d43d5a (diff)
downloadgnutls-d1a3235e8c829855969d00364d8b5456fce2c78c.tar.gz
fips: add self-tests for TLS-PRF
FIPS140-2 IG D.8 mandates self-tests on approved KDF algorithms. As the guidance only requires to run a single instance of each KDF mechanism, this only exercises TLS1.2 PRF with HMAC-SHA-256 as the underlying MAC algorithm. Signed-off-by: Daiki Ueno <ueno@gnu.org>
-rw-r--r--devel/libgnutls-latest-x86_64.abi1
-rw-r--r--lib/crypto-selftests.c196
-rw-r--r--lib/fips.c7
-rw-r--r--lib/includes/gnutls/self-test.h1
-rw-r--r--lib/libgnutls.map1
5 files changed, 206 insertions, 0 deletions
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index dce6137361..f58dde4240 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -877,6 +877,7 @@
<elf-symbol name='gnutls_tdb_set_store_commitment_func' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_tdb_set_store_func' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_tdb_set_verify_func' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='gnutls_tlsprf_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_tpm_get_registered' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_tpm_key_list_deinit' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_tpm_key_list_get_url' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index c4b0bd207f..b740936d6b 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -3183,3 +3183,199 @@ int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac)
return 0;
}
+
+struct tlsprf_vectors_st {
+ const uint8_t *key;
+ size_t key_size;
+ const uint8_t *label;
+ size_t label_size;
+ const uint8_t *seed;
+ size_t seed_size;
+ const uint8_t *output;
+ size_t output_size;
+};
+
+const struct tlsprf_vectors_st tls10prf_vectors[] = {
+ /* tests/tls10-prf.c: test1 */
+ {
+ STR(key, key_size,
+ "\x26\x3b\xdb\xbb\x6f\x6d\x4c\x66\x4e\x05\x8d\x0a\xa9\xd3"
+ "\x21\xbe"),
+ STR(label, label_size,
+ "test label"),
+ STR(seed, seed_size,
+ "\xb9\x20\x57\x3b\x19\x96\x01\x02\x4f\x04\xd6\xdc\x61\x96"
+ "\x6e\x65"),
+ STR(output, output_size,
+ "\x66\x17\x99\x37\x65\xfa\x6c\xa7\x03\xd1\x9e\xc7\x0d\xd5"
+ "\xdd\x16\x0f\xfc\xc0\x77\x25\xfa\xfb\x71\x4a\x9f\x81\x5a"
+ "\x2a\x30\xbf\xb7\xe3\xbb\xfb\x7e\xee\x57\x4b\x3b\x61\x3e"
+ "\xb7\xfe\x80\xee\xc9\x69\x1d\x8c\x1b\x0e\x2d\x9b\x3c\x8b"
+ "\x4b\x02\xb6\xb6\xd6\xdb\x88\xe2\x09\x46\x23\xef\x62\x40"
+ "\x60\x7e\xda\x7a\xbe\x3c\x84\x6e\x82\xa3"),
+ },
+};
+
+const struct tlsprf_vectors_st tls12prf_sha256_vectors[] = {
+ /* tests/tls12-prf.c: sha256_test1 */
+ {
+ STR(key, key_size,
+ "\x04\x50\xb0\xea\x9e\xcd\x36\x02\xee\x0d\x76\xc5\xc3\xc8"
+ "\x6f\x4a"),
+ STR(label, label_size,
+ "test label"),
+ STR(seed, seed_size,
+ "\x20\x7a\xcc\x02\x54\xb8\x67\xf5\xb9\x25\xb4\x5a\x33\x60"
+ "\x1d\x8b"),
+ STR(output, output_size,
+ "\xae\x67\x9e\x0e\x71\x4f\x59\x75\x76\x37\x68\xb1\x66\x97"
+ "\x9e\x1d"),
+ },
+ /* tests/tls12-prf.c: sha256_test2 */
+ {
+ STR(key, key_size,
+ "\x34\x20\x4a\x9d\xf0\xbe\x6e\xb4\xe9\x25\xa8\x02\x7c\xf6"
+ "\xc6\x02"),
+ STR(label, label_size,
+ "test label"),
+ STR(seed, seed_size,
+ "\x98\xb2\xc4\x0b\xcd\x66\x4c\x83\xbb\x92\x0c\x18\x20\x1a"
+ "\x63\x95"),
+ STR(output, output_size,
+ "\xaf\xa9\x31\x24\x53\xc2\x2f\xa8\x3d\x2b\x51\x1b\x37\x2d"
+ "\x73\xa4\x02\xa2\xa6\x28\x73\x23\x9a\x51\xfa\xde\x45\x08"
+ "\x2f\xaf\x3f\xd2\xbb\x7f\xfb\x3e\x9b\xf3\x6e\x28\xb3\x14"
+ "\x1a\xab\xa4\x84\x00\x53\x32\xa9\xf9\xe3\x88\xa4\xd3\x29"
+ "\xf1\x58\x7a\x4b\x31\x7d\xa0\x77\x08\xea\x1b\xa9\x5a\x53"
+ "\xf8\x78\x67\x24\xbd\x83\xce\x4b\x03\xaf"),
+ },
+ /* tests/tls12-prf.c: sha256_test3 */
+ {
+ STR(key, key_size,
+ "\xa3\x69\x1a\xa1\xf6\x81\x4b\x80\x59\x2b\xf1\xcf\x2a\xcf"
+ "\x16\x97"),
+ STR(label, label_size,
+ "test label"),
+ STR(seed, seed_size,
+ "\x55\x23\xd4\x1e\x32\x0e\x69\x4d\x0c\x1f\xf5\x73\x4d\x83"
+ "\x0b\x93\x3e\x46\x92\x70\x71\xc9\x26\x21"),
+ STR(output, output_size,
+ "\x6a\xd0\x98\x4f\xa0\x6f\x78\xfe\x16\x1b\xd4\x6d\x7c\x26"
+ "\x1d\xe4\x33\x40\xd7\x28\xdd\xdc\x3d\x0f\xf0\xdd\x7e\x0d"),
+ },
+ /* tests/tls12-prf.c: sha256_test4 */
+ {
+ STR(key, key_size,
+ "\x21\x0e\xc9\x37\x06\x97\x07\xe5\x46\x5b\xc4\x6b\xf7\x79"
+ "\xe1\x04\x10\x8b\x18\xfd\xb7\x93\xbe\x7b\x21\x8d\xbf\x14"
+ "\x5c\x86\x41\xf3"),
+ STR(label, label_size,
+ "test label"),
+ STR(seed, seed_size,
+ "\x1e\x35\x1a\x0b\xaf\x35\xc7\x99\x45\x92\x43\x94\xb8\x81"
+ "\xcf\xe3\x1d\xae\x8f\x1c\x1e\xd5\x4d\x3b"),
+ STR(output, output_size,
+ "\x76\x53\xfa\x80\x9c\xde\x3b\x55\x3c\x4a\x17\xe2\xcd\xbc"
+ "\xc9\x18\xf3\x65\x27\xf2\x22\x19\xa7\xd7\xf9\x5d\x97\x24"
+ "\x3f\xf2\xd5\xde\xe8\x26\x5e\xf0\xaf\x03"),
+ },
+};
+
+const struct tlsprf_vectors_st tls12prf_sha384_vectors[] = {
+ /* tests/tls12-prf.c: sha384_test1
+ * https://www.ietf.org/mail-archive/web/tls/current/msg03416.html
+ */
+ {
+ STR(key, key_size,
+ "\xb8\x0b\x73\x3d\x6c\xee\xfc\xdc\x71\x56\x6e\xa4\x8e\x55"
+ "\x67\xdf"),
+ STR(label, label_size,
+ "test label"),
+ STR(seed, seed_size,
+ "\xcd\x66\x5c\xf6\xa8\x44\x7d\xd6\xff\x8b\x27\x55\x5e\xdb"
+ "\x74\x65"),
+ STR(output, output_size,
+ "\x7b\x0c\x18\xe9\xce\xd4\x10\xed\x18\x04\xf2\xcf\xa3\x4a"
+ "\x33\x6a\x1c\x14\xdf\xfb\x49\x00\xbb\x5f\xd7\x94\x21\x07"
+ "\xe8\x1c\x83\xcd\xe9\xca\x0f\xaa\x60\xbe\x9f\xe3\x4f\x82"
+ "\xb1\x23\x3c\x91\x46\xa0\xe5\x34\xcb\x40\x0f\xed\x27\x00"
+ "\x88\x4f\x9d\xc2\x36\xf8\x0e\xdd\x8b\xfa\x96\x11\x44\xc9"
+ "\xe8\xd7\x92\xec\xa7\x22\xa7\xb3\x2f\xc3\xd4\x16\xd4\x73"
+ "\xeb\xc2\xc5\xfd\x4a\xbf\xda\xd0\x5d\x91\x84\x25\x9b\x5b"
+ "\xf8\xcd\x4d\x90\xfa\x0d\x31\xe2\xde\xc4\x79\xe4\xf1\xa2"
+ "\x60\x66\xf2\xee\xa9\xa6\x92\x36\xa3\xe5\x26\x55\xc9\xe9"
+ "\xae\xe6\x91\xc8\xf3\xa2\x68\x54\x30\x8d\x5e\xaa\x3b\xe8"
+ "\x5e\x09\x90\x70\x3d\x73\xe5\x6f"),
+ },
+};
+
+static int test_tlsprf(gnutls_mac_algorithm_t mac,
+ const struct tlsprf_vectors_st *vectors,
+ size_t vectors_size, unsigned flags)
+{
+ unsigned int i;
+
+ for (i = 0; i < vectors_size; i++) {
+ char output[4096];
+ int ret;
+
+ ret = _gnutls_prf_raw(mac,
+ vectors[i].key_size, vectors[i].key,
+ vectors[i].label_size, (const char *)vectors[i].label,
+ vectors[i].seed_size, vectors[i].seed,
+ vectors[i].output_size, output);
+ if (ret < 0) {
+ _gnutls_debug_log("error calculating TLS-PRF: MAC-%s\n",
+ gnutls_mac_get_name(mac));
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+
+ if (memcmp(output, vectors[i].output, vectors[i].output_size) != 0) {
+ _gnutls_debug_log
+ ("TLS-PRF: MAC-%s test vector failed!\n",
+ gnutls_mac_get_name(mac));
+
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+ }
+
+ _gnutls_debug_log
+ ("TLS-PRF: MAC-%s self check succeeded\n",
+ gnutls_mac_get_name(mac));
+
+ return 0;
+}
+
+/*-
+ * gnutls_tlsprf_self_test:
+ * @flags: GNUTLS_SELF_TEST_FLAG flags
+ * @mac: the message authentication algorithm to use
+ *
+ * This function will run self tests on TLS-PRF with the provided mac.
+ *
+ * Returns: Zero or a negative error code on error.
+ *
+ * Since: 3.3.0-FIPS140
+ -*/
+int gnutls_tlsprf_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:
+ NON_FIPS_CASE(GNUTLS_MAC_MD5_SHA1, test_tlsprf, tls10prf_vectors);
+ FALLTHROUGH;
+ CASE(GNUTLS_MAC_SHA256, test_tlsprf, tls12prf_sha256_vectors);
+ FALLTHROUGH;
+ CASE(GNUTLS_MAC_SHA384, test_tlsprf, tls12prf_sha384_vectors);
+
+ break;
+ default:
+ return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST);
+ }
+
+ return 0;
+}
diff --git a/lib/fips.c b/lib/fips.c
index 7cfab10493..30d396b2c5 100644
--- a/lib/fips.c
+++ b/lib/fips.c
@@ -437,6 +437,13 @@ int _gnutls_fips_perform_self_checks2(void)
goto error;
}
+ /* TLS-PRF */
+ ret = gnutls_tlsprf_self_test(0, GNUTLS_MAC_SHA256);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+
if (_gnutls_rnd_ops.self_test == NULL) {
gnutls_assert();
goto error;
diff --git a/lib/includes/gnutls/self-test.h b/lib/includes/gnutls/self-test.h
index 958c0da8f7..88b5a8dbf9 100644
--- a/lib/includes/gnutls/self-test.h
+++ b/lib/includes/gnutls/self-test.h
@@ -36,5 +36,6 @@ 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);
int gnutls_pbkdf2_self_test(unsigned flags, gnutls_mac_algorithm_t mac);
+int gnutls_tlsprf_self_test(unsigned flags, gnutls_mac_algorithm_t mac);
#endif /* GNUTLS_SELF_TEST_H */
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index f5537a3868..643d400a1f 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1349,6 +1349,7 @@ GNUTLS_FIPS140_3_4 {
gnutls_digest_self_test;
gnutls_hkdf_self_test;
gnutls_pbkdf2_self_test;
+ gnutls_tlsprf_self_test;
#for FIPS140-2 validation
drbg_aes_reseed;
drbg_aes_init;