Add null digest implementation to the default provider
authorTomas Mraz <tomas@openssl.org>
Fri, 12 Nov 2021 15:31:35 +0000 (16:31 +0100)
committerTomas Mraz <tomas@openssl.org>
Mon, 15 Nov 2021 08:26:03 +0000 (09:26 +0100)
This is necessary to keep compatibility with 1.1.1.

Fixes #16660

Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17016)

(cherry picked from commit bef9b48e5071cdd2b41a4f486d1bcb5e14b2a5c3)

crypto/evp/digest.c
providers/defltprov.c
providers/implementations/digests/build.info
providers/implementations/digests/null_prov.c [new file with mode: 0644]
providers/implementations/include/prov/digestcommon.h
providers/implementations/include/prov/implementations.h
test/evp_extra_test.c

index 1f2910bc695f6059a8577260086fd289e59d2a2e..a269bb8260928cccdeea6d161a079a7b72b58085 100644 (file)
@@ -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);
index 62258da7235a5e7f2a7ebc68b23b8844776cd3e2..6e669fbdfbac27404f730e59256fb5d71b0752fa 100644 (file)
@@ -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 }
 };
 
index 2c2b0c3db045f9f490b3133c1b8b822394bdeb5e..c6508b6e85b267c6c3866357f9b439972b1b8b09 100644 (file)
@@ -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 (file)
index 0000000..b220a19
--- /dev/null
@@ -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 <openssl/crypto.h>
+#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)
index b0ed83648dfcd26b36b2a1a73142f6329fea0684..abdb8bb2ad55a8d5d9a84caee48e834e639881e4 100644 (file)
@@ -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 },                \
index 73e1823742261a98b13c9bfc5a88f3c09251c9aa..30e5e4cd775a903004fc3339d9d4dd6a227839a6 100644 (file)
@@ -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[];
index a8d4d6cf4db085691c60b4ccfbc792cb2ebe1433..0db48a7c93737c09c7610bcc09d57056929b6944 100644 (file)
@@ -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));