summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS13
-rw-r--r--configure.ac12
-rw-r--r--lib/algorithms/ciphers.c21
-rw-r--r--lib/algorithms/mac.c8
-rw-r--r--lib/buffers.c8
-rw-r--r--lib/crypto-selftests-pk.c90
-rw-r--r--lib/crypto-selftests.c280
-rw-r--r--lib/dtls.c8
-rw-r--r--lib/dtls.h2
-rw-r--r--lib/ext/heartbeat.c8
-rw-r--r--lib/ext/pre_shared_key.c27
-rw-r--r--lib/fips.h5
-rw-r--r--lib/gnutls_int.h20
-rw-r--r--lib/handshake.c2
-rw-r--r--lib/handshake.h2
-rw-r--r--lib/includes/gnutls/gnutls.h.in10
-rw-r--r--lib/libgnutls.map2
-rw-r--r--lib/nettle/Makefile.am3
-rw-r--r--lib/nettle/backport/cfb8.c117
-rw-r--r--lib/nettle/backport/cfb8.h96
-rw-r--r--lib/nettle/backport/cmac.c213
-rw-r--r--lib/nettle/backport/cmac.h140
-rw-r--r--lib/nettle/cipher.c69
-rw-r--r--lib/nettle/mac.c37
-rw-r--r--lib/nettle/rnd.c2
-rw-r--r--lib/session_pack.c12
-rw-r--r--lib/str.h42
-rw-r--r--lib/system.c22
-rw-r--r--lib/system.h19
-rw-r--r--lib/tls13/session_ticket.c22
-rw-r--r--lib/tls13/session_ticket.h6
-rw-r--r--tests/virt-time.h27
32 files changed, 1266 insertions, 79 deletions
diff --git a/NEWS b/NEWS
index 4f2cc29e4e..4f393e6c01 100644
--- a/NEWS
+++ b/NEWS
@@ -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:
diff --git a/lib/str.h b/lib/str.h
index da472eb4f7..c8be6c9913 100644
--- a/lib/str.h
+++ b/lib/str.h
@@ -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