summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-06-26 15:12:41 +0000
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-06-26 15:12:41 +0000
commite1eaba41da82b2588b48bebc6ec5cb13cc46f717 (patch)
treefc65332ce1bf611b72f8b611e1183ea774e533b4
parent7d8fd3aee4d71e1cd79ab5c980d137b363283a33 (diff)
parent4d1967a3c48c4e54fda4e3cf996160b466188f6c (diff)
downloadgnutls-e1eaba41da82b2588b48bebc6ec5cb13cc46f717.tar.gz
Merge branch 'hmac-copy' into 'master'
gnutls_hmac_copy() API Closes #787 See merge request gnutls/gnutls!1035
-rw-r--r--NEWS6
-rw-r--r--devel/libgnutls-latest-x86_64.abi2
-rw-r--r--devel/symbols.last2
-rw-r--r--doc/Makefile.am4
-rw-r--r--doc/manpages/Makefile.am2
-rw-r--r--lib/accelerated/aarch64/hmac-sha-aarch64.c21
-rw-r--r--lib/accelerated/aarch64/sha-aarch64.c20
-rw-r--r--lib/accelerated/x86/hmac-padlock.c20
-rw-r--r--lib/accelerated/x86/hmac-x86-ssse3.c20
-rw-r--r--lib/accelerated/x86/sha-padlock.c20
-rw-r--r--lib/accelerated/x86/sha-x86-ssse3.c20
-rw-r--r--lib/crypto-api.c64
-rw-r--r--lib/crypto-backend.h2
-rw-r--r--lib/crypto-selftests.c51
-rw-r--r--lib/hash_int.c32
-rw-r--r--lib/hash_int.h7
-rw-r--r--lib/includes/gnutls/crypto.h4
-rw-r--r--lib/libgnutls.map2
-rw-r--r--lib/nettle/mac.c34
-rw-r--r--tests/Makefile.am1
-rw-r--r--tests/cert-tests/Makefile.am1
-rw-r--r--tests/slow/Makefile.am1
-rwxr-xr-xtests/slow/override-ciphers5
-rw-r--r--tests/suite/Makefile.am1
-rw-r--r--tests/windows/Makefile.am1
25 files changed, 343 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 32236eb375..cf5b127760 100644
--- a/NEWS
+++ b/NEWS
@@ -34,12 +34,18 @@ See the end for copying conditions.
the GNUTLS_SYSTEM_PRIORITY_FAIL_ON_INVALID environment parameter is
set to 1.
+** libgnutls: add gnutls_hash_copy/gnutls_hmac_copy functions that will create a copy
+ of digest or MAC context. Copying contexts for externally-registered digest and MAC
+ contexts is unupported.
+
** API and ABI modifications:
gnutls_get_system_config_file: Added
gnutls_crypto_register_cipher: Deprecated
gnutls_crypto_register_aead_cipher: Deprecated
gnutls_crypto_register_digest: Deprecated
gnutls_crypto_register_mac: Deprecated
+gnutls_hash_copy: Added
+gnutls_hmac_copy: Added
* Version 3.6.8 (released 2019-05-28)
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index 11c4174508..3fa7f45238 100644
--- a/devel/libgnutls-latest-x86_64.abi
+++ b/devel/libgnutls-latest-x86_64.abi
@@ -292,6 +292,7 @@
<elf-symbol name='gnutls_handshake_set_random' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_handshake_set_timeout' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hash' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='gnutls_hash_copy' version='GNUTLS_3_6_9' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hash_deinit' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hash_fast' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hash_get_len' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@@ -309,6 +310,7 @@
<elf-symbol name='gnutls_hex_encode2' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hex_encode' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hmac' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
+ <elf-symbol name='gnutls_hmac_copy' version='GNUTLS_3_6_9' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hmac_deinit' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hmac_fast' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='gnutls_hmac_get_len' version='GNUTLS_3_4' is-default-version='yes' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
diff --git a/devel/symbols.last b/devel/symbols.last
index c2287e0f53..e5ff89d5e4 100644
--- a/devel/symbols.last
+++ b/devel/symbols.last
@@ -262,6 +262,7 @@ gnutls_handshake_set_private_extensions@GNUTLS_3_4
gnutls_handshake_set_random@GNUTLS_3_4
gnutls_handshake_set_timeout@GNUTLS_3_4
gnutls_hash@GNUTLS_3_4
+gnutls_hash_copy@GNUTLS_3_6_9
gnutls_hash_deinit@GNUTLS_3_4
gnutls_hash_fast@GNUTLS_3_4
gnutls_hash_get_len@GNUTLS_3_4
@@ -279,6 +280,7 @@ gnutls_hex_decode@GNUTLS_3_4
gnutls_hex_encode2@GNUTLS_3_4
gnutls_hex_encode@GNUTLS_3_4
gnutls_hmac@GNUTLS_3_4
+gnutls_hmac_copy@GNUTLS_3_6_9
gnutls_hmac_deinit@GNUTLS_3_4
gnutls_hmac_fast@GNUTLS_3_4
gnutls_hmac_get_len@GNUTLS_3_4
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 3ab2ad0049..6d21d74820 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1079,6 +1079,8 @@ FUNCS += functions/gnutls_handshake_set_timeout
FUNCS += functions/gnutls_handshake_set_timeout.short
FUNCS += functions/gnutls_hash
FUNCS += functions/gnutls_hash.short
+FUNCS += functions/gnutls_hash_copy
+FUNCS += functions/gnutls_hash_copy.short
FUNCS += functions/gnutls_hash_deinit
FUNCS += functions/gnutls_hash_deinit.short
FUNCS += functions/gnutls_hash_fast
@@ -1113,6 +1115,8 @@ FUNCS += functions/gnutls_hex_encode2
FUNCS += functions/gnutls_hex_encode2.short
FUNCS += functions/gnutls_hmac
FUNCS += functions/gnutls_hmac.short
+FUNCS += functions/gnutls_hmac_copy
+FUNCS += functions/gnutls_hmac_copy.short
FUNCS += functions/gnutls_hmac_deinit
FUNCS += functions/gnutls_hmac_deinit.short
FUNCS += functions/gnutls_hmac_fast
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
index 063ebcb659..d06c180138 100644
--- a/doc/manpages/Makefile.am
+++ b/doc/manpages/Makefile.am
@@ -341,6 +341,7 @@ APIMANS += gnutls_handshake_set_private_extensions.3
APIMANS += gnutls_handshake_set_random.3
APIMANS += gnutls_handshake_set_timeout.3
APIMANS += gnutls_hash.3
+APIMANS += gnutls_hash_copy.3
APIMANS += gnutls_hash_deinit.3
APIMANS += gnutls_hash_fast.3
APIMANS += gnutls_hash_get_len.3
@@ -358,6 +359,7 @@ APIMANS += gnutls_hex_decode2.3
APIMANS += gnutls_hex_encode.3
APIMANS += gnutls_hex_encode2.3
APIMANS += gnutls_hmac.3
+APIMANS += gnutls_hmac_copy.3
APIMANS += gnutls_hmac_deinit.3
APIMANS += gnutls_hmac_fast.3
APIMANS += gnutls_hmac_get_len.3
diff --git a/lib/accelerated/aarch64/hmac-sha-aarch64.c b/lib/accelerated/aarch64/hmac-sha-aarch64.c
index d9081060c6..47d6c516ce 100644
--- a/lib/accelerated/aarch64/hmac-sha-aarch64.c
+++ b/lib/accelerated/aarch64/hmac-sha-aarch64.c
@@ -218,6 +218,26 @@ static int wrap_aarch64_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
return 0;
}
+static void *
+wrap_aarch64_hmac_copy(const void *_ctx)
+{
+ struct aarch64_hmac_ctx *new_ctx;
+ const struct aarch64_hmac_ctx *ctx=_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_malloc(sizeof(struct aarch64_hmac_ctx));
+ if (new_ctx == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ memcpy(new_ctx, ctx, sizeof(*new_ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
+
static int
wrap_aarch64_hmac_setkey(void *_ctx, const void *key, size_t keylen)
{
@@ -287,6 +307,7 @@ const gnutls_crypto_mac_st _gnutls_hmac_sha_aarch64 = {
.setnonce = NULL,
.hash = wrap_aarch64_hmac_update,
.output = wrap_aarch64_hmac_output,
+ .copy = wrap_aarch64_hmac_copy,
.deinit = wrap_aarch64_hmac_deinit,
.fast = wrap_aarch64_hmac_fast,
};
diff --git a/lib/accelerated/aarch64/sha-aarch64.c b/lib/accelerated/aarch64/sha-aarch64.c
index 9cdf12ca3a..e4871293e5 100644
--- a/lib/accelerated/aarch64/sha-aarch64.c
+++ b/lib/accelerated/aarch64/sha-aarch64.c
@@ -305,6 +305,25 @@ static int wrap_aarch64_hash_init(gnutls_digest_algorithm_t algo, void **_ctx)
return 0;
}
+static void *
+wrap_aarch64_hash_copy(const void *_ctx)
+{
+ struct aarch64_hash_ctx *new_ctx;
+ const struct aarch64_hash_ctx *ctx=_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_malloc(sizeof(struct aarch64_hash_ctx));
+ if (new_ctx == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ memcpy(new_ctx, ctx, sizeof(*new_ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_aarch64_hash_output(void *src_ctx, void *digest, size_t digestsize)
{
@@ -352,6 +371,7 @@ const gnutls_crypto_digest_st _gnutls_sha_aarch64 = {
.init = wrap_aarch64_hash_init,
.hash = wrap_aarch64_hash_update,
.output = wrap_aarch64_hash_output,
+ .copy = wrap_aarch64_hash_copy,
.deinit = wrap_aarch64_hash_deinit,
.fast = wrap_aarch64_hash_fast,
};
diff --git a/lib/accelerated/x86/hmac-padlock.c b/lib/accelerated/x86/hmac-padlock.c
index 5e1f918fa7..be6c55bc33 100644
--- a/lib/accelerated/x86/hmac-padlock.c
+++ b/lib/accelerated/x86/hmac-padlock.c
@@ -223,6 +223,25 @@ static int wrap_padlock_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
return 0;
}
+static void *
+wrap_padlock_hmac_copy(const void *_ctx)
+{
+ struct padlock_hmac_ctx *new_ctx;
+ const struct padlock_hmac_ctx *ctx=_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_malloc(sizeof(struct padlock_hmac_ctx));
+ if (new_ctx == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ memcpy(new_ctx, ctx, sizeof(*new_ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_padlock_hmac_setkey(void *_ctx, const void *key, size_t keylen)
{
@@ -344,6 +363,7 @@ const gnutls_crypto_mac_st _gnutls_hmac_sha_padlock_nano = {
.setnonce = NULL,
.hash = wrap_padlock_hmac_update,
.output = wrap_padlock_hmac_output,
+ .copy = wrap_padlock_hmac_copy,
.deinit = wrap_padlock_hmac_deinit,
.fast = wrap_padlock_hmac_fast,
};
diff --git a/lib/accelerated/x86/hmac-x86-ssse3.c b/lib/accelerated/x86/hmac-x86-ssse3.c
index 62adf0c4ef..5a4677b405 100644
--- a/lib/accelerated/x86/hmac-x86-ssse3.c
+++ b/lib/accelerated/x86/hmac-x86-ssse3.c
@@ -224,6 +224,25 @@ static int wrap_x86_hmac_init(gnutls_mac_algorithm_t algo, void **_ctx)
return 0;
}
+static void *
+wrap_x86_hmac_copy(const void *_ctx)
+{
+ struct x86_hmac_ctx *new_ctx;
+ const struct x86_hmac_ctx *ctx=_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_malloc(sizeof(struct x86_hmac_ctx));
+ if (new_ctx == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ memcpy(new_ctx, ctx, sizeof(*new_ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_x86_hmac_setkey(void *_ctx, const void *key, size_t keylen)
{
@@ -293,6 +312,7 @@ const gnutls_crypto_mac_st _gnutls_hmac_sha_x86_ssse3 = {
.setnonce = NULL,
.hash = wrap_x86_hmac_update,
.output = wrap_x86_hmac_output,
+ .copy = wrap_x86_hmac_copy,
.deinit = wrap_x86_hmac_deinit,
.fast = wrap_x86_hmac_fast,
};
diff --git a/lib/accelerated/x86/sha-padlock.c b/lib/accelerated/x86/sha-padlock.c
index 16a63d80cb..e878ebe310 100644
--- a/lib/accelerated/x86/sha-padlock.c
+++ b/lib/accelerated/x86/sha-padlock.c
@@ -292,6 +292,25 @@ wrap_padlock_hash_init(gnutls_digest_algorithm_t algo, void **_ctx)
return 0;
}
+static void *
+wrap_padlock_hash_copy(const void *_ctx)
+{
+ struct padlock_hash_ctx *new_ctx;
+ const struct padlock_hash_ctx *ctx=_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_malloc(sizeof(struct padlock_hash_ctx));
+ if (new_ctx == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ memcpy(new_ctx, ctx, sizeof(*new_ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_padlock_hash_output(void *src_ctx, void *digest, size_t digestsize)
{
@@ -367,6 +386,7 @@ const gnutls_crypto_digest_st _gnutls_sha_padlock_nano = {
.init = wrap_padlock_hash_init,
.hash = wrap_padlock_hash_update,
.output = wrap_padlock_hash_output,
+ .copy = wrap_padlock_hash_copy,
.deinit = wrap_padlock_hash_deinit,
.fast = wrap_padlock_hash_fast,
};
diff --git a/lib/accelerated/x86/sha-x86-ssse3.c b/lib/accelerated/x86/sha-x86-ssse3.c
index 5dc9da6349..b6393488cf 100644
--- a/lib/accelerated/x86/sha-x86-ssse3.c
+++ b/lib/accelerated/x86/sha-x86-ssse3.c
@@ -311,6 +311,25 @@ static int wrap_x86_hash_init(gnutls_digest_algorithm_t algo, void **_ctx)
return 0;
}
+static void *
+wrap_x86_hash_copy(const void *_ctx)
+{
+ struct x86_hash_ctx *new_ctx;
+ const struct x86_hash_ctx *ctx=_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_malloc(sizeof(struct x86_hash_ctx));
+ if (new_ctx == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ memcpy(new_ctx, ctx, sizeof(*new_ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_x86_hash_output(void *src_ctx, void *digest, size_t digestsize)
{
@@ -360,6 +379,7 @@ const gnutls_crypto_digest_st _gnutls_sha_x86_ssse3 = {
.init = wrap_x86_hash_init,
.hash = wrap_x86_hash_update,
.output = wrap_x86_hash_output,
+ .copy = wrap_x86_hash_copy,
.deinit = wrap_x86_hash_deinit,
.fast = wrap_x86_hash_fast,
};
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index 0b6be4eed2..0cd3d21723 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -482,6 +482,38 @@ gnutls_hmac_fast(gnutls_mac_algorithm_t algorithm,
digest);
}
+/**
+ * gnutls_hmac_copy:
+ * @handle: is a #gnutls_hmac_hd_t type
+ *
+ * This function will create a copy of MAC context, containing all its current
+ * state. Copying contexts for MACs registered using
+ * gnutls_crypto_register_mac() is not supported and will always result in an
+ * error.
+ *
+ * Returns: new MAC context or NULL in case of an error.
+ *
+ * Since: 3.6.9
+ */
+gnutls_hmac_hd_t gnutls_hmac_copy(gnutls_hmac_hd_t handle)
+{
+ gnutls_hmac_hd_t dig;
+
+ dig = gnutls_malloc(sizeof(mac_hd_st));
+ if (dig == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ if (_gnutls_mac_copy((const mac_hd_st *) handle, (mac_hd_st *)dig) != GNUTLS_E_SUCCESS) {
+ gnutls_assert();
+ gnutls_free(dig);
+ return NULL;
+ }
+
+ return dig;
+}
+
/* HASH */
/**
@@ -605,6 +637,38 @@ gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
}
/**
+ * gnutls_hash_copy:
+ * @handle: is a #gnutls_hash_hd_t type
+ *
+ * This function will create a copy of Message Digest context, containing all
+ * its current state. Copying contexts for Message Digests registered using
+ * gnutls_crypto_register_digest() is not supported and will always result in
+ * an error.
+ *
+ * Returns: new Message Digest context or NULL in case of an error.
+ *
+ * Since: 3.6.9
+ */
+gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle)
+{
+ gnutls_hash_hd_t dig;
+
+ dig = gnutls_malloc(sizeof(digest_hd_st));
+ if (dig == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ if (_gnutls_hash_copy((const digest_hd_st *) handle, (digest_hd_st *)dig) != GNUTLS_E_SUCCESS) {
+ gnutls_assert();
+ gnutls_free(dig);
+ return NULL;
+ }
+
+ return dig;
+}
+
+/**
* gnutls_key_generate:
* @key: is a pointer to a #gnutls_datum_t which will contain a newly
* created key
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
index f2fbba947d..43124abafb 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -55,6 +55,7 @@ typedef struct {
gnutls_mac_output_func output;
gnutls_mac_deinit_func deinit;
gnutls_mac_fast_func fast;
+ gnutls_mac_copy_func copy;
/* Not needed for registered on run-time. Only included
* should define it. */
@@ -67,6 +68,7 @@ typedef struct {
gnutls_digest_output_func output;
gnutls_digest_deinit_func deinit;
gnutls_digest_fast_func fast;
+ gnutls_digest_copy_func copy;
/* Not needed for registered on run-time. Only included
* should define it. */
diff --git a/lib/crypto-selftests.c b/lib/crypto-selftests.c
index 02e92849e9..eddf935680 100644
--- a/lib/crypto-selftests.c
+++ b/lib/crypto-selftests.c
@@ -1355,6 +1355,7 @@ static int test_digest(gnutls_digest_algorithm_t dig,
int ret;
size_t data_size;
gnutls_hash_hd_t hd;
+ gnutls_hash_hd_t copy;
if (_gnutls_digest_exists(dig) == 0)
return 0;
@@ -1371,6 +1372,12 @@ static int test_digest(gnutls_digest_algorithm_t dig,
if (ret < 0)
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ copy = gnutls_hash_copy(hd);
+ /* Returning NULL is not an error here for the time being, but
+ * it might become one later */
+ if (!copy && secure_getenv("GNUTLS_TEST_SUITE_RUN"))
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
ret = gnutls_hash(hd,
&vectors[i].plaintext[1],
vectors[i].plaintext_size - 1);
@@ -1390,6 +1397,24 @@ static int test_digest(gnutls_digest_algorithm_t dig,
gnutls_digest_get_name(dig), i);
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
}
+
+ if (copy != NULL) {
+ ret = gnutls_hash(copy,
+ &vectors[i].plaintext[1],
+ vectors[i].plaintext_size - 1);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
+ memset(data, 0xaa, data_size);
+ gnutls_hash_deinit(copy, data);
+
+ if (memcmp(data, vectors[i].output,
+ vectors[i].output_size) != 0) {
+ _gnutls_debug_log("%s copy test vector %d failed!\n",
+ gnutls_digest_get_name(dig), i);
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+ }
}
_gnutls_debug_log("%s self check succeeded\n",
@@ -1544,6 +1569,7 @@ static int test_mac(gnutls_mac_algorithm_t mac,
int ret;
size_t data_size;
gnutls_hmac_hd_t hd;
+ gnutls_hmac_hd_t copy;
for (i = 0; i < vectors_size; i++) {
ret = gnutls_hmac_init(&hd,
@@ -1560,6 +1586,12 @@ static int test_mac(gnutls_mac_algorithm_t mac,
if (ret < 0)
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ copy = gnutls_hmac_copy(hd);
+ /* Returning NULL is not an error here for the time being, but
+ * it might become one later */
+ if (!copy && secure_getenv("GNUTLS_TEST_SUITE_RUN"))
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
ret = gnutls_hmac(hd,
&vectors[i].plaintext[1],
vectors[i].plaintext_size - 1);
@@ -1582,6 +1614,25 @@ static int test_mac(gnutls_mac_algorithm_t mac,
return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
}
+
+ if (copy != NULL) {
+ ret = gnutls_hmac(copy,
+ &vectors[i].plaintext[1],
+ vectors[i].plaintext_size - 1);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+
+ memset(data, 0xaa, data_size);
+ gnutls_hmac_deinit(copy, data);
+
+ if (memcmp(data, vectors[i].output,
+ vectors[i].output_size) != 0) {
+ _gnutls_debug_log
+ ("MAC-%s copy test vector %d failed!\n",
+ gnutls_mac_get_name(mac), i);
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+ }
+ }
}
_gnutls_debug_log
diff --git a/lib/hash_int.c b/lib/hash_int.c
index fbc56b4333..d326960e80 100644
--- a/lib/hash_int.c
+++ b/lib/hash_int.c
@@ -54,6 +54,7 @@ int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
dig->hash = cc->hash;
dig->output = cc->output;
dig->deinit = cc->deinit;
+ dig->copy = cc->copy;
return 0;
}
@@ -67,6 +68,7 @@ int _gnutls_hash_init(digest_hd_st * dig, const mac_entry_st * e)
dig->hash = _gnutls_digest_ops.hash;
dig->output = _gnutls_digest_ops.output;
dig->deinit = _gnutls_digest_ops.deinit;
+ dig->copy = _gnutls_digest_ops.copy;
return 0;
}
@@ -88,6 +90,20 @@ int _gnutls_digest_exists(gnutls_digest_algorithm_t algo)
return _gnutls_digest_ops.exists(algo);
}
+int _gnutls_hash_copy(const digest_hd_st * handle, digest_hd_st * dst)
+{
+ if (handle->copy == NULL)
+ return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
+
+ *dst = *handle; /* copy data */
+ dst->handle = handle->copy(handle->handle);
+
+ if (dst->handle == NULL)
+ return GNUTLS_E_HASH_FAILED;
+
+ return 0;
+}
+
void _gnutls_hash_deinit(digest_hd_st * handle, void *digest)
{
if (handle->handle == NULL) {
@@ -225,6 +241,7 @@ _gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
mac->setnonce = cc->setnonce;
mac->output = cc->output;
mac->deinit = cc->deinit;
+ mac->copy = cc->copy;
return 0;
}
@@ -239,6 +256,7 @@ _gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
mac->setnonce = _gnutls_mac_ops.setnonce;
mac->output = _gnutls_mac_ops.output;
mac->deinit = _gnutls_mac_ops.deinit;
+ mac->copy = _gnutls_mac_ops.copy;
if (_gnutls_mac_ops.setkey(mac->handle, key, keylen) < 0) {
gnutls_assert();
@@ -249,6 +267,20 @@ _gnutls_mac_init(mac_hd_st * mac, const mac_entry_st * e,
return 0;
}
+int _gnutls_mac_copy(const mac_hd_st * handle, mac_hd_st * dst)
+{
+ if (handle->copy == NULL)
+ return gnutls_assert_val(GNUTLS_E_HASH_FAILED);
+
+ *dst = *handle; /* copy data */
+ dst->handle = handle->copy(handle->handle);
+
+ if (dst->handle == NULL)
+ return GNUTLS_E_HASH_FAILED;
+
+ return 0;
+}
+
void _gnutls_mac_deinit(mac_hd_st * handle, void *digest)
{
if (handle->handle == NULL) {
diff --git a/lib/hash_int.h b/lib/hash_int.h
index 52fb2b01f0..9f6059da33 100644
--- a/lib/hash_int.h
+++ b/lib/hash_int.h
@@ -41,12 +41,14 @@ typedef int (*nonce_func) (void *handle, const void *text, size_t size);
typedef int (*output_func) (void *src_ctx, void *digest,
size_t digestsize);
typedef void (*hash_deinit_func) (void *handle);
+typedef void *(*copy_func) (const void *handle);
typedef struct {
const mac_entry_st *e;
hash_func hash;
output_func output;
hash_deinit_func deinit;
+ copy_func copy;
const void *key; /* esoteric use by SSL3 MAC functions */
int keysize;
@@ -62,6 +64,7 @@ typedef struct {
nonce_func setnonce;
output_func output;
hash_deinit_func deinit;
+ copy_func copy;
void *handle;
} mac_hd_st;
@@ -73,6 +76,8 @@ int _gnutls_mac_exists(gnutls_mac_algorithm_t algorithm);
int _gnutls_mac_init(mac_hd_st *, const mac_entry_st * e,
const void *key, int keylen);
+int _gnutls_mac_copy(const mac_hd_st * handle, mac_hd_st * dst);
+
int _gnutls_mac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
int keylen, const void *text, size_t textlen,
void *digest);
@@ -122,6 +127,8 @@ _gnutls_hash(digest_hd_st * handle, const void *text, size_t textlen)
void _gnutls_hash_deinit(digest_hd_st * handle, void *digest);
+int _gnutls_hash_copy(const digest_hd_st * handle, digest_hd_st * dst);
+
int
_gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
const void *text, size_t textlen, void *digest);
diff --git a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
index 93a157857c..d2b8cae8f4 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -112,6 +112,7 @@ unsigned gnutls_hmac_get_len(gnutls_mac_algorithm_t algorithm) __GNUTLS_CONST__;
int gnutls_hmac_fast(gnutls_mac_algorithm_t algorithm,
const void *key, size_t keylen,
const void *text, size_t textlen, void *digest);
+gnutls_hmac_hd_t gnutls_hmac_copy(gnutls_hmac_hd_t handle);
int gnutls_hash_init(gnutls_hash_hd_t * dig,
gnutls_digest_algorithm_t algorithm);
@@ -121,6 +122,7 @@ void gnutls_hash_deinit(gnutls_hash_hd_t handle, void *digest);
unsigned gnutls_hash_get_len(gnutls_digest_algorithm_t algorithm) __GNUTLS_CONST__;
int gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
const void *text, size_t textlen, void *digest);
+gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle);
/* register ciphers */
@@ -208,6 +210,7 @@ typedef void (*gnutls_mac_deinit_func) (void *ctx);
typedef int (*gnutls_mac_fast_func) (gnutls_mac_algorithm_t, const void *nonce,
size_t nonce_size, const void *key, size_t keysize,
const void *text, size_t textsize, void *digest);
+typedef void *(*gnutls_mac_copy_func) (const void *ctx);
int
gnutls_crypto_register_mac(gnutls_mac_algorithm_t mac,
@@ -227,6 +230,7 @@ typedef int (*gnutls_digest_output_func) (void *src_ctx, void *digest, size_t di
typedef void (*gnutls_digest_deinit_func) (void *ctx);
typedef int (*gnutls_digest_fast_func) (gnutls_digest_algorithm_t,
const void *text, size_t textsize, void *digest);
+typedef void *(*gnutls_digest_copy_func) (const void *ctx);
int
gnutls_crypto_register_digest(gnutls_digest_algorithm_t digest,
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 338cae2b1b..0f31f4aef4 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1290,6 +1290,8 @@ GNUTLS_3_6_9
{
global:
gnutls_get_system_config_file;
+ gnutls_hmac_copy;
+ gnutls_hash_copy;
} GNUTLS_3_6_8;
GNUTLS_FIPS140_3_4 {
diff --git a/lib/nettle/mac.c b/lib/nettle/mac.c
index 249ff2e2d7..8107f7cea4 100644
--- a/lib/nettle/mac.c
+++ b/lib/nettle/mac.c
@@ -324,6 +324,22 @@ static int wrap_nettle_mac_init(gnutls_mac_algorithm_t algo, void **_ctx)
return 0;
}
+static void *wrap_nettle_mac_copy(const void *_ctx)
+{
+ const struct nettle_mac_ctx *ctx = _ctx;
+ struct nettle_mac_ctx *new_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_calloc(1, sizeof(struct nettle_mac_ctx));
+ if (new_ctx == NULL)
+ return NULL;
+
+ memcpy(new_ctx, ctx, sizeof(*ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_nettle_mac_set_key(void *_ctx, const void *key, size_t keylen)
{
@@ -616,6 +632,22 @@ wrap_nettle_hash_init(gnutls_digest_algorithm_t algo, void **_ctx)
return 0;
}
+static void *wrap_nettle_hash_copy(const void *_ctx)
+{
+ const struct nettle_hash_ctx *ctx = _ctx;
+ struct nettle_hash_ctx *new_ctx;
+ ptrdiff_t off = (uint8_t *)ctx->ctx_ptr - (uint8_t *)(&ctx->ctx);
+
+ new_ctx = gnutls_calloc(1, sizeof(struct nettle_hash_ctx));
+ if (new_ctx == NULL)
+ return NULL;
+
+ memcpy(new_ctx, ctx, sizeof(*ctx));
+ new_ctx->ctx_ptr = (uint8_t *)&new_ctx->ctx + off;
+
+ return new_ctx;
+}
+
static int
wrap_nettle_hash_output(void *src_ctx, void *digest, size_t digestsize)
{
@@ -641,6 +673,7 @@ gnutls_crypto_mac_st _gnutls_mac_ops = {
.deinit = wrap_nettle_mac_deinit,
.fast = wrap_nettle_mac_fast,
.exists = wrap_nettle_mac_exists,
+ .copy = wrap_nettle_mac_copy,
};
gnutls_crypto_digest_st _gnutls_digest_ops = {
@@ -650,4 +683,5 @@ gnutls_crypto_digest_st _gnutls_digest_ops = {
.deinit = wrap_nettle_hash_deinit,
.fast = wrap_nettle_hash_fast,
.exists = wrap_nettle_hash_exists,
+ .copy = wrap_nettle_hash_copy,
};
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 62b2db75e5..98623a20c8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -571,6 +571,7 @@ TESTS_ENVIRONMENT += \
PSK_FILE=$(srcdir)/psk.passwd \
OPENSSL_ia32cap=0x00000000 \
EXEEXT=$(EXEEXT) \
+ GNUTLS_TEST_SUITE_RUN=1 \
builddir="$(builddir)" \
top_builddir="$(top_builddir)" \
libdir="$(libdir)" \
diff --git a/tests/cert-tests/Makefile.am b/tests/cert-tests/Makefile.am
index 06bdf42950..c34b69c40a 100644
--- a/tests/cert-tests/Makefile.am
+++ b/tests/cert-tests/Makefile.am
@@ -146,6 +146,7 @@ TESTS_ENVIRONMENT = EXEEXT=$(EXEEXT) \
top_builddir="$(top_builddir)" \
ac_cv_sizeof_time_t="$(ac_cv_sizeof_time_t)" \
ASAN_OPTIONS="detect_leaks=0:exitcode=6" \
+ GNUTLS_TEST_SUITE_RUN=1 \
srcdir="$(srcdir)"
if ENABLE_FIPS140
diff --git a/tests/slow/Makefile.am b/tests/slow/Makefile.am
index 7e8e4650ca..b4c43c6aa3 100644
--- a/tests/slow/Makefile.am
+++ b/tests/slow/Makefile.am
@@ -65,6 +65,7 @@ EXTRA_DIST = README gnutls-asan.supp
TESTS_ENVIRONMENT = EXEEXT=$(EXEEXT) \
LC_ALL="C" \
LSAN_OPTIONS=suppressions=gnutls-asan.supp \
+ GNUTLS_TEST_SUITE_RUN=1 \
OPENSSL_ia32cap=0x00000000 \
top_builddir="$(top_builddir)" \
srcdir="$(srcdir)"
diff --git a/tests/slow/override-ciphers b/tests/slow/override-ciphers
index 2a87b7655f..3c00e5be3e 100755
--- a/tests/slow/override-ciphers
+++ b/tests/slow/override-ciphers
@@ -26,6 +26,11 @@ if ! test -z "${VALGRIND}"; then
fi
PROG=./cipher-override${EXEEXT}
+# we are explicitly unsetting this variable, because we want
+# the "production" checks to be triggered, not the ones in the
+# test suite.
+
+unset GNUTLS_TEST_SUITE_RUN
GNUTLS_NO_EXPLICIT_INIT=1 ${VALGRIND} ${PROG}
ret=$?
if test $ret != 0; then
diff --git a/tests/suite/Makefile.am b/tests/suite/Makefile.am
index bd3a56cc35..b4da01a375 100644
--- a/tests/suite/Makefile.am
+++ b/tests/suite/Makefile.am
@@ -102,6 +102,7 @@ TESTS_ENVIRONMENT = EXEEXT=$(EXEEXT) \
top_builddir="$(top_builddir)" \
srcdir="$(srcdir)" \
ASAN_OPTIONS="detect_leaks=0" \
+ GNUTLS_TEST_SUITE_RUN=1 \
OPENSSL_ia32cap=0x00000000
if ENABLE_NON_SUITEB_CURVES
diff --git a/tests/windows/Makefile.am b/tests/windows/Makefile.am
index 86de084bb7..5a81043772 100644
--- a/tests/windows/Makefile.am
+++ b/tests/windows/Makefile.am
@@ -69,6 +69,7 @@ TESTS = $(ctests) $(dist_check_SCRIPTS)
TESTS_ENVIRONMENT = \
WINEDLLOVERRIDES="crypt32=n,ncrypt=n" \
LC_ALL="C" \
+ GNUTLS_TEST_SUITE_RUN=1 \
EXEEXT=$(EXEEXT) \
top_builddir="$(top_builddir)" \
srcdir="$(srcdir)"