The branch master has been updated via ed16b0fc282d29f755e656043e8a70553ef7bea5 (commit) via 0be4b0403d2f65adf0d037581223dbebd0fa135e (commit) via 0324ae3e98725f722b7d7871c23fbbff596a5bf6 (commit) via 4e62f1a3af36512a1f5e1273d2dc54e3ce7f5fca (commit) via 2c9da416a608e2aaf19c16d920baddf2473c8392 (commit) from 15b7175f558bf9eb057ec3266685486f727dd70f (commit)
- Log ----------------------------------------------------------------- commit ed16b0fc282d29f755e656043e8a70553ef7bea5 Author: Pauli <pa...@openssl.org> Date: Mon Jan 17 13:09:41 2022 +1100 test: add cipher context dup test Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17529) commit 0be4b0403d2f65adf0d037581223dbebd0fa135e Author: Pauli <pa...@openssl.org> Date: Fri Jan 7 11:47:20 2022 +1100 test: add digest context dup tests Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17529) commit 0324ae3e98725f722b7d7871c23fbbff596a5bf6 Author: Pauli <pa...@openssl.org> Date: Fri Jan 7 11:47:02 2022 +1100 doc: document digest and cipher dup functions Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17529) commit 4e62f1a3af36512a1f5e1273d2dc54e3ce7f5fca Author: Pauli <pa...@openssl.org> Date: Fri Jan 7 11:46:33 2022 +1100 Add context dup functions for digests and ciphers Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17529) commit 2c9da416a608e2aaf19c16d920baddf2473c8392 Author: Pauli <pa...@openssl.org> Date: Fri Jan 7 11:45:33 2022 +1100 fix indentation Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17529) ----------------------------------------------------------------------- Summary of changes: crypto/evp/digest.c | 11 +++++++ crypto/evp/evp_enc.c | 11 +++++++ doc/man3/EVP_DigestInit.pod | 17 +++++++++-- doc/man3/EVP_EncryptInit.pod | 20 ++++++++++++ include/openssl/evp.h | 2 ++ providers/implementations/digests/sha3_prov.c | 2 +- providers/implementations/kdfs/pbkdf2.c | 8 ++--- test/evp_extra_test2.c | 16 ++++++++++ test/evp_test.c | 44 +++++++++++++++++++-------- util/libcrypto.num | 2 ++ 10 files changed, 114 insertions(+), 19 deletions(-) diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index d4685e6489..db2eed6355 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -505,6 +505,17 @@ legacy: return ret; } +EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in) +{ + EVP_MD_CTX *out = EVP_MD_CTX_new(); + + if (out != NULL && !EVP_MD_CTX_copy_ex(out, in)) { + EVP_MD_CTX_free(out); + out = NULL; + } + return out; +} + int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) { EVP_MD_CTX_reset(out); diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 519cab3f2b..1c02cafa16 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -1346,6 +1346,17 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) #endif /* FIPS_MODULE */ } +EVP_CIPHER_CTX *EVP_CIPHER_CTX_dup(const EVP_CIPHER_CTX *in) +{ + EVP_CIPHER_CTX *out = EVP_CIPHER_CTX_new(); + + if (out != NULL && !EVP_CIPHER_CTX_copy(out, in)) { + EVP_CIPHER_CTX_free(out); + out = NULL; + } + return out; +} + int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { if ((in == NULL) || (in->cipher == NULL)) { diff --git a/doc/man3/EVP_DigestInit.pod b/doc/man3/EVP_DigestInit.pod index 5b9d75b704..2a2a17f27f 100644 --- a/doc/man3/EVP_DigestInit.pod +++ b/doc/man3/EVP_DigestInit.pod @@ -4,8 +4,8 @@ EVP_MD_fetch, EVP_MD_up_ref, EVP_MD_free, EVP_MD_get_params, EVP_MD_gettable_params, -EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_copy, -EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, +EVP_MD_CTX_new, EVP_MD_CTX_reset, EVP_MD_CTX_free, EVP_MD_CTX_dup, +EVP_MD_CTX_copy, EVP_MD_CTX_copy_ex, EVP_MD_CTX_ctrl, EVP_MD_CTX_set_params, EVP_MD_CTX_get_params, EVP_MD_settable_ctx_params, EVP_MD_gettable_ctx_params, EVP_MD_CTX_settable_params, EVP_MD_CTX_gettable_params, @@ -63,6 +63,7 @@ EVP_MD_CTX_type, EVP_MD_CTX_pkey_ctx, EVP_MD_CTX_md_data int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s); int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); + EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in); int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); @@ -295,6 +296,12 @@ It retrieves the digest value from I<ctx> and places it in I<len>-sized I<md>. After calling this function no additional calls to EVP_DigestUpdate() can be made, but EVP_DigestInit_ex2() can be called to initialize a new operation. +=item EVP_MD_CTX_dup() + +Can be used to duplicate the message digest state from I<in>. This is useful +to avoid multiple EVP_MD_fetch() calls or if large amounts of data are to be +hashed which only differ in the last few bytes. + =item EVP_MD_CTX_copy_ex() Can be used to copy the message digest state from I<in> to I<out>. This is @@ -592,6 +599,10 @@ EVP_MD_CTX_gettable_params() Return an array of constant B<OSSL_PARAM>s, or NULL if there is none to get. +=item EVP_MD_CTX_dup() + +Returns a new EVP_MD_CTX if successful or NULL on failure. + =item EVP_MD_CTX_copy_ex() Returns 1 if successful or 0 for failure. @@ -761,6 +772,8 @@ EVP_MD_CTX_get0_md() instead. EVP_MD_CTX_update_fn() and EVP_MD_CTX_set_update_fn() were deprecated in OpenSSL 3.0. +EVP_MD_CTX_dup() was added in OpenSSL 3.1. + =head1 COPYRIGHT Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod index fcaa5d669d..b220e6e0b8 100644 --- a/doc/man3/EVP_EncryptInit.pod +++ b/doc/man3/EVP_EncryptInit.pod @@ -8,6 +8,8 @@ EVP_CIPHER_free, EVP_CIPHER_CTX_new, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX_free, +EVP_CIPHER_CTX_dup, +EVP_CIPHER_CTX_copy, EVP_EncryptInit_ex, EVP_EncryptInit_ex2, EVP_EncryptUpdate, @@ -109,6 +111,8 @@ EVP_CIPHER_CTX_mode EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void); int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx); void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx); + EVP_CIPHER_CTX *EVP_CIPHER_CTX_dup(const EVP_CIPHER_CTX *in); + int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, const unsigned char *key, const unsigned char *iv); @@ -280,6 +284,16 @@ associated with it, including I<ctx> itself. This function should be called afte all operations using a cipher are complete so sensitive information does not remain in memory. +=item EVP_CIPHER_CTX_dup() + +Can be used to duplicate the cipher state from I<in>. This is useful +to avoid multiple EVP_MD_fetch() calls or if large amounts of data are to be +hashed which only differ in the last few bytes. + +=item EVP_CIPHER_CTX_copy() + +Can be used to copy the cipher state from I<in> to I<out>. + =item EVP_CIPHER_CTX_ctrl() I<This is a legacy method.> EVP_CIPHER_CTX_set_params() and @@ -1186,6 +1200,10 @@ EVP_CIPHER_up_ref() returns 1 for success or 0 otherwise. EVP_CIPHER_CTX_new() returns a pointer to a newly created B<EVP_CIPHER_CTX> for success and B<NULL> for failure. +EVP_CIPHER_CTX_dup() returns a new EVP_MD_CTX if successful or NULL on failure. + +EVP_CIPHER_CTX_copy() returns 1 if successful or 0 for failure. + EVP_EncryptInit_ex2(), EVP_EncryptUpdate() and EVP_EncryptFinal_ex() return 1 for success and 0 for failure. @@ -1699,6 +1717,8 @@ non-deprecated alias macro. The EVP_CIPHER_CTX_flags() macro was deprecated in OpenSSL 1.1.0. +EVP_CIPHER_CTX_dup() was added in OpenSSL 3.1. + =head1 COPYRIGHT Copyright 2000-2021 The OpenSSL Project Authors. All Rights Reserved. diff --git a/include/openssl/evp.h b/include/openssl/evp.h index be57127e36..ae8ddbcf41 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -634,6 +634,7 @@ unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx); int EVP_CIPHER_CTX_get_num(const EVP_CIPHER_CTX *ctx); # define EVP_CIPHER_CTX_num EVP_CIPHER_CTX_get_num int EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num); +EVP_CIPHER_CTX *EVP_CIPHER_CTX_dup(const EVP_CIPHER_CTX *in); int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in); void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx); void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data); @@ -699,6 +700,7 @@ void EVP_MD_CTX_free(EVP_MD_CTX *ctx); # define EVP_MD_CTX_create() EVP_MD_CTX_new() # define EVP_MD_CTX_init(ctx) EVP_MD_CTX_reset((ctx)) # define EVP_MD_CTX_destroy(ctx) EVP_MD_CTX_free((ctx)) +__owur EVP_MD_CTX *EVP_MD_CTX_dup(const EVP_MD_CTX *in); __owur int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in); void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags); void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags); diff --git a/providers/implementations/digests/sha3_prov.c b/providers/implementations/digests/sha3_prov.c index 230de73275..65e8262a3e 100644 --- a/providers/implementations/digests/sha3_prov.c +++ b/providers/implementations/digests/sha3_prov.c @@ -268,7 +268,7 @@ static void *keccak_dupctx(void *ctx) { KECCAK1600_CTX *in = (KECCAK1600_CTX *)ctx; KECCAK1600_CTX *ret = ossl_prov_is_running() ? OPENSSL_malloc(sizeof(*ret)) - : NULL; + : NULL; if (ret != NULL) *ret = *in; diff --git a/providers/implementations/kdfs/pbkdf2.c b/providers/implementations/kdfs/pbkdf2.c index b9e865f8ec..4c829a6d1f 100644 --- a/providers/implementations/kdfs/pbkdf2.c +++ b/providers/implementations/kdfs/pbkdf2.c @@ -45,10 +45,10 @@ static OSSL_FUNC_kdf_set_ctx_params_fn kdf_pbkdf2_set_ctx_params; static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_pbkdf2_gettable_ctx_params; static OSSL_FUNC_kdf_get_ctx_params_fn kdf_pbkdf2_get_ctx_params; -static int pbkdf2_derive(const char *pass, size_t passlen, - const unsigned char *salt, int saltlen, uint64_t iter, - const EVP_MD *digest, unsigned char *key, - size_t keylen, int extra_checks); +static int pbkdf2_derive(const char *pass, size_t passlen, + const unsigned char *salt, int saltlen, uint64_t iter, + const EVP_MD *digest, unsigned char *key, + size_t keylen, int extra_checks); typedef struct { void *provctx; diff --git a/test/evp_extra_test2.c b/test/evp_extra_test2.c index b70c168d9d..287f3d1443 100644 --- a/test/evp_extra_test2.c +++ b/test/evp_extra_test2.c @@ -853,6 +853,21 @@ static int test_rsa_pss_sign(void) return ret; } +static int test_evp_md_ctx_dup(void) +{ + EVP_MD_CTX *mdctx; + EVP_MD_CTX *copyctx = NULL; + int ret; + + /* test copying freshly initialized context */ + ret = TEST_ptr(mdctx = EVP_MD_CTX_new()) + && TEST_ptr(copyctx = EVP_MD_CTX_dup(mdctx)); + + EVP_MD_CTX_free(mdctx); + EVP_MD_CTX_free(copyctx); + return ret; +} + static int test_evp_md_ctx_copy(void) { EVP_MD_CTX *mdctx = NULL; @@ -895,6 +910,7 @@ int setup_tests(void) #endif ADD_ALL_TESTS(test_PEM_read_bio_negative, OSSL_NELEM(keydata)); ADD_TEST(test_rsa_pss_sign); + ADD_TEST(test_evp_md_ctx_dup); ADD_TEST(test_evp_md_ctx_copy); return 1; } diff --git a/test/evp_test.c b/test/evp_test.c index d068d6fa8e..871f2a9c6b 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -396,6 +396,26 @@ static int digest_update_fn(void *ctx, const unsigned char *buf, size_t buflen) return EVP_DigestUpdate(ctx, buf, buflen); } +static int test_duplicate_md_ctx(EVP_TEST *t, EVP_MD_CTX *mctx) +{ + char dont[] = "touch"; + + if (!TEST_ptr(mctx)) + return 0; + if (!EVP_DigestFinalXOF(mctx, (unsigned char *)dont, 0)) { + EVP_MD_CTX_free(mctx); + t->err = "DIGESTFINALXOF_ERROR"; + return 0; + } + if (!TEST_str_eq(dont, "touch")) { + EVP_MD_CTX_free(mctx); + t->err = "DIGESTFINALXOF_ERROR"; + return 0; + } + EVP_MD_CTX_free(mctx); + return 1; +} + static int digest_test_run(EVP_TEST *t) { DIGEST_DATA *expected = t->data; @@ -407,6 +427,7 @@ static int digest_test_run(EVP_TEST *t) int xof = 0; OSSL_PARAM params[2]; + printf("test %s (%d %d)\n", t->name, t->s.start, t->s.curr); t->err = "TEST_FAILURE"; if (!TEST_ptr(mctx = EVP_MD_CTX_new())) goto err; @@ -437,26 +458,19 @@ static int digest_test_run(EVP_TEST *t) xof = (EVP_MD_get_flags(expected->digest) & EVP_MD_FLAG_XOF) != 0; if (xof) { EVP_MD_CTX *mctx_cpy; - char dont[] = "touch"; if (!TEST_ptr(mctx_cpy = EVP_MD_CTX_new())) { goto err; } - if (!EVP_MD_CTX_copy(mctx_cpy, mctx)) { + if (!TEST_true(EVP_MD_CTX_copy(mctx_cpy, mctx))) { EVP_MD_CTX_free(mctx_cpy); goto err; - } - if (!EVP_DigestFinalXOF(mctx_cpy, (unsigned char *)dont, 0)) { - EVP_MD_CTX_free(mctx_cpy); - t->err = "DIGESTFINALXOF_ERROR"; + } else if (!test_duplicate_md_ctx(t, mctx_cpy)) { goto err; } - if (!TEST_str_eq(dont, "touch")) { - EVP_MD_CTX_free(mctx_cpy); - t->err = "DIGESTFINALXOF_ERROR"; + + if (!test_duplicate_md_ctx(t, EVP_MD_CTX_dup(mctx))) goto err; - } - EVP_MD_CTX_free(mctx_cpy); got_len = expected->output_len; if (!EVP_DigestFinalXOF(mctx, got, got_len)) { @@ -694,7 +708,7 @@ static int cipher_test_enc(EVP_TEST *t, int enc, size_t in_len, out_len, donelen = 0; int ok = 0, tmplen, chunklen, tmpflen, i; EVP_CIPHER_CTX *ctx_base = NULL; - EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER_CTX *ctx = NULL, *duped; t->err = "TEST_FAILURE"; if (!TEST_ptr(ctx_base = EVP_CIPHER_CTX_new())) @@ -832,6 +846,12 @@ static int cipher_test_enc(EVP_TEST *t, int enc, EVP_CIPHER_CTX_free(ctx); ctx = ctx_base; } + /* Likewise for dup */ + duped = EVP_CIPHER_CTX_dup(ctx); + if (duped != NULL) { + EVP_CIPHER_CTX_free(ctx); + ctx = duped; + } ERR_pop_to_mark(); if (expected->mac_key != NULL diff --git a/util/libcrypto.num b/util/libcrypto.num index 681cbf31b0..762e23a858 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -5426,3 +5426,5 @@ ASN1_TIME_print_ex 5553 3_0_0 EXIST::FUNCTION: EVP_PKEY_get0_provider 5554 3_0_0 EXIST::FUNCTION: EVP_PKEY_CTX_get0_provider 5555 3_0_0 EXIST::FUNCTION: OSSL_STACK_OF_X509_free ? 3_1_0 EXIST::FUNCTION: +EVP_MD_CTX_dup ? 3_1_0 EXIST::FUNCTION: +EVP_CIPHER_CTX_dup ? 3_1_0 EXIST::FUNCTION: