From de29ff17a207347f77c0d1df8ea79f16efd82f93 Mon Sep 17 00:00:00 2001
From: Matt Caswell <matt@openssl.org>
Date: Wed, 13 Mar 2019 17:26:17 +0000
Subject: [PATCH] Implement SHA256 in the default provider

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/8513)
---
 crypto/evp/digest.c                 |  2 +
 providers/build.info                |  2 +-
 providers/common/build.info         |  1 +
 providers/common/digests/build.info |  3 ++
 providers/common/digests/sha2.c     | 63 +++++++++++++++++++++++++++++
 providers/default/defltprov.c       | 20 +++++++++
 6 files changed, 90 insertions(+), 1 deletion(-)
 create mode 100644 providers/common/build.info
 create mode 100644 providers/common/digests/build.info
 create mode 100644 providers/common/digests/sha2.c

diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 9e8aaf2203..d4b481443c 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -140,6 +140,8 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 
     if (type->prov == NULL) {
         switch(type->type) {
+        case NID_sha256:
+            break;
         default:
             goto legacy;
         }
diff --git a/providers/build.info b/providers/build.info
index 29cc1845c5..ec4162bdd8 100644
--- a/providers/build.info
+++ b/providers/build.info
@@ -1 +1 @@
-SUBDIRS=default
+SUBDIRS=common default
diff --git a/providers/common/build.info b/providers/common/build.info
new file mode 100644
index 0000000000..5cb7e43830
--- /dev/null
+++ b/providers/common/build.info
@@ -0,0 +1 @@
+SUBDIRS=digests
diff --git a/providers/common/digests/build.info b/providers/common/digests/build.info
new file mode 100644
index 0000000000..a3c2369fb3
--- /dev/null
+++ b/providers/common/digests/build.info
@@ -0,0 +1,3 @@
+LIBS=../../../libcrypto
+SOURCE[../../../libcrypto]=\
+        sha2.c
diff --git a/providers/common/digests/sha2.c b/providers/common/digests/sha2.c
new file mode 100644
index 0000000000..b538ab9c4a
--- /dev/null
+++ b/providers/common/digests/sha2.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 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/sha.h>
+#include <openssl/crypto.h>
+#include <openssl/core_numbers.h>
+
+static int sha256_final(void *ctx, unsigned char *md, size_t *size)
+{
+    if (SHA256_Final(md, ctx)) {
+        *size = SHA256_DIGEST_LENGTH;
+        return 1;
+    }
+
+    return 0;
+}
+
+static void *sha256_newctx(void)
+{
+    SHA256_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+    return ctx;
+}
+
+static void sha256_freectx(void *vctx)
+{
+    SHA256_CTX *ctx = (SHA256_CTX *)vctx;
+
+    OPENSSL_clear_free(ctx,  sizeof(*ctx));
+}
+
+static void *sha256_dupctx(void *ctx)
+{
+    SHA256_CTX *in = (SHA256_CTX *)ctx;
+    SHA256_CTX *ret = OPENSSL_malloc(sizeof(*ret));
+
+    *ret = *in;
+
+    return ret;
+}
+
+static size_t sha256_size(void)
+{
+    return SHA256_DIGEST_LENGTH;
+}
+
+extern const OSSL_DISPATCH sha256_functions[];
+const OSSL_DISPATCH sha256_functions[] = {
+    { OSSL_FUNC_DIGEST_NEWCTX, (void (*)(void))sha256_newctx },
+    { OSSL_FUNC_DIGEST_INIT, (void (*)(void))SHA256_Init },
+    { OSSL_FUNC_DIGEST_UPDDATE, (void (*)(void))SHA256_Update },
+    { OSSL_FUNC_DIGEST_FINAL, (void (*)(void))sha256_final },
+    { OSSL_FUNC_DIGEST_FREECTX, (void (*)(void))sha256_freectx },
+    { OSSL_FUNC_DIGEST_DUPCTX, (void (*)(void))sha256_dupctx },
+    { OSSL_FUNC_DIGEST_SIZE, (void (*)(void))sha256_size },
+    { 0, NULL }
+};
diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c
index 27903098a7..9b52429b50 100644
--- a/providers/default/defltprov.c
+++ b/providers/default/defltprov.c
@@ -49,10 +49,30 @@ static int deflt_get_params(const OSSL_PROVIDER *prov,
     return 1;
 }
 
+extern const OSSL_DISPATCH sha256_functions[];
+
+static const OSSL_ALGORITHM deflt_digests[] = {
+    { "SHA256", "default=yes", sha256_functions },
+    { NULL, NULL, NULL }
+};
+
+static const OSSL_ALGORITHM *deflt_query(OSSL_PROVIDER *prov,
+                                         int operation_id,
+                                         int *no_cache)
+{
+    *no_cache = 0;
+    switch (operation_id) {
+    case OSSL_OP_DIGEST:
+        return deflt_digests;
+    }
+    return NULL;
+}
+
 /* Functions we provide to the core */
 static const OSSL_DISPATCH deflt_dispatch_table[] = {
     { OSSL_FUNC_PROVIDER_GET_PARAM_TYPES, (void (*)(void))deflt_get_param_types },
     { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))deflt_get_params },
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))deflt_query },
     { 0, NULL }
 };
 
-- 
2.25.1