From cf9a84a12dc4f3b314347e44f5c51b473a504926 Mon Sep 17 00:00:00 2001 From: Tomas Mraz Date: Fri, 12 Nov 2021 16:31:35 +0100 Subject: [PATCH] Add null digest implementation to the default provider This is necessary to keep compatibility with 1.1.1. Fixes #16660 Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/17016) (cherry picked from commit bef9b48e5071cdd2b41a4f486d1bcb5e14b2a5c3) --- crypto/evp/digest.c | 5 +- providers/defltprov.c | 1 + providers/implementations/digests/build.info | 3 ++ providers/implementations/digests/null_prov.c | 52 +++++++++++++++++++ .../include/prov/digestcommon.h | 23 ++++---- .../include/prov/implementations.h | 1 + test/evp_extra_test.c | 30 +++++++++++ 7 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 providers/implementations/digests/null_prov.c diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index 1f2910bc69..a269bb8260 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -228,7 +228,10 @@ static int evp_md_init_internal(EVP_MD_CTX *ctx, const EVP_MD *type, ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); return 0; #else - EVP_MD *provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), ""); + /* The NULL digest is a special case */ + EVP_MD *provmd = EVP_MD_fetch(NULL, + type->type != NID_undef ? OBJ_nid2sn(type->type) + : "NULL", ""); if (provmd == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); diff --git a/providers/defltprov.c b/providers/defltprov.c index 62258da723..6e669fbdfb 100644 --- a/providers/defltprov.c +++ b/providers/defltprov.c @@ -148,6 +148,7 @@ static const OSSL_ALGORITHM deflt_digests[] = { { PROV_NAMES_MD5_SHA1, "provider=default", ossl_md5_sha1_functions }, #endif /* OPENSSL_NO_MD5 */ + { PROV_NAMES_NULL, "provider=default", ossl_nullmd_functions }, { NULL, NULL, NULL } }; diff --git a/providers/implementations/digests/build.info b/providers/implementations/digests/build.info index 2c2b0c3db0..c6508b6e85 100644 --- a/providers/implementations/digests/build.info +++ b/providers/implementations/digests/build.info @@ -9,6 +9,7 @@ $SHA3_GOAL=../../libdefault.a ../../libfips.a $BLAKE2_GOAL=../../libdefault.a $SM3_GOAL=../../libdefault.a $MD5_GOAL=../../libdefault.a +$NULL_GOAL=../../libdefault.a $MD2_GOAL=../../liblegacy.a $MD4_GOAL=../../liblegacy.a @@ -22,6 +23,8 @@ SOURCE[$COMMON_GOAL]=digestcommon.c SOURCE[$SHA2_GOAL]=sha2_prov.c SOURCE[$SHA3_GOAL]=sha3_prov.c +SOURCE[$NULL_GOAL]=null_prov.c + IF[{- !$disabled{blake2} -}] SOURCE[$BLAKE2_GOAL]=blake2_prov.c blake2b_prov.c blake2s_prov.c ENDIF diff --git a/providers/implementations/digests/null_prov.c b/providers/implementations/digests/null_prov.c new file mode 100644 index 0000000000..b220a1966f --- /dev/null +++ b/providers/implementations/digests/null_prov.c @@ -0,0 +1,52 @@ +/* + * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "prov/digestcommon.h" +#include "prov/implementations.h" + +typedef struct { + unsigned char nothing; +} NULLMD_CTX; + +static int null_init(NULLMD_CTX *ctx) +{ + return 1; +} + +static int null_update(NULLMD_CTX *ctx, const void *data, size_t datalen) +{ + return 1; +} + +static int null_final(unsigned char *md, NULLMD_CTX *ctx) +{ + return 1; +} + +/* + * We must override the PROV_FUNC_DIGEST_FINAL as dgstsize == 0 + * and that would cause compilation warnings with the default implementation. + */ +#undef PROV_FUNC_DIGEST_FINAL +#define PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \ +static OSSL_FUNC_digest_final_fn name##_internal_final; \ +static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \ + size_t outsz) \ +{ \ + if (ossl_prov_is_running() && fin(out, ctx)) { \ + *outl = dgstsize; \ + return 1; \ + } \ + return 0; \ +} + +IMPLEMENT_digest_functions(nullmd, NULLMD_CTX, + 0, 0, 0, + null_init, null_update, null_final) diff --git a/providers/implementations/include/prov/digestcommon.h b/providers/implementations/include/prov/digestcommon.h index b0ed83648d..abdb8bb2ad 100644 --- a/providers/implementations/include/prov/digestcommon.h +++ b/providers/implementations/include/prov/digestcommon.h @@ -35,6 +35,18 @@ static int name##_get_params(OSSL_PARAM params[]) \ { OSSL_FUNC_DIGEST_GETTABLE_PARAMS, \ (void (*)(void))ossl_digest_default_gettable_params } +# define PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \ +static OSSL_FUNC_digest_final_fn name##_internal_final; \ +static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \ + size_t outsz) \ +{ \ + if (ossl_prov_is_running() && outsz >= dgstsize && fin(out, ctx)) { \ + *outl = dgstsize; \ + return 1; \ + } \ + return 0; \ +} + # define PROV_DISPATCH_FUNC_DIGEST_CONSTRUCT_START( \ name, CTX, blksize, dgstsize, flags, upd, fin) \ static OSSL_FUNC_digest_newctx_fn name##_newctx; \ @@ -58,16 +70,7 @@ static void *name##_dupctx(void *ctx) \ *ret = *in; \ return ret; \ } \ -static OSSL_FUNC_digest_final_fn name##_internal_final; \ -static int name##_internal_final(void *ctx, unsigned char *out, size_t *outl, \ - size_t outsz) \ -{ \ - if (ossl_prov_is_running() && outsz >= dgstsize && fin(out, ctx)) { \ - *outl = dgstsize; \ - return 1; \ - } \ - return 0; \ -} \ +PROV_FUNC_DIGEST_FINAL(name, dgstsize, fin) \ PROV_FUNC_DIGEST_GET_PARAM(name, blksize, dgstsize, flags) \ const OSSL_DISPATCH ossl_##name##_functions[] = { \ { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))name##_newctx }, \ diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index 73e1823742..30e5e4cd77 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -36,6 +36,7 @@ extern const OSSL_DISPATCH ossl_md4_functions[]; extern const OSSL_DISPATCH ossl_mdc2_functions[]; extern const OSSL_DISPATCH ossl_wp_functions[]; extern const OSSL_DISPATCH ossl_ripemd160_functions[]; +extern const OSSL_DISPATCH ossl_nullmd_functions[]; /* Ciphers */ extern const OSSL_DISPATCH ossl_null_functions[]; diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index a8d4d6cf4d..0db48a7c93 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -1445,6 +1445,35 @@ static int test_EVP_Digest(void) return ret; } +static int test_EVP_md_null(void) +{ + int ret = 0; + EVP_MD_CTX *md_ctx = NULL; + const EVP_MD *md_null = EVP_md_null(); + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned int md_len = sizeof(md_value); + + if (nullprov != NULL) + return TEST_skip("Test does not support a non-default library context"); + + if (!TEST_ptr(md_null) + || !TEST_ptr(md_ctx = EVP_MD_CTX_new())) + goto out; + + if (!TEST_true(EVP_DigestInit_ex(md_ctx, md_null, NULL)) + || !TEST_true(EVP_DigestUpdate(md_ctx, "test", 4)) + || !TEST_true(EVP_DigestFinal_ex(md_ctx, md_value, &md_len))) + goto out; + + if (!TEST_uint_eq(md_len, 0)) + goto out; + + ret = 1; + out: + EVP_MD_CTX_free(md_ctx); + return ret; +} + static int test_d2i_AutoPrivateKey(int i) { int ret = 0; @@ -4249,6 +4278,7 @@ int setup_tests(void) ADD_TEST(test_siphash_digestsign); #endif ADD_TEST(test_EVP_Digest); + ADD_TEST(test_EVP_md_null); ADD_ALL_TESTS(test_EVP_PKEY_sign, 3); ADD_ALL_TESTS(test_EVP_Enveloped, 2); ADD_ALL_TESTS(test_d2i_AutoPrivateKey, OSSL_NELEM(keydata)); -- 2.34.1