diff options
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | lib/algorithms/ciphers.c | 21 | ||||
-rw-r--r-- | lib/algorithms/mac.c | 8 | ||||
-rw-r--r-- | lib/buffers.c | 8 | ||||
-rw-r--r-- | lib/crypto-selftests-pk.c | 90 | ||||
-rw-r--r-- | lib/crypto-selftests.c | 280 | ||||
-rw-r--r-- | lib/dtls.c | 8 | ||||
-rw-r--r-- | lib/dtls.h | 2 | ||||
-rw-r--r-- | lib/ext/heartbeat.c | 8 | ||||
-rw-r--r-- | lib/ext/pre_shared_key.c | 27 | ||||
-rw-r--r-- | lib/fips.h | 5 | ||||
-rw-r--r-- | lib/gnutls_int.h | 20 | ||||
-rw-r--r-- | lib/handshake.c | 2 | ||||
-rw-r--r-- | lib/handshake.h | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 10 | ||||
-rw-r--r-- | lib/libgnutls.map | 2 | ||||
-rw-r--r-- | lib/nettle/Makefile.am | 3 | ||||
-rw-r--r-- | lib/nettle/backport/cfb8.c | 117 | ||||
-rw-r--r-- | lib/nettle/backport/cfb8.h | 96 | ||||
-rw-r--r-- | lib/nettle/backport/cmac.c | 213 | ||||
-rw-r--r-- | lib/nettle/backport/cmac.h | 140 | ||||
-rw-r--r-- | lib/nettle/cipher.c | 69 | ||||
-rw-r--r-- | lib/nettle/mac.c | 37 | ||||
-rw-r--r-- | lib/nettle/rnd.c | 2 | ||||
-rw-r--r-- | lib/session_pack.c | 12 | ||||
-rw-r--r-- | lib/str.h | 42 | ||||
-rw-r--r-- | lib/system.c | 22 | ||||
-rw-r--r-- | lib/system.h | 19 | ||||
-rw-r--r-- | lib/tls13/session_ticket.c | 22 | ||||
-rw-r--r-- | lib/tls13/session_ticket.h | 6 | ||||
-rw-r--r-- | tests/virt-time.h | 27 |
32 files changed, 1266 insertions, 79 deletions
@@ -10,11 +10,24 @@ See the end for copying conditions. ** libgnutls: Provide the option of transparent re-handshake/reauthentication when the GNUTLS_AUTO_REAUTH flag is specified in gnutls_init(). +** libgnutls: Added support for AES-CFB8 cipher (#357) + +** libgnutls: Added support for AES-CMAC MAC (#351) + ** p11tool: fix initialization of security officer's PIN with the --initialize-so-pin option (#561) +** In two previous versions GNUTLS_CIPHER_GOST28147_CPB/CPC/CPD_CFB ciphers + have incorrectly used CryptoPro-A S-BOX instead of proper (CryptoPro-B/-C/-D + S-BOXes). They are fixed now. + ** API and ABI modifications: GNUTLS_AUTO_REAUTH: Added +GNUTLS_CIPHER_AES_128_CFB8: Added +GNUTLS_CIPHER_AES_192_CFB8: Added +GNUTLS_CIPHER_AES_256_CFB8: Added +GNUTLS_MAC_AES_CMAC_128: Added +GNUTLS_MAC_AES_CMAC_256: Added * Version 3.6.4 (released 2018-09-24) diff --git a/configure.ac b/configure.ac index 95c756e8bd..3f87907516 100644 --- a/configure.ac +++ b/configure.ac @@ -559,6 +559,18 @@ if test "$enable_non_suiteb" = "yes";then fi AM_CONDITIONAL(ENABLE_NON_SUITEB_CURVES, test "$enable_non_suiteb" = "yes") +# Check if nettle has CFB8 support +save_LIBS=$LIBS +LIBS="$LIBS $NETTLE_LIBS" +AC_CHECK_FUNCS(nettle_cfb8_encrypt) +LIBS=$save_LIBS + +# Check if nettle has CMAC support +save_LIBS=$LIBS +LIBS="$LIBS $NETTLE_LIBS" +AC_CHECK_FUNCS(nettle_cmac128_update) +LIBS=$save_LIBS + AC_MSG_CHECKING([whether to build libdane]) AC_ARG_ENABLE(libdane, AS_HELP_STRING([--disable-libdane], diff --git a/lib/algorithms/ciphers.c b/lib/algorithms/ciphers.c index bbdb1c8524..1a8704be25 100644 --- a/lib/algorithms/ciphers.c +++ b/lib/algorithms/ciphers.c @@ -219,6 +219,27 @@ static const cipher_entry_st algorithms[] = { .type = CIPHER_STREAM, .implicit_iv = 8, .cipher_iv = 8}, + { .name = "AES-128-CFB8", + .id = GNUTLS_CIPHER_AES_128_CFB8, + .blocksize = 16, + .keysize = 16, + .type = CIPHER_BLOCK, + .explicit_iv = 16, + .cipher_iv = 16}, + { .name = "AES-192-CFB8", + .id = GNUTLS_CIPHER_AES_192_CFB8, + .blocksize = 16, + .keysize = 24, + .type = CIPHER_BLOCK, + .explicit_iv = 16, + .cipher_iv = 16}, + { .name = "AES-256-CFB8", + .id = GNUTLS_CIPHER_AES_256_CFB8, + .blocksize = 16, + .keysize = 32, + .type = CIPHER_BLOCK, + .explicit_iv = 16, + .cipher_iv = 16}, { .name = "3DES-CBC", .id = GNUTLS_CIPHER_3DES_CBC, .blocksize = 8, diff --git a/lib/algorithms/mac.c b/lib/algorithms/mac.c index 6573b35686..d027ca5ea4 100644 --- a/lib/algorithms/mac.c +++ b/lib/algorithms/mac.c @@ -153,6 +153,14 @@ static const mac_entry_st hash_algorithms[] = { .output_size = 64, .key_size = 64, .block_size = 64}, + {.name = "AES-CMAC-128", + .id = GNUTLS_MAC_AES_CMAC_128, + .output_size = 16, + .key_size = 16,}, + {.name = "AES-CMAC-256", + .id = GNUTLS_MAC_AES_CMAC_256, + .output_size = 16, + .key_size = 32}, {.name = "MAC-NULL", .id = GNUTLS_MAC_NULL}, {0, 0, 0, 0, 0, 0, 0, 0, 0} diff --git a/lib/buffers.c b/lib/buffers.c index cee0d5fc59..78fe6e22cc 100644 --- a/lib/buffers.c +++ b/lib/buffers.c @@ -252,7 +252,7 @@ _gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel, ret = _gnutls_io_check_recv(session, *ms); if (ret < 0) return gnutls_assert_val(ret); - gettime(&t1); + gnutls_gettime(&t1); } *bufel = _mbuffer_alloc_align16(max_size, get_total_headers(session)); @@ -287,7 +287,7 @@ _gnutls_dgram_read(gnutls_session_t session, mbuffer_st ** bufel, } if (ms && *ms > 0) { - gettime(&t2); + gnutls_gettime(&t2); diff = timespec_sub_ms(&t2, &t1); if (diff < *ms) *ms -= diff; @@ -338,7 +338,7 @@ _gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel, goto cleanup; } - gettime(&t1); + gnutls_gettime(&t1); } reset_errno(session); @@ -383,7 +383,7 @@ _gnutls_stream_read(gnutls_session_t session, mbuffer_st ** bufel, (*bufel)->msg.size += i; if (ms && *ms > 0 && *ms != GNUTLS_INDEFINITE_TIMEOUT) { - gettime(&t2); + gnutls_gettime(&t2); diff = timespec_sub_ms(&t2, &t1); if (diff < *ms) *ms -= diff; diff --git a/lib/crypto-selftests-pk.c b/lib/crypto-selftests-pk.c index ea30d848dc..c7d1934f28 100644 --- a/lib/crypto-selftests-pk.c +++ b/lib/crypto-selftests-pk.c @@ -88,6 +88,24 @@ static const char dsa_key[] = "VzO8qcrLCFvTOXY=\n" "-----END DSA PRIVATE KEY-----\n"; +static const char gost01_key[] = + "-----BEGIN PRIVATE KEY-----\n" + "MEUCAQAwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEEIgQgR1lBLIr4WBpn\n" + "4MOCH8oxGWb52EPNL3gjNJiQuBQuf6U=\n" + "-----END PRIVATE KEY-----\n"; + +static const char gost12_256_key[] = + "-----BEGIN PRIVATE KEY-----\n" + "MEgCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIkAAYIKoUDBwEBAgIEIgQg0+JttJEV\n" + "Ud+XBzX9q13ByKK+j2b+mEmNIo1yB0wGleo=\n" + "-----END PRIVATE KEY-----\n"; + +static const char gost12_512_key[] = + "-----BEGIN PRIVATE KEY-----\n" + "MGoCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRCBECS7bAh\n" + "TP5um5bxziaKkhb6xSI5WBQCSlaiHPBaMbgmgJiF8RubF7k0YMefpt0+sA3GvVGA\n" + "KjL7CLBERDm7Yvlv\n" + "-----END PRIVATE KEY-----\n"; static int test_rsa_enc(gnutls_pk_algorithm_t pk, unsigned bits, gnutls_digest_algorithm_t ign) @@ -173,11 +191,15 @@ static int test_sig(gnutls_pk_algorithm_t pk, gnutls_datum_t raw_rsa_key = { (void*)rsa_key2048, sizeof(rsa_key2048)-1 }; gnutls_datum_t raw_dsa_key = { (void*)dsa_key, sizeof(dsa_key)-1 }; gnutls_datum_t raw_ecc_key = { (void*)ecc_key, sizeof(ecc_key)-1 }; + gnutls_datum_t raw_gost01_key = { (void*)gost01_key, sizeof(gost01_key)-1 }; + gnutls_datum_t raw_gost12_256_key = { (void*)gost12_256_key, sizeof(gost12_256_key)-1 }; + gnutls_datum_t raw_gost12_512_key = { (void*)gost12_512_key, sizeof(gost12_512_key)-1 }; gnutls_privkey_t key; gnutls_pubkey_t pub = NULL; char param_name[32]; - if (pk == GNUTLS_PK_EC) { + if (pk == GNUTLS_PK_EC || pk == GNUTLS_PK_GOST_01 || + pk == GNUTLS_PK_GOST_12_256 || pk == GNUTLS_PK_GOST_12_512) { snprintf(param_name, sizeof(param_name), "%s", gnutls_ecc_curve_get_name(GNUTLS_BITS_TO_CURVE (bits))); @@ -201,6 +223,12 @@ static int test_sig(gnutls_pk_algorithm_t pk, ret = gnutls_privkey_import_x509_raw(key, &raw_dsa_key, GNUTLS_X509_FMT_PEM, NULL, 0); } else if (pk == GNUTLS_PK_ECC) { ret = gnutls_privkey_import_x509_raw(key, &raw_ecc_key, GNUTLS_X509_FMT_PEM, NULL, 0); + } else if (pk == GNUTLS_PK_GOST_01) { + ret = gnutls_privkey_import_x509_raw(key, &raw_gost01_key, GNUTLS_X509_FMT_PEM, NULL, 0); + } else if (pk == GNUTLS_PK_GOST_12_256) { + ret = gnutls_privkey_import_x509_raw(key, &raw_gost12_256_key, GNUTLS_X509_FMT_PEM, NULL, 0); + } else if (pk == GNUTLS_PK_GOST_12_512) { + ret = gnutls_privkey_import_x509_raw(key, &raw_gost12_512_key, GNUTLS_X509_FMT_PEM, NULL, 0); } else { gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; @@ -343,6 +371,34 @@ static const char dsa_privkey[] = static const char dsa_sig[] = "\x30\x3d\x02\x1c\x2e\x40\x14\xb3\x7a\x3f\xc0\x4f\x06\x74\x4f\xa6\x5f\xc2\x0a\x46\x35\x38\x88\xb4\x1a\xcf\x94\x02\x40\x42\x7c\x7f\x02\x1d\x00\x98\xfc\xf1\x08\x66\xf1\x86\x28\xc9\x73\x9e\x2b\x5d\xce\x57\xe8\xb5\xeb\xcf\xa3\xf6\x60\xf6\x63\x16\x0e\xc0\x42"; +static const char gost01_privkey[] = + "-----BEGIN PRIVATE KEY-----\n" + "MEUCAQAwHAYGKoUDAgITMBIGByqFAwICIwEGByqFAwICHgEEIgQgdNfuHGmmTdPm\n" + "p5dAa3ea9UYxpdYQPP9lbDwzQwG2bJM=\n" + "-----END PRIVATE KEY-----\n"; + +static const char gost01_sig[] = + "\xc5\xc8\xf8\xdc\x22\x51\xb0\x72\xe9\xa2\xbb\x84\x6c\xe2\x24\xd5\x72\x39\x2a\x5a\x0e\x7a\x43\xfc\x9c\xc3\x5d\x32\x92\xbb\xab\xc0\x4b\x99\xbd\xc8\x47\x24\x70\x06\x7e\xa1\xc6\xe3\xa0\xdc\x42\xed\xa0\x66\xf0\xcc\x50\x97\xe9\x5a\x7d\x3f\x65\x2d\x7b\x1b\x03\xcb"; + +static const char gost12_256_privkey[] = + "-----BEGIN PRIVATE KEY-----\n" + "MEgCAQAwHwYIKoUDBwEBAQEwEwYHKoUDAgIjAQYIKoUDBwEBAgIEIgQgKOF96tom\n" + "D61rhSnzKjyrmO3fv0gdlHei+6ovrc8SnBk=\n" + "-----END PRIVATE KEY-----\n"; + +static const char gost12_256_sig[] = + "\xb2\x51\x5a\x1a\xbd\x95\x4e\x71\x55\xad\x74\x74\x81\xa6\xca\x6c\x14\x01\xe0\x18\xda\xe4\x0d\x02\x4f\x14\xd2\x39\xd6\x3c\xb5\x85\xa8\x37\xfd\x7f\x2b\xfa\xe4\xf5\xbc\xbc\x15\x20\x8b\x83\x4b\x84\x0d\x5d\x02\x21\x8c\x0d\xb9\xc4\x2b\xc0\x3e\xfd\x42\x55\x1d\xb0"; + +static const char gost12_512_privkey[] = + "-----BEGIN PRIVATE KEY-----\n" + "MGoCAQAwIQYIKoUDBwEBAQIwFQYJKoUDBwECAQIBBggqhQMHAQECAwRCBECjFpvp\n" + "B0vdc7u59b99TCNXhHiB69JJtUjvieNkGYJpoaaIvoKZTNCjpSZASsZcQZCHOTof\n" + "hsQ3JCCy4xnd5jWT\n" + "-----END PRIVATE KEY-----\n"; + +static const char gost12_512_sig[] = + "\x52\x4f\xa2\x77\x51\xd2\xc5\xef\xd3\xa3\x99\x4e\xec\xff\xc6\xe9\xfc\x2f\xc0\x28\x42\x03\x95\x6c\x9a\x38\xee\xea\x89\x79\xae\x1a\xc3\x68\x5e\xe4\x15\x15\x4b\xec\x0f\xf1\x7e\x0f\xba\x01\xc7\x84\x16\xc7\xb5\xac\x9d\x0c\x22\xdd\x31\xf7\xb0\x9b\x59\x4b\xf0\x02\xa8\x7d\xfd\x6d\x02\x43\xc7\x4f\x65\xbd\x84\x5c\x54\x91\xba\x75\x9f\x5a\x61\x19\x5c\x9a\x10\x78\x34\xa0\xa6\xf6\xdc\xb6\xb0\x50\x22\x38\x5f\xb0\x16\x66\xf1\xd5\x46\x00\xd5\xe2\xa8\xe5\xd2\x11\x5f\xd1\xbe\x6e\xac\xb2\x9c\x14\x34\x96\xe7\x58\x94\xb8\xf4\x5f"; + static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits, gnutls_digest_algorithm_t dig, const void *privkey, size_t privkey_size, @@ -356,7 +412,8 @@ static int test_known_sig(gnutls_pk_algorithm_t pk, unsigned bits, gnutls_privkey_t key; char param_name[32]; - if (pk == GNUTLS_PK_EC) { + if (pk == GNUTLS_PK_EC || pk == GNUTLS_PK_GOST_01 || + pk == GNUTLS_PK_GOST_12_256 || pk == GNUTLS_PK_GOST_12_512) { snprintf(param_name, sizeof(param_name), "%s", gnutls_ecc_curve_get_name(GNUTLS_BITS_TO_CURVE (bits))); @@ -794,6 +851,35 @@ int gnutls_pk_self_test(unsigned flags, gnutls_pk_algorithm_t pk) GNUTLS_DIG_SHA256); #endif +#if ENABLE_GOST + FALLTHROUGH; + case GNUTLS_PK_GOST_01: + PK_KNOWN_TEST(GNUTLS_PK_GOST_01, 0, GNUTLS_ECC_CURVE_GOST256CPA, GNUTLS_DIG_GOSTR_94, + gost01_privkey, gost01_sig); + PK_TEST(GNUTLS_PK_GOST_01, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST256CPA), GNUTLS_DIG_GOSTR_94); + + if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL)) + return 0; + + FALLTHROUGH; + case GNUTLS_PK_GOST_12_256: + PK_KNOWN_TEST(GNUTLS_PK_GOST_12_256, 0, GNUTLS_ECC_CURVE_GOST256CPA, GNUTLS_DIG_STREEBOG_256, + gost12_256_privkey, gost12_256_sig); + PK_TEST(GNUTLS_PK_GOST_12_256, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST256CPA), GNUTLS_DIG_STREEBOG_256); + + if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL)) + return 0; + + FALLTHROUGH; + case GNUTLS_PK_GOST_12_512: + PK_KNOWN_TEST(GNUTLS_PK_GOST_12_512, 0, GNUTLS_ECC_CURVE_GOST512A, GNUTLS_DIG_STREEBOG_512, + gost12_512_privkey, gost12_512_sig); + PK_TEST(GNUTLS_PK_GOST_12_256, test_sig, GNUTLS_CURVE_TO_BITS(GNUTLS_ECC_CURVE_GOST512A), GNUTLS_DIG_STREEBOG_256); + + if (!(flags & GNUTLS_SELF_TEST_FLAG_ALL)) + return 0; +#endif + break; default: return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c index 1e51dfd6c3..3d24c3aede 100644 --- a/lib/crypto-selftests.c +++ b/lib/crypto-selftests.c @@ -373,6 +373,132 @@ const struct cipher_vectors_st arcfour_vectors[] = { /* RFC6229 */ }, }; +const struct cipher_vectors_st aes128_cfb8_vectors[] = { /* NIST 800-38a */ + { + STR(key, key_size, + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c"), + STR(plaintext, plaintext_size, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d"), + .ciphertext = (uint8_t *) + "\x3b\x79\x42\x4c\x9c\x0d\xd4\x36\xba\xce\x9e\x0e\xd4\x58\x6a\x4f" + "\x32\xb9", + STR(iv, iv_size, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"), + }, +}; + +const struct cipher_vectors_st aes192_cfb8_vectors[] = { /* NIST 800-38a */ + { + STR(key, key_size, + "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" + "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b"), + STR(plaintext, plaintext_size, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d"), + .ciphertext = (uint8_t *) + "\xcd\xa2\x52\x1e\xf0\xa9\x05\xca\x44\xcd\x05\x7c\xbf\x0d\x47\xa0" + "\x67\x8a", + STR(iv, iv_size, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"), + }, +}; + +const struct cipher_vectors_st aes256_cfb8_vectors[] = { /* NIST 800-38a */ + { + STR(key, key_size, + "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4"), + STR(plaintext, plaintext_size, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" + "\xae\x2d"), + .ciphertext = (uint8_t *) + "\xdc\x1f\x1a\x85\x20\xa6\x4d\xb5\x5f\xcc\x8a\xc5\x54\x84\x4e\x88" + "\x97\x00", + STR(iv, iv_size, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"), + }, +}; + +/* GOST 28147-89 vectors come from the testsuite contributed to OpenSSL by + * Sergey E. Leontiev. CryptoPro-B test vector is just truncated. + * TC26Z is calculated using Nettle */ +const struct cipher_vectors_st gost28147_cpa_cfb_vectors[] = { + { + STR(key, key_size, + "\x8d\x5a\x2c\x83\xa7\xc7\x0a\x61\xd6\x1b\x34\xb5\x1f\xdf\x42\x68" + "\x66\x71\xa3\x5d\x87\x4c\xfd\x84\x99\x36\x63\xb6\x1e\xd6\x0d\xad"), + STR(plaintext, plaintext_size, + "\xd2\xfd\xf8\x3a\xc1\xb4\x39\x23\x2e\xaa\xcc\x98\x0a\x02\xda\x33"), + .ciphertext = (uint8_t *) + "\x88\xb7\x75\x16\x74\xa5\xee\x2d\x14\xfe\x91\x67\xd0\x5c\xcc\x40", + STR(iv, iv_size, + "\x46\x60\x6f\x0d\x88\x34\x23\x5a"), + }, +}; + +const struct cipher_vectors_st gost28147_cpb_cfb_vectors[] = { + { + STR(key, key_size, + "\x48\x0c\x74\x1b\x02\x6b\x55\xd5\xb6\x6d\xd7\x1d\x40\x48\x05\x6b" + "\x6d\xeb\x3c\x29\x0f\x84\x80\x23\xee\x0d\x47\x77\xe3\xfe\x61\xc9"), + STR(plaintext, plaintext_size, + "\x8c\x9c\x44\x35\xfb\xe9\xa5\xa3\xa0\xae\x28\x56\x91\x10\x8e\x1e" + "\xd2\xbb\x18\x53\x81\x27\x0d\xa6\x68\x59\x36\xc5\x81\x62\x9a\x8e" + "\x7d\x50\xf1\x6f\x97\x62\x29\xec\x80\x51\xe3\x7d\x6c\xc4\x07\x95" + "\x28\x63\xdc\xb4\xb9\x2d\xb8\x13\xb1\x05\xb5\xf9\xeb\x75\x37"), + .ciphertext = (uint8_t *) + "\x23\xc6\x7f\x20\xa1\x23\x58\xbc\x7b\x05\xdb\x21\x15\xcf\x96\x41" + "\xc7\x88\xef\x76\x5c\x49\xdb\x42\xbf\xf3\xc0\xf5\xbd\x5d\xd9\x8e" + "\xaf\x3d\xf4\xe4\xda\x88\xbd\xbc\x47\x5d\x76\x07\xc9\x5f\x54\x1d" + "\x1d\x6a\xa1\x2e\x18\xd6\x60\x84\x02\x18\x37\x92\x92\x15\xab", + STR(iv, iv_size, + "\x1f\x3f\x82\x1e\x0d\xd8\x1e\x22"), + }, +}; + +const struct cipher_vectors_st gost28147_cpc_cfb_vectors[] = { + { + STR(key, key_size, + "\x77\xc3\x45\x8e\xf6\x42\xe7\x04\x8e\xfc\x08\xe4\x70\x96\xd6\x05" + "\x93\x59\x02\x6d\x6f\x97\xca\xe9\xcf\x89\x44\x4b\xde\x6c\x22\x1d"), + STR(plaintext, plaintext_size, + "\x07\x9c\x91\xbe"), + .ciphertext = (uint8_t *) + "\x19\x35\x81\x34", + STR(iv, iv_size, + "\x43\x7c\x3e\x8e\x2f\x2a\x00\x98"), + }, +}; + +const struct cipher_vectors_st gost28147_cpd_cfb_vectors[] = { + { + STR(key, key_size, + "\x38\x9f\xe8\x37\xff\x9c\x5d\x29\xfc\x48\x55\xa0\x87\xea\xe8\x40" + "\x20\x87\x5b\xb2\x01\x15\x55\xa7\xe3\x2d\xcb\x3d\xd6\x59\x04\x73"), + STR(plaintext, plaintext_size, + "\x2f\x31\xd8\x83\xb4\x20\xe8\x6e\xda"), + .ciphertext = (uint8_t *) + "\x6d\xa4\xed\x40\x08\x88\x71\xad\x16", + STR(iv, iv_size, + "\xc5\xa2\xd2\x1f\x2f\xdf\xb8\xeb"), + }, +}; + +const struct cipher_vectors_st gost28147_tc26z_cfb_vectors[] = { + { + STR(key, key_size, + "\x8d\x5a\x2c\x83\xa7\xc7\x0a\x61\xd6\x1b\x34\xb5\x1f\xdf\x42\x68" + "\x66\x71\xa3\x5d\x87\x4c\xfd\x84\x99\x36\x63\xb6\x1e\xd6\x0d\xad"), + STR(plaintext, plaintext_size, + "\xd2\xfd\xf8\x3a\xc1\xb4\x39\x23\x2e\xaa\xcc\x98\x0a\x02\xda\x33"), + .ciphertext = (uint8_t *) + "\xed\xa7\xf1\x41\x01\x9c\xbd\xcd\x44\x6b\x00\x96\x87\xf7\xc7\xe6", + STR(iv, iv_size, + "\x46\x60\x6f\x0d\x88\x34\x23\x5a"), + }, +}; + static int test_cipher(gnutls_cipher_algorithm_t cipher, const struct cipher_vectors_st *vectors, size_t vectors_size, unsigned flags) @@ -1089,6 +1215,47 @@ const struct hash_vectors_st sha3_512_vectors[] = { }, }; +const struct hash_vectors_st gostr_94_vectors[] = { + { + STR(plaintext, plaintext_size, + "The quick brown fox jumps over the lazy dog"), + STR(output, output_size, + "\x90\x04\x29\x4a\x36\x1a\x50\x8c\x58\x6f\xe5\x3d\x1f\x1b\x02\x74\x67\x65\xe7\x1b\x76\x54\x72\x78\x6e\x47\x70\xd5\x65\x83\x0a\x76"), + }, +}; + +/* GOST R 34.11-2012 */ +const struct hash_vectors_st streebog_512_vectors[] = { + { + STR(plaintext, plaintext_size, + "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee" + "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20" + "\xf1\x20\xec\xee\xf0\xff\x20\xf1\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20" + "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0\xfb\xff\x20\xef\xeb\xfa\xea\xfb" + "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb"), + STR(output, output_size, + "\x1e\x88\xe6\x22\x26\xbf\xca\x6f\x99\x94\xf1\xf2\xd5\x15\x69\xe0" + "\xda\xf8\x47\x5a\x3b\x0f\xe6\x1a\x53\x00\xee\xe4\x6d\x96\x13\x76" + "\x03\x5f\xe8\x35\x49\xad\xa2\xb8\x62\x0f\xcd\x7c\x49\x6c\xe5\xb3" + "\x3f\x0c\xb9\xdd\xdc\x2b\x64\x60\x14\x3b\x03\xda\xba\xc9\xfb\x28"), + }, +}; + +/* GOST R 34.11-2012 */ +const struct hash_vectors_st streebog_256_vectors[] = { + { + STR(plaintext, plaintext_size, + "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee" + "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20" + "\xf1\x20\xec\xee\xf0\xff\x20\xf1\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20" + "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0\xfb\xff\x20\xef\xeb\xfa\xea\xfb" + "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb"), + STR(output, output_size, + "\x9d\xd2\xfe\x4e\x90\x40\x9e\x5d\xa8\x7f\x53\x97\x6d\x74\x05\xb0" + "\xc0\xca\xc6\x28\xfc\x66\x9a\x74\x1d\x50\x06\x3c\x55\x7e\x8f\x50"), + }, +}; + #define HASH_DATA_SIZE 64 /* SHA1 and other hashes */ @@ -1214,6 +1381,73 @@ const struct mac_vectors_st hmac_sha512_vectors[] = { }, }; +/* Calculated */ +const struct mac_vectors_st hmac_gostr_94_vectors[] = { + { + STR(key, key_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"), + STR(plaintext, plaintext_size, + "\x01\x26\xbd\xb8\x78\x00\xaf\x21\x43\x41\x45\x65\x63\x78\x01\x00"), + STR(output, output_size, + "\xba\xd7\x0b\x61\xc4\x10\x95\xbc\x47\xe1\x14\x1c\xfa\xed\x42\x72" + "\x6a\x5c\xee\xbd\x62\xce\x75\xdb\xbb\x9a\xd7\x6c\xda\x9f\x72\xf7"), + }, +}; + +/* RFC 7836 */ +const struct mac_vectors_st hmac_streebog_512_vectors[] = { + { + STR(key, key_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"), + STR(plaintext, plaintext_size, + "\x01\x26\xbd\xb8\x78\x00\xaf\x21\x43\x41\x45\x65\x63\x78\x01\x00"), + STR(output, output_size, + "\xa5\x9b\xab\x22\xec\xae\x19\xc6\x5f\xbd\xe6\xe5\xf4\xe9\xf5\xd8" + "\x54\x9d\x31\xf0\x37\xf9\xdf\x9b\x90\x55\x00\xe1\x71\x92\x3a\x77" + "\x3d\x5f\x15\x30\xf2\xed\x7e\x96\x4c\xb2\xee\xdc\x29\xe9\xad\x2f" + "\x3a\xfe\x93\xb2\x81\x4f\x79\xf5\x00\x0f\xfc\x03\x66\xc2\x51\xe6"), + }, +}; + +/* RFC 7836 */ +const struct mac_vectors_st hmac_streebog_256_vectors[] = { + { + STR(key, key_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"), + STR(plaintext, plaintext_size, + "\x01\x26\xbd\xb8\x78\x00\xaf\x21\x43\x41\x45\x65\x63\x78\x01\x00"), + STR(output, output_size, + "\xa1\xaa\x5f\x7d\xe4\x02\xd7\xb3\xd3\x23\xf2\x99\x1c\x8d\x45\x34" + "\x01\x31\x37\x01\x0a\x83\x75\x4f\xd0\xaf\x6d\x7c\xd4\x92\x2e\xd9"), + }, +}; + +const struct mac_vectors_st aes_cmac_128_vectors[] = { /* NIST SP800-38A */ + { + STR(key, key_size, + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c"), + STR(plaintext, plaintext_size, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"), + STR(output, output_size, + "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c"), + }, +}; + +const struct mac_vectors_st aes_cmac_256_vectors[] = { /* NIST SP800-38A */ + { + STR(key, key_size, + "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" + "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4"), + STR(plaintext, plaintext_size, + "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a"), + STR(output, output_size, + "\x28\xa7\x02\x3f\x45\x2e\x8f\x82\xbd\x4b\xf2\x8d\x8c\x37\xc3\x5c"), + }, +}; + static int test_mac(gnutls_mac_algorithm_t mac, const struct mac_vectors_st *vectors, size_t vectors_size, unsigned flags) @@ -1339,6 +1573,32 @@ int gnutls_cipher_self_test(unsigned flags, gnutls_cipher_algorithm_t cipher) FALLTHROUGH; NON_FIPS_CASE(GNUTLS_CIPHER_CHACHA20_POLY1305, test_cipher_aead, chacha_poly1305_vectors); + FALLTHROUGH; + CASE(GNUTLS_CIPHER_AES_128_CFB8, test_cipher, + aes128_cfb8_vectors); + FALLTHROUGH; + CASE(GNUTLS_CIPHER_AES_192_CFB8, test_cipher, + aes192_cfb8_vectors); + FALLTHROUGH; + CASE(GNUTLS_CIPHER_AES_256_CFB8, test_cipher, + aes256_cfb8_vectors); +#if ENABLE_GOST + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_CPA_CFB, test_cipher, + gost28147_cpa_cfb_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_CPB_CFB, test_cipher, + gost28147_cpb_cfb_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_CPC_CFB, test_cipher, + gost28147_cpc_cfb_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_CPD_CFB, test_cipher, + gost28147_cpd_cfb_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_CIPHER_GOST28147_TC26Z_CFB, test_cipher, + gost28147_tc26z_cfb_vectors); +#endif break; default: return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); @@ -1378,6 +1638,18 @@ int gnutls_mac_self_test(unsigned flags, gnutls_mac_algorithm_t mac) CASE(GNUTLS_MAC_SHA384, test_mac, hmac_sha384_vectors); FALLTHROUGH; CASE(GNUTLS_MAC_SHA512, test_mac, hmac_sha512_vectors); +#if ENABLE_GOST + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_MAC_GOSTR_94, test_mac, hmac_gostr_94_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_MAC_STREEBOG_512, test_mac, hmac_streebog_512_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_MAC_STREEBOG_256, test_mac, hmac_streebog_256_vectors); +#endif + FALLTHROUGH; + CASE(GNUTLS_MAC_AES_CMAC_128, test_mac, aes_cmac_128_vectors); + FALLTHROUGH; + CASE(GNUTLS_MAC_AES_CMAC_256, test_mac, aes_cmac_256_vectors); break; default: @@ -1428,6 +1700,14 @@ int gnutls_digest_self_test(unsigned flags, gnutls_digest_algorithm_t digest) FALLTHROUGH; CASE(GNUTLS_DIG_SHA3_512, test_digest, sha3_512_vectors); #endif +#if ENABLE_GOST + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_DIG_GOSTR_94, test_digest, gostr_94_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_DIG_STREEBOG_512, test_digest, streebog_512_vectors); + FALLTHROUGH; + NON_FIPS_CASE(GNUTLS_DIG_STREEBOG_256, test_digest, streebog_256_vectors); +#endif break; default: return gnutls_assert_val(GNUTLS_E_NO_SELF_TEST); diff --git a/lib/dtls.c b/lib/dtls.c index 07c3495a46..a22379ece1 100644 --- a/lib/dtls.c +++ b/lib/dtls.c @@ -234,7 +234,7 @@ int _dtls_transmit(gnutls_session_t session) unsigned int diff; struct timespec now; - gettime(&now); + gnutls_gettime(&now); /* If we have already sent a flight and we are operating in a * non blocking way, check if it is time to retransmit or just @@ -321,7 +321,7 @@ int _dtls_transmit(gnutls_session_t session) last_type = cur->htype; } - gettime(&session->internals.dtls.last_retransmit); + gnutls_gettime(&session->internals.dtls.last_retransmit); if (session->internals.dtls.flight_init == 0) { session->internals.dtls.flight_init = 1; @@ -391,7 +391,7 @@ int _dtls_transmit(gnutls_session_t session) } keep_up: - gettime(&now); + gnutls_gettime(&now); } while (ret == GNUTLS_E_TIMEDOUT); if (ret < 0) { @@ -789,7 +789,7 @@ unsigned int gnutls_dtls_get_timeout(gnutls_session_t session) struct timespec now; unsigned int diff; - gettime(&now); + gnutls_gettime(&now); diff = timespec_sub_ms(&now, diff --git a/lib/dtls.h b/lib/dtls.h index c7e72cf9b7..717d3bdc6d 100644 --- a/lib/dtls.h +++ b/lib/dtls.h @@ -40,7 +40,7 @@ void _dtls_reset_window(struct record_parameters_st *rp); #define RETURN_DTLS_EAGAIN_OR_TIMEOUT(session, r) { \ struct timespec _now; \ unsigned int _diff; \ - gettime(&_now); \ + gnutls_gettime(&_now); \ \ _diff = timespec_sub_ms(&_now, &session->internals.handshake_start_time); \ if (_diff > session->internals.handshake_timeout_ms) \ diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c index 1b970fbc46..7ec26a9804 100644 --- a/lib/ext/heartbeat.c +++ b/lib/ext/heartbeat.c @@ -202,7 +202,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size, if (ret < 0) return gnutls_assert_val(ret); - gettime(&session->internals.hb_ping_start); + gnutls_gettime(&session->internals.hb_ping_start); session->internals.hb_local_data.length = data_size; session->internals.hb_state = SHB_SEND2; @@ -220,7 +220,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size, if (ret < 0) return gnutls_assert_val(ret); - gettime(&session->internals.hb_ping_sent); + gnutls_gettime(&session->internals.hb_ping_sent); if (!(flags & GNUTLS_HEARTBEAT_WAIT)) { session->internals.hb_state = SHB_SEND1; @@ -246,7 +246,7 @@ gnutls_heartbeat_ping(gnutls_session_t session, size_t data_size, return gnutls_assert_val(ret); } - gettime(&now); + gnutls_gettime(&now); diff = timespec_sub_ms(&now, &session->internals. @@ -405,7 +405,7 @@ unsigned int gnutls_heartbeat_get_timeout(gnutls_session_t session) struct timespec now; unsigned int diff; - gettime(&now); + gnutls_gettime(&now); diff = timespec_sub_ms(&now, &session->internals.hb_ping_sent); if (diff >= session->internals.hb_actual_retrans_timeout_ms) return 0; diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c index 7e61d45cb7..be18c264ff 100644 --- a/lib/ext/pre_shared_key.c +++ b/lib/ext/pre_shared_key.c @@ -33,7 +33,7 @@ #include <assert.h> static int -compute_psk_from_ticket(const tls13_ticket_t *ticket, gnutls_datum_t *key) +compute_psk_from_ticket(const tls13_ticket_st *ticket, gnutls_datum_t *key) { int ret; char label[] = "resumption"; @@ -201,7 +201,7 @@ client_send_params(gnutls_session_t session, unsigned next_idx; const mac_entry_st *prf_res = NULL; const mac_entry_st *prf_psk = NULL; - time_t cur_time; + struct timespec cur_time; uint32_t ticket_age, ob_ticket_age; int free_username = 0; psk_auth_info_t info = NULL; @@ -235,16 +235,21 @@ client_send_params(gnutls_session_t session, prf_res = session->internals.tls13_ticket.prf; - cur_time = gnutls_time(0); - if (unlikely(cur_time < session->internals.tls13_ticket.timestamp)) { + gnutls_gettime(&cur_time); + if (unlikely(_gnutls_timespec_cmp(&cur_time, + &session->internals. + tls13_ticket. + arrival_time) < 0)) { gnutls_assert(); _gnutls13_session_ticket_unset(session); goto ignore_ticket; } /* Check whether the ticket is stale */ - ticket_age = cur_time - session->internals.tls13_ticket.timestamp; - if (ticket_age > session->internals.tls13_ticket.lifetime) { + ticket_age = timespec_sub_ms(&cur_time, + &session->internals.tls13_ticket. + arrival_time); + if (ticket_age / 1000 > session->internals.tls13_ticket.lifetime) { _gnutls13_session_ticket_unset(session); goto ignore_ticket; } @@ -256,7 +261,7 @@ client_send_params(gnutls_session_t session, } /* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */ - ob_ticket_age = ticket_age * 1000 + session->internals.tls13_ticket.age_add; + ob_ticket_age = ticket_age + session->internals.tls13_ticket.age_add; if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16, session->internals.tls13_ticket.ticket.data, @@ -476,7 +481,7 @@ static int server_recv_params(gnutls_session_t session, psk_ext_iter_st psk_iter; struct psk_st psk; psk_auth_info_t info; - tls13_ticket_t ticket_data; + tls13_ticket_st ticket_data; uint32_t ticket_age; bool resuming; @@ -507,12 +512,6 @@ static int server_recv_params(gnutls_session_t session, session->internals.resumption_requested = 1; /* Check whether ticket is stale or not */ - if (psk.ob_ticket_age < ticket_data.age_add) { - gnutls_assert(); - tls13_ticket_deinit(&ticket_data); - continue; - } - ticket_age = psk.ob_ticket_age - ticket_data.age_add; if (ticket_age / 1000 > ticket_data.lifetime) { gnutls_assert(); diff --git a/lib/fips.h b/lib/fips.h index 7d3f3cfd39..df04f0c86c 100644 --- a/lib/fips.h +++ b/lib/fips.h @@ -105,6 +105,8 @@ static unsigned is_mac_algo_forbidden(gnutls_mac_algorithm_t algo) case GNUTLS_MAC_SHA3_256: case GNUTLS_MAC_SHA3_384: case GNUTLS_MAC_SHA3_512: + case GNUTLS_MAC_AES_CMAC_128: + case GNUTLS_MAC_AES_CMAC_256: return 0; default: if (mode == GNUTLS_FIPS140_LAX) @@ -139,6 +141,9 @@ static unsigned is_cipher_algo_forbidden(gnutls_cipher_algorithm_t algo) case GNUTLS_CIPHER_3DES_CBC: case GNUTLS_CIPHER_AES_128_CCM_8: case GNUTLS_CIPHER_AES_256_CCM_8: + case GNUTLS_CIPHER_AES_128_CFB8: + case GNUTLS_CIPHER_AES_192_CFB8: + case GNUTLS_CIPHER_AES_256_CFB8: return 0; default: if (mode == GNUTLS_FIPS140_LAX) diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index f32eba181d..2eff31caff 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1016,8 +1016,8 @@ typedef struct gnutls_dh_params_int { /* TLS 1.3 session ticket */ -typedef struct tls13_ticket { - time_t timestamp; +typedef struct { + struct timespec arrival_time; uint32_t lifetime; uint32_t age_add; uint8_t nonce[255]; @@ -1025,7 +1025,7 @@ typedef struct tls13_ticket { const mac_entry_st *prf; uint8_t resumption_master_secret[MAX_HASH_SIZE]; gnutls_datum_t ticket; -} tls13_ticket_t; +} tls13_ticket_st; /* DTLS session state */ @@ -1447,7 +1447,7 @@ typedef struct { /* this is only used under TLS1.2 or earlier */ int session_ticket_renew; - tls13_ticket_t tls13_ticket; + tls13_ticket_st tls13_ticket; /* the amount of early data received so far */ uint32_t early_data_received; @@ -1512,6 +1512,18 @@ unsigned int /* returns a-b in ms */ timespec_sub_ms(struct timespec *a, struct timespec *b); +inline static int _gnutls_timespec_cmp(struct timespec *a, struct timespec *b) { + if (a->tv_sec < b->tv_sec) + return -1; + if (a->tv_sec > b->tv_sec) + return 1; + if (a->tv_nsec < b->tv_nsec) + return -1; + if (a->tv_nsec > b->tv_nsec) + return 1; + return 0; +} + #include <algorithms.h> inline static int _gnutls_set_current_version(gnutls_session_t s, unsigned v) { diff --git a/lib/handshake.c b/lib/handshake.c index 841c88385d..a20c7a302a 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -2679,7 +2679,7 @@ int gnutls_handshake(gnutls_session_t session) session->internals.hsk_flags = 0; session->internals.handshake_in_progress = 1; session->internals.vc_status = -1; - gettime(&session->internals.handshake_start_time); + gnutls_gettime(&session->internals.handshake_start_time); if (session->internals.handshake_timeout_ms && session->internals.handshake_endtime == 0) session->internals.handshake_endtime = session->internals.handshake_start_time.tv_sec + diff --git a/lib/handshake.h b/lib/handshake.h index 38ef848784..ee5ee7a437 100644 --- a/lib/handshake.h +++ b/lib/handshake.h @@ -116,7 +116,7 @@ inline static int handshake_remaining_time(gnutls_session_t session) { if (session->internals.handshake_endtime) { struct timespec now; - gettime(&now); + gnutls_gettime(&now); if (now.tv_sec < session->internals.handshake_endtime) return (session->internals.handshake_endtime - diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index a5439cce56..5dcbc1c986 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -97,6 +97,9 @@ extern "C" { * @GNUTLS_CIPHER_AES_128_CBC: AES in CBC mode with 128-bit keys. * @GNUTLS_CIPHER_AES_192_CBC: AES in CBC mode with 192-bit keys. * @GNUTLS_CIPHER_AES_256_CBC: AES in CBC mode with 256-bit keys. + * @GNUTLS_CIPHER_AES_128_CFB8: AES in CFB8 mode with 128-bit keys. + * @GNUTLS_CIPHER_AES_192_CFB8: AES in CFB8 mode with 192-bit keys. + * @GNUTLS_CIPHER_AES_256_CFB8: AES in CFB8 mode with 256-bit keys. * @GNUTLS_CIPHER_ARCFOUR_40: ARCFOUR stream cipher with 40-bit keys. * @GNUTLS_CIPHER_CAMELLIA_128_CBC: Camellia in CBC mode with 128-bit keys. * @GNUTLS_CIPHER_CAMELLIA_192_CBC: Camellia in CBC mode with 192-bit keys. @@ -161,6 +164,9 @@ typedef enum gnutls_cipher_algorithm { GNUTLS_CIPHER_GOST28147_CPB_CFB = 26, GNUTLS_CIPHER_GOST28147_CPC_CFB = 27, GNUTLS_CIPHER_GOST28147_CPD_CFB = 28, + GNUTLS_CIPHER_AES_128_CFB8 = 29, + GNUTLS_CIPHER_AES_192_CFB8 = 30, + GNUTLS_CIPHER_AES_256_CFB8 = 31, /* used only for PGP internals. Ignored in TLS/SSL */ @@ -269,6 +275,8 @@ typedef enum { * @GNUTLS_MAC_AEAD: MAC implicit through AEAD cipher. * @GNUTLS_MAC_UMAC_96: The UMAC-96 MAC algorithm. * @GNUTLS_MAC_UMAC_128: The UMAC-128 MAC algorithm. + * @GNUTLS_MAC_AES_CMAC_128: The AES-CMAC-128 MAC algorithm. + * @GNUTLS_MAC_AES_CMAC_256: The AES-CMAC-256 MAC algorithm. * @GNUTLS_MAC_SHA3_224: Reserved; unimplemented. * @GNUTLS_MAC_SHA3_256: Reserved; unimplemented. * @GNUTLS_MAC_SHA3_384: Reserved; unimplemented. @@ -301,6 +309,8 @@ typedef enum { GNUTLS_MAC_AEAD = 200, /* indicates that MAC is on the cipher */ GNUTLS_MAC_UMAC_96 = 201, GNUTLS_MAC_UMAC_128 = 202, + GNUTLS_MAC_AES_CMAC_128 = 203, + GNUTLS_MAC_AES_CMAC_256 = 204, } gnutls_mac_algorithm_t; /** diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 041fda7b80..ad6613b907 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1326,4 +1326,6 @@ GNUTLS_PRIVATE_3_4 { _gnutls_server_name_set_raw; # Internal symbols needed by tests/suite/resume-with-stek-expiration _gnutls_set_session_ticket_key_rotation_callback; + # Internal symbols needed by tests/virt-time.h + _gnutls_global_set_gettime_function; } GNUTLS_3_4; diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am index bd5ec45901..b3d9ec5dac 100644 --- a/lib/nettle/Makefile.am +++ b/lib/nettle/Makefile.am @@ -24,6 +24,7 @@ AM_CFLAGS += $(HOGWEED_CFLAGS) $(GMP_CFLAGS) AM_CPPFLAGS = \ -I$(srcdir)/int \ + -I$(srcdir)/backport \ -I$(srcdir)/../../gl \ -I$(builddir)/../../gl \ -I$(srcdir)/../includes \ @@ -39,6 +40,8 @@ noinst_LTLIBRARIES = libcrypto.la libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c init.c \ gnettle.h rnd-common.h prf.c \ + backport/cfb8.c backport/cfb8.h \ + backport/cmac.c backport/cmac.h \ rnd.c int/rsa-fips.h int/rsa-keygen-fips186.c int/provable-prime.c \ int/dsa-fips.h int/dsa-keygen-fips186.c int/dsa-validate.c \ int/tls1-prf.c int/tls1-prf.h diff --git a/lib/nettle/backport/cfb8.c b/lib/nettle/backport/cfb8.c new file mode 100644 index 0000000000..30e48322fd --- /dev/null +++ b/lib/nettle/backport/cfb8.c @@ -0,0 +1,117 @@ +/* backport of cfb.c for CFB8 + + Cipher feedback mode. + + Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov + Copyright (C) 2001, 2011 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +/* ############################################# + * THIS IS A BACKPORT FROM NETTLE, DO NOT MODIFY + * ############################################# + */ + +#ifndef HAVE_NETTLE_CFB8_ENCRYPT + +#include "cfb8.h" +#include <string.h> +#include <nettle/memxor.h> + +/* CFB-8 uses slight optimization: it encrypts or decrypts up to block_size + * bytes and does memcpy/memxor afterwards */ +void +cfb8_encrypt(const void *ctx, nettle_cipher_func *f, + size_t block_size, uint8_t *iv, + size_t length, uint8_t *dst, + const uint8_t *src) +{ + TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2); + TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); + TMP_ALLOC(buffer, block_size * 2); + TMP_ALLOC(outbuf, block_size); + uint8_t pos; + + memcpy(buffer, iv, block_size); + pos = 0; + while (length) + { + uint8_t t; + + if (pos == block_size) + { + memcpy(buffer, buffer + block_size, block_size); + pos = 0; + } + + f(ctx, block_size, outbuf, buffer + pos); + t = *(dst++) = *(src++) ^ outbuf[0]; + buffer[pos + block_size] = t; + length--; + pos ++; + } + memcpy(iv, buffer + pos, block_size); +} + +void +cfb8_decrypt(const void *ctx, nettle_cipher_func *f, + size_t block_size, uint8_t *iv, + size_t length, uint8_t *dst, + const uint8_t *src) +{ + TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2); + TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2); + TMP_ALLOC(buffer, block_size * 2); + TMP_ALLOC(outbuf, block_size * 2); + uint8_t i = 0; + + memcpy(buffer, iv, block_size); + memcpy(buffer + block_size, src, + length < block_size ? length : block_size); + + while (length) + { + + for (i = 0; i < length && i < block_size; i++) + f(ctx, block_size, outbuf + i, buffer + i); + + memxor3(dst, src, outbuf, i); + + length -= i; + src += i; + dst += i; + + memcpy(buffer, buffer + block_size, block_size); + memcpy(buffer + block_size, src, + length < block_size ? length : block_size); + + } + + memcpy(iv, buffer + i, block_size); +} +#endif /* HAVE_NETTLE_CFB8_ENCRYPT */ diff --git a/lib/nettle/backport/cfb8.h b/lib/nettle/backport/cfb8.h new file mode 100644 index 0000000000..595c367edc --- /dev/null +++ b/lib/nettle/backport/cfb8.h @@ -0,0 +1,96 @@ +/* backport of cfb.h for CFB8 + + Cipher feedback mode. + + Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov + Copyright (C) 2001 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#ifndef NETTLE_CFB8_H_INCLUDED +#define NETTLE_CFB8_H_INCLUDED + +#include <nettle/cfb.h> + +#ifndef NETTLE_INTERNAL_H_INCLUDED +#define NETTLE_INTERNAL_H_INCLUDED +#if HAVE_ALLOCA +# define TMP_DECL(name, type, max) type *name +# define TMP_ALLOC(name, size) (name = alloca(sizeof (*name) * (size))) +#else /* !HAVE_ALLOCA */ +# define TMP_DECL(name, type, max) type name[max] +# define TMP_ALLOC(name, size) \ + do { if ((size) > (sizeof(name) / sizeof(name[0]))) abort(); } while (0) +#endif + +#define NETTLE_MAX_CIPHER_BLOCK_SIZE 32 +#endif /* NETTLE_INTERNAL_H_INCLUDED */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Name mangling */ +#define cfb8_encrypt _gnutls_backport_nettle_cfb8_encrypt +#define cfb8_decrypt _gnutls_backport_nettle_cfb8_decrypt + +void +cfb8_encrypt(const void *ctx, nettle_cipher_func *f, + size_t block_size, uint8_t *iv, + size_t length, uint8_t *dst, + const uint8_t *src); + +void +cfb8_decrypt(const void *ctx, nettle_cipher_func *f, + size_t block_size, uint8_t *iv, + size_t length, uint8_t *dst, + const uint8_t *src); + +#define CFB8_CTX CFB_CTX +#define CFB8_SET_IV CFB_SET_IV + +#define CFB8_ENCRYPT(self, f, length, dst, src) \ + (0 ? ((f)(&(self)->ctx, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0)) \ + : cfb8_encrypt((void *) &(self)->ctx, \ + (nettle_cipher_func *) (f), \ + sizeof((self)->iv), (self)->iv, \ + (length), (dst), (src))) + +#define CFB8_DECRYPT(self, f, length, dst, src) \ + (0 ? ((f)(&(self)->ctx, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0)) \ + : cfb8_decrypt((void *) &(self)->ctx, \ + (nettle_cipher_func *) (f), \ + sizeof((self)->iv), (self)->iv, \ + (length), (dst), (src))) + +#ifdef __cplusplus +} +#endif +#endif /* NETTLE_CFB8_H_INCLUDED */ diff --git a/lib/nettle/backport/cmac.c b/lib/nettle/backport/cmac.c new file mode 100644 index 0000000000..481e5c080d --- /dev/null +++ b/lib/nettle/backport/cmac.c @@ -0,0 +1,213 @@ +/* backport of cmac*.c for CMAC + + AES-CMAC-128 (rfc 4493) + Copyright (C) Stefan Metzmacher 2012 + Copyright (C) Jeremy Allison 2012 + Copyright (C) Michael Adam 2012 + Copyright (C) 2017, Red Hat Inc. + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +/* ############################################# + * THIS IS A BACKPORT FROM NETTLE, DO NOT MODIFY + * ############################################# + */ + +#ifndef HAVE_NETTLE_CMAC128_UPDATE + +#include <nettle/aes.h> +#include "cmac.h" +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +#include <nettle/memxor.h> +#include <nettle/macros.h> + +/* shift one and XOR with 0x87. */ +static void +block_mulx(union nettle_block16 *dst, + const union nettle_block16 *src) +{ + uint64_t b1 = READ_UINT64(src->b); + uint64_t b2 = READ_UINT64(src->b+8); + + b1 = (b1 << 1) | (b2 >> 63); + b2 <<= 1; + + if (src->b[0] & 0x80) + b2 ^= 0x87; + + WRITE_UINT64(dst->b, b1); + WRITE_UINT64(dst->b+8, b2); +} + +void +cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt) +{ + static const uint8_t const_zero[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + union nettle_block16 *L = &ctx->block; + memset(ctx, 0, sizeof(*ctx)); + + /* step 1 - generate subkeys k1 and k2 */ + encrypt(cipher, 16, L->b, const_zero); + + block_mulx(&ctx->K1, L); + block_mulx(&ctx->K2, &ctx->K1); +} + +#define MIN(x,y) ((x)<(y)?(x):(y)) + +void +cmac128_update(struct cmac128_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg) +{ + union nettle_block16 Y; + /* + * check if we expand the block + */ + if (ctx->index < 16) + { + size_t len = MIN(16 - ctx->index, msg_len); + memcpy(&ctx->block.b[ctx->index], msg, len); + msg += len; + msg_len -= len; + ctx->index += len; + } + + if (msg_len == 0) { + /* if it is still the last block, we are done */ + return; + } + + /* + * now checksum everything but the last block + */ + memxor3(Y.b, ctx->X.b, ctx->block.b, 16); + encrypt(cipher, 16, ctx->X.b, Y.b); + + while (msg_len > 16) + { + memxor3(Y.b, ctx->X.b, msg, 16); + encrypt(cipher, 16, ctx->X.b, Y.b); + msg += 16; + msg_len -= 16; + } + + /* + * copy the last block, it will be processed in + * cmac128_digest(). + */ + memcpy(ctx->block.b, msg, msg_len); + ctx->index = msg_len; +} + +void +cmac128_digest(struct cmac128_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + unsigned length, + uint8_t *dst) +{ + union nettle_block16 Y; + + memset(ctx->block.b+ctx->index, 0, sizeof(ctx->block.b)-ctx->index); + + /* re-use ctx->block for memxor output */ + if (ctx->index < 16) + { + ctx->block.b[ctx->index] = 0x80; + memxor(ctx->block.b, ctx->K2.b, 16); + } + else + { + memxor(ctx->block.b, ctx->K1.b, 16); + } + + memxor3(Y.b, ctx->block.b, ctx->X.b, 16); + + assert(length <= 16); + if (length == 16) + { + encrypt(cipher, 16, dst, Y.b); + } + else + { + encrypt(cipher, 16, ctx->block.b, Y.b); + memcpy(dst, ctx->block.b, length); + } + + /* reset state for re-use */ + memset(&ctx->X, 0, sizeof(ctx->X)); + ctx->index = 0; +} + +void +cmac_aes128_set_key(struct cmac_aes128_ctx *ctx, const uint8_t *key) +{ + CMAC128_SET_KEY(ctx, aes128_set_encrypt_key, aes128_encrypt, key); +} + +void +cmac_aes128_update (struct cmac_aes128_ctx *ctx, + size_t length, const uint8_t *data) +{ + CMAC128_UPDATE (ctx, aes128_encrypt, length, data); +} + +void +cmac_aes128_digest(struct cmac_aes128_ctx *ctx, + size_t length, uint8_t *digest) +{ + CMAC128_DIGEST(ctx, aes128_encrypt, length, digest); +} + +void +cmac_aes256_set_key(struct cmac_aes256_ctx *ctx, const uint8_t *key) +{ + CMAC128_SET_KEY(ctx, aes256_set_encrypt_key, aes256_encrypt, key); +} + +void +cmac_aes256_update (struct cmac_aes256_ctx *ctx, + size_t length, const uint8_t *data) +{ + CMAC128_UPDATE (ctx, aes256_encrypt, length, data); +} + +void +cmac_aes256_digest(struct cmac_aes256_ctx *ctx, + size_t length, uint8_t *digest) +{ + CMAC128_DIGEST(ctx, aes256_encrypt, length, digest); +} +#endif /* HAVE_NETTLE_CMAC128_UPDATE */ diff --git a/lib/nettle/backport/cmac.h b/lib/nettle/backport/cmac.h new file mode 100644 index 0000000000..94a2b06295 --- /dev/null +++ b/lib/nettle/backport/cmac.h @@ -0,0 +1,140 @@ +/* backport of cmac.h + + CMAC mode, as specified in RFC4493 + + Copyright (C) 2017 Red Hat, Inc. + + Contributed by Nikos Mavrogiannopoulos + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#ifndef NETTLE_CMAC_H_INCLUDED +#define NETTLE_CMAC_H_INCLUDED + +#include <nettle/nettle-types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define CMAC128_DIGEST_SIZE 16 + +#define cmac128_set_key _gnutls_backport_nettle_cmac128_set_key +#define cmac128_update _gnutls_backport_nettle_cmac128_update +#define cmac128_digest _gnutls_backport_nettle_cmac128_digest +#define cmac_aes128_set_key _gnutls_backport_nettle_cmac_aes128_set_key +#define cmac_aes128_update _gnutls_backport_nettle_cmac_aes128_update +#define cmac_aes128_digest _gnutls_backport_nettle_cmac_aes128_digest +#define cmac_aes256_set_key _gnutls_backport_nettle_cmac_aes256_set_key +#define cmac_aes256_update _gnutls_backport_nettle_cmac_aes256_update +#define cmac_aes256_digest _gnutls_backport_nettle_cmac_aes256_digest + +struct cmac128_ctx +{ + /* Key */ + union nettle_block16 K1; + union nettle_block16 K2; + + /* MAC state */ + union nettle_block16 X; + + /* Block buffer */ + union nettle_block16 block; + size_t index; +}; + +void +cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt); +void +cmac128_update(struct cmac128_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + size_t msg_len, const uint8_t *msg); +void +cmac128_digest(struct cmac128_ctx *ctx, const void *cipher, + nettle_cipher_func *encrypt, + unsigned length, + uint8_t *digest); + + +#define CMAC128_CTX(type) \ + { struct cmac128_ctx ctx; type cipher; } + +/* NOTE: Avoid using NULL, as we don't include anything defining it. */ +#define CMAC128_SET_KEY(self, set_key, encrypt, cmac_key) \ + do { \ + (set_key)(&(self)->cipher, (cmac_key)); \ + if (0) (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0); \ + cmac128_set_key(&(self)->ctx, &(self)->cipher, \ + (nettle_cipher_func *) (encrypt)); \ + } while (0) + +#define CMAC128_UPDATE(self, encrypt, length, src) \ + cmac128_update(&(self)->ctx, &(self)->cipher, \ + (nettle_cipher_func *)encrypt, (length), (src)) + +#define CMAC128_DIGEST(self, encrypt, length, digest) \ + (0 ? (encrypt)(&(self)->cipher, ~(size_t) 0, \ + (uint8_t *) 0, (const uint8_t *) 0) \ + : cmac128_digest(&(self)->ctx, &(self)->cipher, \ + (nettle_cipher_func *) (encrypt), \ + (length), (digest))) + +struct cmac_aes128_ctx CMAC128_CTX(struct aes128_ctx); + +void +cmac_aes128_set_key(struct cmac_aes128_ctx *ctx, const uint8_t *key); + +void +cmac_aes128_update(struct cmac_aes128_ctx *ctx, + size_t length, const uint8_t *data); + +void +cmac_aes128_digest(struct cmac_aes128_ctx *ctx, + size_t length, uint8_t *digest); + +struct cmac_aes256_ctx CMAC128_CTX(struct aes256_ctx); + +void +cmac_aes256_set_key(struct cmac_aes256_ctx *ctx, const uint8_t *key); + +void +cmac_aes256_update(struct cmac_aes256_ctx *ctx, + size_t length, const uint8_t *data); + +void +cmac_aes256_digest(struct cmac_aes256_ctx *ctx, + size_t length, uint8_t *digest); + +#ifdef __cplusplus +} +#endif + +#endif /* CMAC_H_INCLUDED */ + diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c index 24ecf8ded3..e28c39038c 100644 --- a/lib/nettle/cipher.c +++ b/lib/nettle/cipher.c @@ -36,13 +36,17 @@ #include <nettle/version.h> #if ENABLE_GOST #include "gost/gost28147.h" -#include <nettle/cfb.h> #endif #include <nettle/nettle-meta.h> #include <nettle/cbc.h> #include <nettle/gcm.h> #include <nettle/ccm.h> #include <nettle/chacha-poly1305.h> +#ifdef HAVE_NETTLE_CFB8_ENCRYPT +#include <nettle/cfb.h> +#else +#include "cfb8.h" +#endif /* HAVE_NETTLE_CFB8_ENCRYPT */ #include <fips.h> struct nettle_cipher_ctx; @@ -172,21 +176,21 @@ static void _gost28147_set_key_cpb(void *ctx, const uint8_t *key) { gost28147_set_key(ctx, key); - gost28147_set_param(ctx, &gost28147_param_CryptoPro_A); + gost28147_set_param(ctx, &gost28147_param_CryptoPro_B); } static void _gost28147_set_key_cpc(void *ctx, const uint8_t *key) { gost28147_set_key(ctx, key); - gost28147_set_param(ctx, &gost28147_param_CryptoPro_A); + gost28147_set_param(ctx, &gost28147_param_CryptoPro_C); } static void _gost28147_set_key_cpd(void *ctx, const uint8_t *key) { gost28147_set_key(ctx, key); - gost28147_set_param(ctx, &gost28147_param_CryptoPro_A); + gost28147_set_param(ctx, &gost28147_param_CryptoPro_D); } #endif @@ -258,6 +262,24 @@ static void _des3_set_key(struct des3_ctx *ctx, const uint8_t *key) des3_set_key(ctx, key); } +static void +_cfb8_encrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst, + const uint8_t * src) +{ + cfb8_encrypt(ctx->ctx_ptr, ctx->cipher->encrypt_block, + ctx->iv_size, ctx->iv, + length, dst, src); +} + +static void +_cfb8_decrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst, + const uint8_t * src) +{ + cfb8_decrypt(ctx->ctx_ptr, ctx->cipher->encrypt_block, + ctx->iv_size, ctx->iv, + length, dst, src); +} + static const struct nettle_cipher_st builtin_ciphers[] = { { .algo = GNUTLS_CIPHER_AES_128_GCM, .block_size = AES_BLOCK_SIZE, @@ -616,6 +638,45 @@ static const struct nettle_cipher_st builtin_ciphers[] = { .set_decrypt_key = _gost28147_set_key_cpd, }, #endif + { .algo = GNUTLS_CIPHER_AES_128_CFB8, + .block_size = AES_BLOCK_SIZE, + .key_size = AES128_KEY_SIZE, + .encrypt_block = (nettle_cipher_func*)aes128_encrypt, + .decrypt_block = (nettle_cipher_func*)aes128_encrypt, + + .ctx_size = sizeof(struct CFB8_CTX(struct aes128_ctx, AES_BLOCK_SIZE)), + .encrypt = _cfb8_encrypt, + .decrypt = _cfb8_decrypt, + .set_encrypt_key = (nettle_set_key_func*)aes128_set_encrypt_key, + .set_decrypt_key = (nettle_set_key_func*)aes128_set_encrypt_key, + .max_iv_size = AES_BLOCK_SIZE, + }, + { .algo = GNUTLS_CIPHER_AES_192_CFB8, + .block_size = AES_BLOCK_SIZE, + .key_size = AES192_KEY_SIZE, + .encrypt_block = (nettle_cipher_func*)aes192_encrypt, + .decrypt_block = (nettle_cipher_func*)aes192_encrypt, + + .ctx_size = sizeof(struct CFB8_CTX(struct aes192_ctx, AES_BLOCK_SIZE)), + .encrypt = _cfb8_encrypt, + .decrypt = _cfb8_decrypt, + .set_encrypt_key = (nettle_set_key_func*)aes192_set_encrypt_key, + .set_decrypt_key = (nettle_set_key_func*)aes192_set_encrypt_key, + .max_iv_size = AES_BLOCK_SIZE, + }, + { .algo = GNUTLS_CIPHER_AES_256_CFB8, + .block_size = AES_BLOCK_SIZE, + .key_size = AES256_KEY_SIZE, + .encrypt_block = (nettle_cipher_func*)aes256_encrypt, + .decrypt_block = (nettle_cipher_func*)aes256_encrypt, + + .ctx_size = sizeof(struct CFB8_CTX(struct aes256_ctx, AES_BLOCK_SIZE)), + .encrypt = _cfb8_encrypt, + .decrypt = _cfb8_decrypt, + .set_encrypt_key = (nettle_set_key_func*)aes256_set_encrypt_key, + .set_decrypt_key = (nettle_set_key_func*)aes256_set_encrypt_key, + .max_iv_size = AES_BLOCK_SIZE, + }, }; static int wrap_nettle_cipher_exists(gnutls_cipher_algorithm_t algo) diff --git a/lib/nettle/mac.c b/lib/nettle/mac.c index e46862d215..202bdc4951 100644 --- a/lib/nettle/mac.c +++ b/lib/nettle/mac.c @@ -37,6 +37,11 @@ #include "gost/gosthash94.h" #include "gost/streebog.h" #endif +#ifdef HAVE_NETTLE_CMAC128_UPDATE +#include <nettle/cmac.h> +#else +#include "cmac.h" +#endif /* HAVE_NETTLE_CMAC128_UPDATE */ typedef void (*update_func) (void *, size_t, const uint8_t *); typedef void (*digest_func) (void *, size_t, uint8_t *); @@ -93,6 +98,8 @@ struct nettle_mac_ctx { #endif struct umac96_ctx umac96; struct umac128_ctx umac128; + struct cmac_aes128_ctx cmac128; + struct cmac_aes256_ctx cmac256; } ctx; void *ctx_ptr; @@ -120,6 +127,22 @@ _wrap_umac128_set_key(void *ctx, size_t len, const uint8_t * key) umac128_set_key(ctx, key); } +static void +_wrap_cmac128_set_key(void *ctx, size_t len, const uint8_t * key) +{ + if (unlikely(len != 16)) + abort(); + cmac_aes128_set_key(ctx, key); +} + +static void +_wrap_cmac256_set_key(void *ctx, size_t len, const uint8_t * key) +{ + if (unlikely(len != 32)) + abort(); + cmac_aes256_set_key(ctx, key); +} + static int _mac_ctx_init(gnutls_mac_algorithm_t algo, struct nettle_mac_ctx *ctx) { @@ -209,6 +232,20 @@ static int _mac_ctx_init(gnutls_mac_algorithm_t algo, ctx->ctx_ptr = &ctx->ctx.umac128; ctx->length = 16; break; + case GNUTLS_MAC_AES_CMAC_128: + ctx->update = (update_func) cmac_aes128_update; + ctx->digest = (digest_func) cmac_aes128_digest; + ctx->set_key = _wrap_cmac128_set_key; + ctx->ctx_ptr = &ctx->ctx.cmac128; + ctx->length = CMAC128_DIGEST_SIZE; + break; + case GNUTLS_MAC_AES_CMAC_256: + ctx->update = (update_func) cmac_aes256_update; + ctx->digest = (digest_func) cmac_aes256_digest; + ctx->set_key = _wrap_cmac256_set_key; + ctx->ctx_ptr = &ctx->ctx.cmac256; + ctx->length = CMAC128_DIGEST_SIZE; + break; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/nettle/rnd.c b/lib/nettle/rnd.c index 9d8b250012..3f816d43ae 100644 --- a/lib/nettle/rnd.c +++ b/lib/nettle/rnd.c @@ -106,7 +106,7 @@ static int single_prng_init(struct prng_ctx_st *ctx, ctx->forkid = _gnutls_get_forkid(); - gettime(&now); + gnutls_gettime(&now); memcpy(nonce, &now, MIN(sizeof(nonce), sizeof(now))); ctx->last_reseed = now.tv_sec; } diff --git a/lib/session_pack.c b/lib/session_pack.c index 8d8abd9f3a..b83c9c7440 100644 --- a/lib/session_pack.c +++ b/lib/session_pack.c @@ -310,6 +310,7 @@ _gnutls_session_unpack(gnutls_session_t session, * x bytes the ticket * 1 bytes the resumption master secret length * x bytes the resumption master secret + * 12 bytes the ticket arrival time * * WE DON'T STORE NewSessionTicket EXTENSIONS, as we don't support them yet. * @@ -323,14 +324,12 @@ tls13_pack_security_parameters(gnutls_session_t session, gnutls_buffer_st *ps) int ret = 0; uint32_t length = 0; size_t length_pos; - tls13_ticket_t *ticket = &session->internals.tls13_ticket; + tls13_ticket_st *ticket = &session->internals.tls13_ticket; length_pos = ps->length; BUFFER_APPEND_NUM(ps, 0); if (ticket->ticket.data != NULL) { - BUFFER_APPEND_NUM(ps, ticket->timestamp); - length += 4; BUFFER_APPEND_NUM(ps, ticket->lifetime); length += 4; BUFFER_APPEND_NUM(ps, ticket->age_add); @@ -347,6 +346,8 @@ tls13_pack_security_parameters(gnutls_session_t session, gnutls_buffer_st *ps) ticket->resumption_master_secret, ticket->prf->output_size); length += (1 + ticket->prf->output_size); + BUFFER_APPEND_TS(ps, ticket->arrival_time); + length += 12; /* Overwrite the length field */ _gnutls_write_uint32(length, ps->data + length_pos); @@ -359,14 +360,13 @@ static int tls13_unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st *ps) { uint32_t ttl_len; - tls13_ticket_t *ticket = &session->internals.tls13_ticket; + tls13_ticket_st *ticket = &session->internals.tls13_ticket; gnutls_datum_t t; int ret = 0; BUFFER_POP_NUM(ps, ttl_len); if (ttl_len > 0) { - BUFFER_POP_NUM(ps, ticket->timestamp); BUFFER_POP_NUM(ps, ticket->lifetime); BUFFER_POP_NUM(ps, ticket->age_add); @@ -394,6 +394,8 @@ tls13_unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st *ps) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); ticket->prf = session->internals.resumed_security_parameters.prf; + + BUFFER_POP_TS(ps, ticket->arrival_time); } error: @@ -233,6 +233,24 @@ int _gnutls_hostname_compare(const char *certname, size_t certnamesize, } \ } +#define BUFFER_APPEND_TS(b, s) { \ + ret = _gnutls_buffer_append_prefix(b, 32, s.tv_sec >> 32); \ + if (ret < 0) { \ + gnutls_assert(); \ + return ret; \ + } \ + ret = _gnutls_buffer_append_prefix(b, 32, s.tv_sec & 0xFFFFFFFF); \ + if (ret < 0) { \ + gnutls_assert(); \ + return ret; \ + } \ + ret = _gnutls_buffer_append_prefix(b, 32, s.tv_nsec); \ + if (ret < 0) { \ + gnutls_assert(); \ + return ret; \ + } \ + } + #define BUFFER_POP(b, x, s) { \ ret = _gnutls_buffer_pop_data(b, x, s); \ if (ret < 0) { \ @@ -273,4 +291,28 @@ int _gnutls_hostname_compare(const char *certname, size_t certnamesize, o = (void *) (intptr_t)(s); \ } +#define BUFFER_POP_TS(b, o) { \ + size_t s; \ + uint64_t v; \ + ret = _gnutls_buffer_pop_prefix32(b, &s, 0); \ + if (ret < 0) { \ + gnutls_assert(); \ + goto error; \ + } \ + v = s; \ + ret = _gnutls_buffer_pop_prefix32(b, &s, 0); \ + if (ret < 0) { \ + gnutls_assert(); \ + goto error; \ + } \ + v = (v << 32) | s; \ + ret = _gnutls_buffer_pop_prefix32(b, &s, 0); \ + if (ret < 0) { \ + gnutls_assert(); \ + goto error; \ + } \ + o.tv_sec = v; \ + o.tv_nsec = s; \ + } + #endif diff --git a/lib/system.c b/lib/system.c index 1a17974d58..1bbbf79c84 100644 --- a/lib/system.c +++ b/lib/system.c @@ -44,6 +44,26 @@ static HMODULE Crypt32_dll; /* System specific function wrappers for certificate stores. */ gnutls_time_func gnutls_time; +gnutls_gettime_func gnutls_gettime; + +/* emulate gnulib's gettime using gettimeofday to avoid linking to + * librt */ +static void _gnutls_gettime(struct timespec *t) +{ +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) + clock_gettime(CLOCK_REALTIME, t); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + t->tv_sec = tv.tv_sec; + t->tv_nsec = tv.tv_usec * 1000; +#endif +} + +void _gnutls_global_set_gettime_function(gnutls_gettime_func gettime_func) +{ + gnutls_gettime = gettime_func; +} int gnutls_system_global_init(void) { @@ -66,6 +86,7 @@ int gnutls_system_global_init(void) Crypt32_dll = crypto; #endif gnutls_time = time; + gnutls_gettime = _gnutls_gettime; return 0; } @@ -75,6 +96,7 @@ void gnutls_system_global_deinit(void) FreeLibrary(Crypt32_dll); #endif gnutls_time = time; + gnutls_gettime = _gnutls_gettime; } diff --git a/lib/system.h b/lib/system.h index 0ae3c63b17..6a948f858d 100644 --- a/lib/system.h +++ b/lib/system.h @@ -77,7 +77,10 @@ ssize_t system_read(gnutls_transport_ptr_t ptr, void *data, # define HAVE_NO_LOCKS #endif +typedef void (*gnutls_gettime_func) (struct timespec *); + extern gnutls_time_func gnutls_time; +extern gnutls_gettime_func gnutls_gettime; static inline void millisleep(unsigned int ms) { @@ -93,26 +96,14 @@ static inline void millisleep(unsigned int ms) #endif } -/* emulate gnulib's gettime using gettimeofday to avoid linking to - * librt */ -inline static void gettime(struct timespec *t) -{ -#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) - clock_gettime(CLOCK_REALTIME, t); -#else - struct timeval tv; - gettimeofday(&tv, NULL); - t->tv_sec = tv.tv_sec; - t->tv_nsec = tv.tv_usec * 1000; -#endif -} - int _gnutls_find_config_path(char *path, size_t max_size); int _gnutls_ucs2_to_utf8(const void *data, size_t size, gnutls_datum_t * output, unsigned bigendian); int _gnutls_utf8_to_ucs2(const void *data, size_t size, gnutls_datum_t * output); +void _gnutls_global_set_gettime_function(gnutls_gettime_func gettime_func); + int gnutls_system_global_init(void); void gnutls_system_global_deinit(void); diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c index 36d5dc5260..ad04a60919 100644 --- a/lib/tls13/session_ticket.c +++ b/lib/tls13/session_ticket.c @@ -34,7 +34,7 @@ #include "db.h" static int -pack_ticket(gnutls_session_t session, tls13_ticket_t *ticket, gnutls_datum_t *packed) +pack_ticket(gnutls_session_t session, tls13_ticket_st *ticket, gnutls_datum_t *packed) { uint8_t *p; gnutls_datum_t state; @@ -85,7 +85,7 @@ pack_ticket(gnutls_session_t session, tls13_ticket_t *ticket, gnutls_datum_t *pa } static int -unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_t *data) +unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st *data) { uint32_t age_add, lifetime; uint8_t resumption_master_secret[MAX_HASH_SIZE]; @@ -174,11 +174,11 @@ unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_t * } static int -generate_session_ticket(gnutls_session_t session, tls13_ticket_t *ticket) +generate_session_ticket(gnutls_session_t session, tls13_ticket_st *ticket) { int ret; gnutls_datum_t packed = { NULL, 0 }; - tls13_ticket_t ticket_data; + tls13_ticket_st ticket_data; time_t now = gnutls_time(0); if (session->internals.resumed != RESUME_FALSE) { @@ -234,7 +234,7 @@ int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigne int ret = 0; mbuffer_st *bufel = NULL; gnutls_buffer_st buf; - tls13_ticket_t ticket; + tls13_ticket_st ticket; unsigned i; /* Client does not send a NewSessionTicket */ @@ -253,7 +253,7 @@ int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigne if (again == 0) { for (i=0;i<nr;i++) { - memset(&ticket, 0, sizeof(tls13_ticket_t)); + memset(&ticket, 0, sizeof(tls13_ticket_st)); bufel = NULL; ret = _gnutls_buffer_init_handshake_mbuffer(&buf); @@ -346,7 +346,7 @@ int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *bu { int ret; uint8_t value; - tls13_ticket_t *ticket = &session->internals.tls13_ticket; + tls13_ticket_st *ticket = &session->internals.tls13_ticket; gnutls_datum_t t; size_t val; @@ -354,7 +354,7 @@ int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *bu return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); _gnutls_free_datum(&ticket->ticket); - memset(ticket, 0, sizeof(tls13_ticket_t)); + memset(ticket, 0, sizeof(tls13_ticket_st)); _gnutls_handshake_log("HSK[%p]: parsing session ticket message\n", session); @@ -395,8 +395,8 @@ int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *bu if (ret < 0) return gnutls_assert_val(ret); - /* Set the ticket timestamp */ - ticket->timestamp = gnutls_time(0); + /* Record the ticket arrival time */ + gnutls_gettime(&ticket->arrival_time); return 0; } @@ -407,7 +407,7 @@ int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *bu */ int _gnutls13_unpack_session_ticket(gnutls_session_t session, gnutls_datum_t *data, - tls13_ticket_t *ticket_data) + tls13_ticket_st *ticket_data) { int ret; gnutls_datum_t decrypted = { NULL, 0 }; diff --git a/lib/tls13/session_ticket.h b/lib/tls13/session_ticket.h index d2f637c209..feab3e2379 100644 --- a/lib/tls13/session_ticket.h +++ b/lib/tls13/session_ticket.h @@ -27,17 +27,17 @@ int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigne int _gnutls13_unpack_session_ticket(gnutls_session_t session, gnutls_datum_t *data, - tls13_ticket_t *ticket_data); + tls13_ticket_st *ticket_data); inline static -void tls13_ticket_deinit(tls13_ticket_t *ticket) +void tls13_ticket_deinit(tls13_ticket_st *ticket) { if (ticket) { zeroize_temp_key(&ticket->resumption_master_secret, sizeof(ticket->resumption_master_secret)); _gnutls_free_datum(&ticket->ticket); - memset(ticket, 0, sizeof(tls13_ticket_t)); + memset(ticket, 0, sizeof(tls13_ticket_st)); } } diff --git a/tests/virt-time.h b/tests/virt-time.h index 02c8cdb147..0dd35df299 100644 --- a/tests/virt-time.h +++ b/tests/virt-time.h @@ -29,19 +29,28 @@ #include <time.h> #include <gnutls/gnutls.h> +/* copied from ../lib/system.h so not to include that header from + * every test program */ +typedef void (*gnutls_gettime_func) (struct timespec *); +extern void _gnutls_global_set_gettime_function(gnutls_gettime_func gettime_func); + /* virtualize time in a test. This freezes the time in the test, except for * the advances due to calls to virt_sleep_sec(). This makes the test - * independent of the test system load, and avoids any long delays. - * - * This only affects the parts of the library that utilize gnutls_time(), - * not the higher precision gettime */ -static time_t _now = 0; + * independent of the test system load, and avoids any long delays. */ +static time_t _now; +static struct timespec _now_ts; -#define virt_sec_sleep(s) _now += s +#define virt_sec_sleep(s) { \ + _now += s; \ + _now_ts.tv_sec += s; \ + } #define virt_time_init() { \ _now = time(0); \ gnutls_global_set_time_function(mytime); \ + _now_ts.tv_sec = _now; \ + _now_ts.tv_nsec = 0; \ + _gnutls_global_set_gettime_function(mygettime); \ } @@ -53,4 +62,10 @@ static time_t mytime(time_t * t) return _now; } +static void mygettime(struct timespec * t) +{ + if (t) + *t = _now_ts; +} + #endif |