diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-06-26 11:00:39 +0300 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2019-06-26 11:01:19 +0300 |
commit | c034cf9f332de9f6ccb878e1b0f0355049489827 (patch) | |
tree | dc4a8295710ac0ac9f2593cfafe8a54f9f8994ec /lib | |
parent | 6b41d6ce9f18eac9673279db336f8c84bc839cac (diff) | |
download | gnutls-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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/crypto-api.c | 32 | ||||
-rw-r--r-- | lib/crypto-backend.h | 1 | ||||
-rw-r--r-- | lib/crypto-selftests.c | 27 | ||||
-rw-r--r-- | lib/hash_int.c | 16 | ||||
-rw-r--r-- | lib/hash_int.h | 3 | ||||
-rw-r--r-- | lib/includes/gnutls/crypto.h | 2 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/nettle/mac.c | 17 |
8 files changed, 99 insertions, 0 deletions
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, }; |