summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-06-26 11:00:39 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2019-06-26 11:01:19 +0300
commitc034cf9f332de9f6ccb878e1b0f0355049489827 (patch)
treedc4a8295710ac0ac9f2593cfafe8a54f9f8994ec
parent6b41d6ce9f18eac9673279db336f8c84bc839cac (diff)
downloadgnutls-c034cf9f332de9f6ccb878e1b0f0355049489827.tar.gz
lib: add support for gnutls_hash_copy()
Add gnutls_hash_copy() function for copying message digest context. Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r--devel/libgnutls-latest-x86_64.abi1
-rw-r--r--devel/symbols.last1
-rw-r--r--doc/Makefile.am2
-rw-r--r--doc/manpages/Makefile.am1
-rw-r--r--lib/crypto-api.c32
-rw-r--r--lib/crypto-backend.h1
-rw-r--r--lib/crypto-selftests.c27
-rw-r--r--lib/hash_int.c16
-rw-r--r--lib/hash_int.h3
-rw-r--r--lib/includes/gnutls/crypto.h2
-rw-r--r--lib/libgnutls.map1
-rw-r--r--lib/nettle/mac.c17
12 files changed, 104 insertions, 0 deletions
diff --git a/devel/libgnutls-latest-x86_64.abi b/devel/libgnutls-latest-x86_64.abi
index c63a68d94e..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'/>
diff --git a/devel/symbols.last b/devel/symbols.last
index e3d5fa22a5..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
diff --git a/doc/Makefile.am b/doc/Makefile.am
index f5788e7618..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
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
index d4d358ea5c..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
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index db7a08fd92..0cd3d21723 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -637,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 f91a5387d1..43124abafb 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -68,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 200d98ee8d..5110593845 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,14 @@ 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 0
+ if (!copy)
+ return gnutls_assert_val(GNUTLS_E_SELF_TEST_ERROR);
+#endif
+
ret = gnutls_hash(hd,
&vectors[i].plaintext[1],
vectors[i].plaintext_size - 1);
@@ -1390,6 +1399,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",
diff --git a/lib/hash_int.c b/lib/hash_int.c
index 61e24d5375..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) {
diff --git a/lib/hash_int.h b/lib/hash_int.h
index 8e3154daa6..9f6059da33 100644
--- a/lib/hash_int.h
+++ b/lib/hash_int.h
@@ -48,6 +48,7 @@ typedef struct {
hash_func hash;
output_func output;
hash_deinit_func deinit;
+ copy_func copy;
const void *key; /* esoteric use by SSL3 MAC functions */
int keysize;
@@ -126,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 1afadd8759..d2b8cae8f4 100644
--- a/lib/includes/gnutls/crypto.h
+++ b/lib/includes/gnutls/crypto.h
@@ -122,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 */
@@ -229,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 8f504b70f0..0f31f4aef4 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1291,6 +1291,7 @@ 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 90789d876f..8107f7cea4 100644
--- a/lib/nettle/mac.c
+++ b/lib/nettle/mac.c
@@ -632,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)
{
@@ -667,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,
};