[openssl] master update

Matt Caswell matt at openssl.org
Thu Mar 21 09:28:08 UTC 2019


The branch master has been updated
       via  fdf6c0b6b72756ba69be589b2aaecdd51e4ec12a (commit)
       via  847d0f81bb6f38662aa9d3d448282eda30ed5193 (commit)
       via  de29ff17a207347f77c0d1df8ea79f16efd82f93 (commit)
       via  8c8cf0d96240663749897b44898b3964fa3363e0 (commit)
       via  3653d0c224593ef55830c2fb17941aba9ea26ea8 (commit)
       via  8a73348be02fabc367c375dd3c543753649b2a58 (commit)
      from  df5375b446e700fdd5e8a4aa360d458c4ffed046 (commit)


- Log -----------------------------------------------------------------
commit fdf6c0b6b72756ba69be589b2aaecdd51e4ec12a
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Mar 18 16:15:58 2019 +0000

    Document the functions EVP_MD_fetch() and EVP_MD_upref()
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8513)

commit 847d0f81bb6f38662aa9d3d448282eda30ed5193
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Mar 18 14:36:41 2019 +0000

    Add a test for EVP_MD_fetch
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8513)

commit de29ff17a207347f77c0d1df8ea79f16efd82f93
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Mar 13 17:26:17 2019 +0000

    Implement SHA256 in the default provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8513)

commit 8c8cf0d96240663749897b44898b3964fa3363e0
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Mar 13 16:17:17 2019 +0000

    Make EVP_Digest* functions provider aware
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8513)

commit 3653d0c224593ef55830c2fb17941aba9ea26ea8
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Mar 13 14:49:40 2019 +0000

    Implement EVP_MD_fetch()
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8513)

commit 8a73348be02fabc367c375dd3c543753649b2a58
Author: Matt Caswell <matt at openssl.org>
Date:   Wed Mar 13 12:02:55 2019 +0000

    Add a skeleton default provider
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/8513)

-----------------------------------------------------------------------

Summary of changes:
 build.info                                   |   2 +-
 crypto/err/openssl.txt                       |   5 +
 crypto/evp/digest.c                          | 294 ++++++++++++++++++++++++++-
 crypto/evp/evp_err.c                         |   6 +
 crypto/evp/evp_lib.c                         |  31 ++-
 crypto/evp/evp_locl.h                        |   4 +
 crypto/include/internal/evp_int.h            |  20 ++
 crypto/provider_predefined.c                 |   4 -
 doc/man3/EVP_MD_fetch.pod                    | 162 +++++++++++++++
 doc/man3/EVP_MD_meth_new.pod                 |  17 +-
 include/openssl/core_names.h                 |  41 ++++
 include/openssl/core_numbers.h               |  26 +++
 include/openssl/evp.h                        |   4 +
 include/openssl/evperr.h                     |   5 +
 providers/build.info                         |   1 +
 providers/common/build.info                  |   1 +
 providers/common/digests/build.info          |   3 +
 providers/common/digests/sha2.c              |  63 ++++++
 {crypto/sm4 => providers/default}/build.info |   3 +-
 providers/default/defltprov.c                | 101 +++++++++
 test/evp_extra_test.c                        | 102 ++++++++++
 util/libcrypto.num                           |   2 +
 22 files changed, 880 insertions(+), 17 deletions(-)
 create mode 100644 doc/man3/EVP_MD_fetch.pod
 create mode 100644 include/openssl/core_names.h
 create mode 100644 providers/build.info
 create mode 100644 providers/common/build.info
 create mode 100644 providers/common/digests/build.info
 create mode 100644 providers/common/digests/sha2.c
 copy {crypto/sm4 => providers/default}/build.info (70%)
 create mode 100644 providers/default/defltprov.c

diff --git a/build.info b/build.info
index bea1441..a0ecb21 100644
--- a/build.info
+++ b/build.info
@@ -1,6 +1,6 @@
 # Note that some of these directories are filtered in Configure.  Look for
 # %skipdir there for further explanations.
-SUBDIRS=crypto ssl apps test util tools fuzz engines
+SUBDIRS=crypto ssl apps test util tools fuzz engines providers
 
 LIBS=libcrypto libssl
 INCLUDE[libcrypto]=. crypto/include include
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 7309ed8..f52beb1 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -781,7 +781,9 @@ EVP_F_EVP_CIPHER_PARAM_TO_ASN1:205:EVP_CIPHER_param_to_asn1
 EVP_F_EVP_DECRYPTFINAL_EX:101:EVP_DecryptFinal_ex
 EVP_F_EVP_DECRYPTUPDATE:166:EVP_DecryptUpdate
 EVP_F_EVP_DIGESTFINALXOF:174:EVP_DigestFinalXOF
+EVP_F_EVP_DIGESTFINAL_EX:230:EVP_DigestFinal_ex
 EVP_F_EVP_DIGESTINIT_EX:128:EVP_DigestInit_ex
+EVP_F_EVP_DIGESTUPDATE:231:EVP_DigestUpdate
 EVP_F_EVP_ENCRYPTDECRYPTUPDATE:219:evp_EncryptDecryptUpdate
 EVP_F_EVP_ENCRYPTFINAL_EX:127:EVP_EncryptFinal_ex
 EVP_F_EVP_ENCRYPTUPDATE:167:EVP_EncryptUpdate
@@ -2356,6 +2358,7 @@ EVP_R_EXPECTING_A_DSA_KEY:129:expecting a dsa key
 EVP_R_EXPECTING_A_EC_KEY:142:expecting a ec key
 EVP_R_EXPECTING_A_POLY1305_KEY:164:expecting a poly1305 key
 EVP_R_EXPECTING_A_SIPHASH_KEY:175:expecting a siphash key
+EVP_R_FINAL_ERROR:188:final error
 EVP_R_FIPS_MODE_NOT_SUPPORTED:167:fips mode not supported
 EVP_R_GET_RAW_KEY_FAILED:182:get raw key failed
 EVP_R_ILLEGAL_SCRYPT_PARAMETERS:171:illegal scrypt parameters
@@ -2374,6 +2377,7 @@ EVP_R_MEMORY_LIMIT_EXCEEDED:172:memory limit exceeded
 EVP_R_MESSAGE_DIGEST_IS_NULL:159:message digest is null
 EVP_R_METHOD_NOT_SUPPORTED:144:method not supported
 EVP_R_MISSING_PARAMETERS:103:missing parameters
+EVP_R_NOT_ABLE_TO_COPY_CTX:190:not able to copy ctx
 EVP_R_NOT_XOF_OR_INVALID_LENGTH:178:not XOF or invalid length
 EVP_R_NO_CIPHER_SET:131:no cipher set
 EVP_R_NO_DEFAULT_DIGEST:158:no default digest
@@ -2407,6 +2411,7 @@ EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS:135:unsupported number of rounds
 EVP_R_UNSUPPORTED_PRF:125:unsupported prf
 EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM:118:unsupported private key algorithm
 EVP_R_UNSUPPORTED_SALT_TYPE:126:unsupported salt type
+EVP_R_UPDATE_ERROR:189:update error
 EVP_R_WRAP_MODE_NOT_ALLOWED:170:wrap mode not allowed
 EVP_R_WRONG_FINAL_BLOCK_LENGTH:109:wrong final block length
 KDF_R_INVALID_DIGEST:100:invalid digest
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 86be9ae..d4b4814 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -13,6 +13,7 @@
 #include <openssl/evp.h>
 #include <openssl/engine.h>
 #include "internal/evp_int.h"
+#include "internal/provider.h"
 #include "evp_locl.h"
 
 /* This call frees resources associated with the context */
@@ -21,6 +22,24 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
     if (ctx == NULL)
         return 1;
 
+    if (ctx->digest == NULL || ctx->digest->prov == NULL)
+        goto legacy;
+
+    if (ctx->provctx != NULL) {
+        if (ctx->digest->freectx != NULL)
+            ctx->digest->freectx(ctx->provctx);
+        ctx->provctx = NULL;
+        EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+    }
+
+    if (ctx->pctx != NULL)
+        goto legacy;
+
+    return 1;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
     /*
      * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
      * sometimes only copies of the context are ever finalised.
@@ -53,6 +72,23 @@ EVP_MD_CTX *EVP_MD_CTX_new(void)
 
 void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
 {
+    if (ctx == NULL)
+        return;
+
+    if (ctx->digest == NULL || ctx->digest->prov == NULL)
+        goto legacy;
+
+    EVP_MD_CTX_reset(ctx);
+
+    EVP_MD_meth_free(ctx->fetched_digest);
+    ctx->fetched_digest = NULL;
+    ctx->digest = NULL;
+
+    OPENSSL_free(ctx);
+    return;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
     EVP_MD_CTX_reset(ctx);
     OPENSSL_free(ctx);
 }
@@ -65,7 +101,12 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
 
 int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 {
+    EVP_MD *provmd;
+    ENGINE *tmpimpl = NULL;
+
     EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
+
+    /* TODO(3.0): Legacy work around code below. Remove this */
 #ifndef OPENSSL_NO_ENGINE
     /*
      * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
@@ -76,6 +117,74 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
     if (ctx->engine && ctx->digest &&
         (type == NULL || (type->type == ctx->digest->type)))
         goto skip_to_init;
+
+    if (type != NULL && impl == NULL)
+        tmpimpl = ENGINE_get_digest_engine(type->type);
+#endif
+
+    /*
+     * If there are engines involved or if we're being used as part of
+     * EVP_DigestSignInit then we should use legacy handling for now.
+     */
+    if (ctx->engine != NULL
+            || impl != NULL
+            || tmpimpl != NULL
+            || ctx->pctx != NULL
+            || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) {
+        if (ctx->digest == ctx->fetched_digest)
+            ctx->digest = NULL;
+        EVP_MD_meth_free(ctx->fetched_digest);
+        ctx->fetched_digest = NULL;
+        goto legacy;
+    }
+
+    if (type->prov == NULL) {
+        switch(type->type) {
+        case NID_sha256:
+            break;
+        default:
+            goto legacy;
+        }
+    }
+
+    if (ctx->digest != NULL && ctx->digest->ctx_size > 0) {
+        OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
+        ctx->md_data = NULL;
+    }
+
+    /* TODO(3.0): Start of non-legacy code below */
+
+    if (type->prov == NULL) {
+        provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), "");
+        if (provmd == NULL) {
+            EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+        type = provmd;
+        EVP_MD_meth_free(ctx->fetched_digest);
+        ctx->fetched_digest = provmd;
+    }
+
+    ctx->digest = type;
+    if (ctx->provctx == NULL) {
+        ctx->provctx = ctx->digest->newctx();
+        if (ctx->provctx == NULL) {
+            EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+            return 0;
+        }
+    }
+
+    if (ctx->digest->dinit == NULL) {
+        EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
+        return 0;
+    }
+
+    return ctx->digest->dinit(ctx->provctx);
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
+
+#ifndef OPENSSL_NO_ENGINE
     if (type) {
         /*
          * Ensure an ENGINE left lying around from last time is cleared (the
@@ -90,7 +199,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
             }
         } else {
             /* Ask if an ENGINE is reserved for this job */
-            impl = ENGINE_get_digest_engine(type->type);
+            impl = tmpimpl;
         }
         if (impl != NULL) {
             /* There's an ENGINE for this job ... (apparently) */
@@ -150,6 +259,17 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
 
 int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
 {
+    if (ctx->digest == NULL || ctx->digest->prov == NULL)
+        goto legacy;
+
+    if (ctx->digest->dupdate == NULL) {
+        EVPerr(EVP_F_EVP_DIGESTUPDATE, EVP_R_UPDATE_ERROR);
+        return 0;
+    }
+    return ctx->digest->dupdate(ctx->provctx, data, count);
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
     return ctx->update(ctx, data, count);
 }
 
@@ -163,14 +283,40 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
 }
 
 /* The caller can assume that this removes any secret data from the context */
-int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *isize)
 {
     int ret;
+    size_t size = 0;
+
+    if (ctx->digest == NULL || ctx->digest->prov == NULL)
+        goto legacy;
+
+    if (ctx->digest->dfinal == NULL) {
+        EVPerr(EVP_F_EVP_DIGESTFINAL_EX, EVP_R_FINAL_ERROR);
+        return 0;
+    }
+
+    ret = ctx->digest->dfinal(ctx->provctx, md, &size);
+
+    if (isize != NULL) {
+        if (size <= UINT_MAX) {
+            *isize = (int)size;
+        } else {
+            EVPerr(EVP_F_EVP_DIGESTFINAL_EX, EVP_R_FINAL_ERROR);
+            ret = 0;
+        }
+    }
+
+    EVP_MD_CTX_reset(ctx);
+
+    return ret;
 
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
     OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
     ret = ctx->digest->final(ctx, md);
-    if (size != NULL)
-        *size = ctx->digest->md_size;
+    if (isize != NULL)
+        *isize = ctx->digest->md_size;
     if (ctx->digest->cleanup) {
         ctx->digest->cleanup(ctx);
         EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
@@ -209,10 +355,52 @@ int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
 {
     unsigned char *tmp_buf;
-    if ((in == NULL) || (in->digest == NULL)) {
+
+    if (in == NULL || in->digest == NULL) {
         EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED);
         return 0;
     }
+
+    if (in->digest->prov == NULL)
+        goto legacy;
+
+    if (in->digest->dupctx == NULL) {
+        EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
+        return 0;
+    }
+
+    EVP_MD_CTX_reset(out);
+    if (out->fetched_digest != NULL)
+        EVP_MD_meth_free(out->fetched_digest);
+    *out = *in;
+    /* NULL out pointers in case of error */
+    out->pctx = NULL;
+    out->provctx = NULL;
+
+    if (in->fetched_digest != NULL)
+        EVP_MD_upref(in->fetched_digest);
+
+    out->provctx = in->digest->dupctx(in->provctx);
+    if (out->provctx == NULL) {
+        EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
+        return 0;
+    }
+
+    /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
+    EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
+    if (in->pctx != NULL) {
+        out->pctx = EVP_PKEY_CTX_dup(in->pctx);
+        if (out->pctx == NULL) {
+            EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_NOT_ABLE_TO_COPY_CTX);
+            EVP_MD_CTX_reset(out);
+            return 0;
+        }
+    }
+
+    return 1;
+
+    /* TODO(3.0): Remove legacy code below */
+ legacy:
 #ifndef OPENSSL_NO_ENGINE
     /* Make sure it's safe to copy a digest context using an ENGINE */
     if (in->engine && !ENGINE_init(in->engine)) {
@@ -296,3 +484,99 @@ int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
     }
     return 0;
 }
+
+static void *evp_md_from_dispatch(int mdtype, const OSSL_DISPATCH *fns,
+                                    OSSL_PROVIDER *prov)
+{
+    EVP_MD *md = NULL;
+    int fncnt = 0;
+
+    if ((md = EVP_MD_meth_new(mdtype, NID_undef)) == NULL)
+        return NULL;
+
+    for (; fns->function_id != 0; fns++) {
+        switch (fns->function_id) {
+        case OSSL_FUNC_DIGEST_NEWCTX:
+            if (md->newctx != NULL)
+                break;
+            md->newctx = OSSL_get_OP_digest_newctx(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_DIGEST_INIT:
+            if (md->dinit != NULL)
+                break;
+            md->dinit = OSSL_get_OP_digest_init(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_DIGEST_UPDDATE:
+            if (md->dupdate != NULL)
+                break;
+            md->dupdate = OSSL_get_OP_digest_update(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_DIGEST_FINAL:
+            if (md->dfinal != NULL)
+                break;
+            md->dfinal = OSSL_get_OP_digest_final(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_DIGEST_DIGEST:
+            if (md->digest != NULL)
+                break;
+            md->digest = OSSL_get_OP_digest_digest(fns);
+            /* We don't increment fnct for this as it is stand alone */
+            break;
+        case OSSL_FUNC_DIGEST_FREECTX:
+            if (md->freectx != NULL)
+                break;
+            md->freectx = OSSL_get_OP_digest_freectx(fns);
+            fncnt++;
+            break;
+        case OSSL_FUNC_DIGEST_DUPCTX:
+            if (md->dupctx != NULL)
+                break;
+            md->dupctx = OSSL_get_OP_digest_dupctx(fns);
+            break;
+        case OSSL_FUNC_DIGEST_SIZE:
+            if (md->size != NULL)
+                break;
+            md->size = OSSL_get_OP_digest_size(fns);
+            break;
+        }
+    }
+    if ((fncnt != 0 && fncnt != 5)
+        || (fncnt == 0 && md->digest == NULL)
+        || md->size == NULL) {
+        /*
+         * In order to be a consistent set of functions we either need the
+         * whole set of init/update/final etc functions or none of them.
+         * The "digest" function can standalone. We at least need one way to
+         * generate digests.
+         */
+        EVP_MD_meth_free(md);
+        return NULL;
+    }
+    md->prov = prov;
+    if (prov != NULL)
+        ossl_provider_upref(prov);
+
+    return md;
+}
+
+static int evp_md_upref(void *md)
+{
+    return EVP_MD_upref(md);
+}
+
+static void evp_md_free(void *md)
+{
+    EVP_MD_meth_free(md);
+}
+
+EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                     const char *properties)
+{
+    return evp_generic_fetch(ctx, OSSL_OP_DIGEST, algorithm, properties,
+                             evp_md_from_dispatch, evp_md_upref,
+                             evp_md_free);
+}
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index ef889b0..068120e 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -54,7 +54,9 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
      "EVP_DecryptFinal_ex"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTUPDATE, 0), "EVP_DecryptUpdate"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINALXOF, 0), "EVP_DigestFinalXOF"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTFINAL_EX, 0), "EVP_DigestFinal_ex"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTINIT_EX, 0), "EVP_DigestInit_ex"},
+    {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DIGESTUPDATE, 0), "EVP_DigestUpdate"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTDECRYPTUPDATE, 0),
      "evp_EncryptDecryptUpdate"},
     {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
@@ -219,6 +221,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "expecting a poly1305 key"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_A_SIPHASH_KEY),
     "expecting a siphash key"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FINAL_ERROR), "final error"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_FIPS_MODE_NOT_SUPPORTED),
     "fips mode not supported"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_GET_RAW_KEY_FAILED), "get raw key failed"},
@@ -246,6 +249,8 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_METHOD_NOT_SUPPORTED),
     "method not supported"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_MISSING_PARAMETERS), "missing parameters"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_ABLE_TO_COPY_CTX),
+    "not able to copy ctx"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NOT_XOF_OR_INVALID_LENGTH),
     "not XOF or invalid length"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_NO_CIPHER_SET), "no cipher set"},
@@ -293,6 +298,7 @@ static const ERR_STRING_DATA EVP_str_reasons[] = {
     "unsupported private key algorithm"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UNSUPPORTED_SALT_TYPE),
     "unsupported salt type"},
+    {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_UPDATE_ERROR), "update error"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRAP_MODE_NOT_ALLOWED),
     "wrap mode not allowed"},
     {ERR_PACK(ERR_LIB_EVP, 0, EVP_R_WRONG_FINAL_BLOCK_LENGTH),
diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c
index f0ee6ab..219ae53 100644
--- a/crypto/evp/evp_lib.c
+++ b/crypto/evp/evp_lib.c
@@ -12,6 +12,7 @@
 #include <openssl/evp.h>
 #include <openssl/objects.h>
 #include "internal/evp_int.h"
+#include "internal/provider.h"
 #include "evp_locl.h"
 
 int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
@@ -316,6 +317,10 @@ int EVP_MD_size(const EVP_MD *md)
         EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL);
         return -1;
     }
+
+    if (md->prov != NULL && md->size != NULL)
+        return (int)md->size();
+
     return md->md_size;
 }
 
@@ -331,6 +336,12 @@ EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type)
     if (md != NULL) {
         md->type = md_type;
         md->pkey_type = pkey_type;
+        md->lock = CRYPTO_THREAD_lock_new();
+        if (md->lock == NULL) {
+            OPENSSL_free(md);
+            return NULL;
+        }
+        md->refcnt = 1;
     }
     return md;
 }
@@ -342,9 +353,27 @@ EVP_MD *EVP_MD_meth_dup(const EVP_MD *md)
         memcpy(to, md, sizeof(*to));
     return to;
 }
+
+int EVP_MD_upref(EVP_MD *md)
+{
+    int ref = 0;
+
+    CRYPTO_UP_REF(&md->refcnt, &ref, md->lock);
+    return 1;
+}
+
 void EVP_MD_meth_free(EVP_MD *md)
 {
-    OPENSSL_free(md);
+    if (md != NULL) {
+        int i;
+
+        CRYPTO_DOWN_REF(&md->refcnt, &i, md->lock);
+        if (i > 0)
+            return;
+        ossl_provider_free(md->prov);
+        CRYPTO_THREAD_lock_free(md->lock);
+        OPENSSL_free(md);
+    }
 }
 int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize)
 {
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 82e7bf8..936824a 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -19,6 +19,10 @@ struct evp_md_ctx_st {
     EVP_PKEY_CTX *pctx;
     /* Update function: usually copied from EVP_MD */
     int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count);
+
+    /* Provider ctx */
+    void *provctx;
+    EVP_MD *fetched_digest;
 } /* EVP_MD_CTX */ ;
 
 struct evp_cipher_ctx_st {
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index f6f99ed..ab8ce00 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -8,6 +8,7 @@
  */
 
 #include <openssl/evp.h>
+#include <openssl/core_numbers.h>
 #include "internal/refcount.h"
 
 /*
@@ -172,7 +173,11 @@ extern const EVP_KDF_METHOD sshkdf_kdf_meth;
 extern const EVP_KDF_METHOD ss_kdf_meth;
 
 struct evp_md_st {
+    /* nid */
     int type;
+
+    /* Legacy structure members */
+    /* TODO(3.0): Remove these */
     int pkey_type;
     int md_size;
     unsigned long flags;
@@ -185,6 +190,21 @@ struct evp_md_st {
     int ctx_size;               /* how big does the ctx->md_data need to be */
     /* control function */
     int (*md_ctrl) (EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
+
+    /* New structure members */
+    /* TODO(3.0): Remove above comment when legacy has gone */
+    OSSL_PROVIDER *prov;
+    CRYPTO_REF_COUNT refcnt;
+    CRYPTO_RWLOCK *lock;
+    OSSL_OP_digest_newctx_fn *newctx;
+    OSSL_OP_digest_init_fn *dinit;
+    OSSL_OP_digest_update_fn *dupdate;
+    OSSL_OP_digest_final_fn *dfinal;
+    OSSL_OP_digest_digest_fn *digest;
+    OSSL_OP_digest_freectx_fn *freectx;
+    OSSL_OP_digest_dupctx_fn *dupctx;
+    OSSL_OP_digest_size_fn *size;
+
 } /* EVP_MD */ ;
 
 struct evp_cipher_st {
diff --git a/crypto/provider_predefined.c b/crypto/provider_predefined.c
index be21565..d14cd5b 100644
--- a/crypto/provider_predefined.c
+++ b/crypto/provider_predefined.c
@@ -10,13 +10,9 @@
 #include <openssl/core.h>
 #include "provider_local.h"
 
-#if 0                            /* Until it exists for real */
 OSSL_provider_init_fn ossl_default_provider_init;
-#endif
 
 const struct predefined_providers_st predefined_providers[] = {
-#if 0                            /* Until it exists for real */
     { "default", ossl_default_provider_init, 1 },
-#endif
     { NULL, NULL, 0 }
 };
diff --git a/doc/man3/EVP_MD_fetch.pod b/doc/man3/EVP_MD_fetch.pod
new file mode 100644
index 0000000..1748108
--- /dev/null
+++ b/doc/man3/EVP_MD_fetch.pod
@@ -0,0 +1,162 @@
+=pod
+
+=head1 NAME
+
+EVP_MD_fetch
+- Functions to explicitly fetch algorithm implementations
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                      const char *properties);
+
+=head1 DESCRIPTION
+
+The B<EVP_MD> object is used for representing a digest method implementation.
+
+Having obtained a digest implementation as an B<EVP_MD> type it can be used to
+calculate the digest of input data using functions such as
+L<EVP_DigestInit_ex(3)>, L<EVP_DigestUpdate(3)> and L<EVP_DigestFinal_ex(3)>.
+
+Digest implementations may be obtained in one of three ways, i.e. implicit
+lookup, explicit lookup or user defined.
+
+=over 4
+
+=item Implicit Lookup
+
+With implicit lookup an application can use functions such as L<EVP_sha256(3)>,
+L<EVP_sha512(3)> or L<EVP_blake2b512(3)> to obtain an B<EVP_MD> object. When
+used in a function like L<EVP_DigestInit_ex(3)> the actual implementation to
+be used will be fetched implicitly using default search criteria. Typically,
+(unless the default search criteria have been changed and/or different providers
+have been loaded), this will return an implementation of the appropriate
+algorithm from the default provider.
+
+=item Explicit Lookup
+
+With explicit lookup an application uses the EVP_MD_fetch() function to obtain
+an algorithm implementation. An implementation with the given name and
+satisfying the search criteria specified in the B<properties> parameter will be
+looked for within the available providers and returned. See L<OSSL_PROVIDER(3)>
+for information about providers.
+
+=item User defined
+
+Using the user defined approach an application constructs its own EVP_MD object.
+See L<EVP_MD_meth_new(3)> for details.
+
+=back
+
+The EVP_MD_fetch() function will look for an algorithm within the providers that
+have been loaded into the B<OPENSSL_CTX> given in the B<ctx> parameter. This
+parameter may be NULL in which case the default B<OPENSSL_CTX> will be used. See
+L<OPENSSL_CTX_new(3)> and L<OSSL_PROVIDER_load(3)> for further details.
+
+The B<algorithm> parameter gives the name of the algorithm to be looked up.
+Different algorithms can be made available by loading different providers. The
+built-in default provider algorithm implementation names are: SHA1, SHA224,
+SHA256, SHA384, SHA512, SHA512-224, SHA512-256,SHA3-224, SHA3-256, SHA3-384,
+SHA3-512, SHAKE128, SHAKE256, SM3, BLAKE2b512, BLAKE2s256 and MD5-SHA1.
+
+Additional algorithm implementations may be obtained by loading the "legacy"
+provider. The names of these algorithms are: RIPEMD160, MD2, MD4, MD5, MDC2 and
+whirlpool.
+
+The B<properties> parameter specifies the search criteria that will be used to
+look for an algorithm implementation. Properties are given as a comma delimited
+string of name value pairs. In order for an implementation to match, all the
+properties in the query string must match those defined for that implementation.
+Any properties defined by an implementation but not given in the query string
+are ignored. All algorithm implementations in the default provider have the
+property "default=yes". All algorithm implementations in the legacy provider have
+the property "legacy=yes". All algorithm implementations in the FIPS provider
+have the property "fips=yes". In the event that more than one implementation
+of the given algorithm name matches the specified properties then an unspecified
+one of those implementations may be returned. The B<properties> parameter may be
+NULL in which case any implementation from the available providers with the
+given algorithm name will be returned.
+
+The return value from a call to EVP_MD_fetch() must be freed by the caller using
+L<EVP_MD_meth_free(3)>. Note that EVP_MD objects are reference counted. See
+L<EVP_MD_upref(3)>.
+
+=head1 RETURN VALUES
+
+EVP_MD_fetch() returns a pointer to the algorithm implementation represented by
+an EVP_MD object, or NULL on error.
+
+=head1 EXAMPLES
+
+Fetch any available implementation of SHA256 in the default context:
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "SHA256", NULL);
+
+Fetch an implementation of SHA256 from the default provider in the default
+context:
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "SHA256", "default=yes");
+ ...
+ EVP_MD_meth_free(md);
+
+Fetch an implementation of SHA256 that is not from the default provider in the
+default context:
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "SHA256", "default=no");
+ ...
+ EVP_MD_meth_free(md);
+
+Fetch an implementation of SHA256 from the default provider in the specified
+context:
+
+ EVP_MD *md = EVP_MD_fetch(ctx, "SHA256", "default=yes");
+ ...
+ EVP_MD_meth_free(md);
+
+Load the legacy provider into the default context and then fetch an
+implementation of whirlpool from it:
+
+ /* This only needs to be done once - usually at application start up */
+ OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
+
+ EVP_MD *md = EVP_MD_fetch(NULL, "whirlpool", "legacy=yes");
+ ...
+ EVP_MD_meth_free(md);
+
+Note that in the above example the property string "legacy=yes" is optional
+since, assuming no other providers have been loaded, the only implmentation of
+the "whirlpool" algorithm is in the "legacy" provider. Also note that the
+default provider should be explicitly loaded if it is required in addition to
+other providers:
+
+ /* This only needs to be done once - usually at application start up */
+ OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy");
+ OSSL_PROVIDER *default = OSSL_PROVIDER_load(NULL, "default");
+
+ EVP_MD *md_whirlpool = EVP_MD_fetch(NULL, "whirlpool", NULL);
+ EVP_MD *md_sha256 = EVP_MD_fetch(NULL, "SHA256", NULL);
+ ...
+ EVP_MD_meth_free(md_whirlpool);
+ EVP_MD_meth_free(md_sha256);
+
+=head1 SEE ALSO
+
+L<EVP_DigestInit(3)>, L<EVP_MD_meth_new(3)>, L<EVP_MD_meth_free(3)>,
+L<EVP_MD_upref(3)>, L<OSSL_PROVIDER_load(3)>, L<OPENSSL_CTX(3)>
+
+=head1 HISTORY
+
+The functions described here were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man3/EVP_MD_meth_new.pod b/doc/man3/EVP_MD_meth_new.pod
index f4ac92d..6269a05 100644
--- a/doc/man3/EVP_MD_meth_new.pod
+++ b/doc/man3/EVP_MD_meth_new.pod
@@ -11,7 +11,7 @@ EVP_MD_meth_set_ctrl, EVP_MD_meth_get_input_blocksize,
 EVP_MD_meth_get_result_size, EVP_MD_meth_get_app_datasize,
 EVP_MD_meth_get_flags, EVP_MD_meth_get_init, EVP_MD_meth_get_update,
 EVP_MD_meth_get_final, EVP_MD_meth_get_copy, EVP_MD_meth_get_cleanup,
-EVP_MD_meth_get_ctrl
+EVP_MD_meth_get_ctrl, EVP_MD_upref
 - Routines to build up EVP_MD methods
 
 =head1 SYNOPSIS
@@ -54,17 +54,21 @@ EVP_MD_meth_get_ctrl
  int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
                                                int p1, void *p2);
 
+ int EVP_MD_upref(EVP_MD *md);
+
 =head1 DESCRIPTION
 
 The B<EVP_MD> type is a structure for digest method implementation.
 It can also have associated public/private key signing and verifying
 routines.
 
-EVP_MD_meth_new() creates a new B<EVP_MD> structure.
+EVP_MD_meth_new() creates a new B<EVP_MD> structure. Note that B<EVP_MD>
+structures are reference counted.
 
 EVP_MD_meth_dup() creates a copy of B<md>.
 
-EVP_MD_meth_free() destroys a B<EVP_MD> structure.
+EVP_MD_meth_free() decrements the reference count for the B<EVP_MD> structure.
+If the reference count drops to 0 then the structure is freed.
 
 EVP_MD_meth_set_input_blocksize() sets the internal input block size
 for the method B<md> to B<blocksize> bytes.
@@ -158,6 +162,8 @@ EVP_MD_meth_get_cleanup() and EVP_MD_meth_get_ctrl() are all used
 to retrieve the method data given with the EVP_MD_meth_set_*()
 functions above.
 
+EVP_MD_upref() increments the reference count for an EVP_MD structure.
+
 =head1 RETURN VALUES
 
 EVP_MD_meth_new() and EVP_MD_meth_dup() return a pointer to a newly
@@ -169,6 +175,8 @@ indicated sizes or flags.
 All other EVP_CIPHER_meth_get_*() functions return pointers to their
 respective B<md> function.
 
+EVP_MD_upref() returns 1 for success or 0 otherwise.
+
 =head1 SEE ALSO
 
 L<EVP_DigestInit(3)>, L<EVP_SignInit(3)>, L<EVP_VerifyInit(3)>
@@ -176,7 +184,8 @@ L<EVP_DigestInit(3)>, L<EVP_SignInit(3)>, L<EVP_VerifyInit(3)>
 =head1 HISTORY
 
 The B<EVP_MD> structure was openly available in OpenSSL before version
-1.1.  The functions described here were added in OpenSSL 1.1.
+1.1.  EVP_MD_upref() was added in OpenSSL 3.0. All other functions described
+here were added in OpenSSL 1.1.
 
 =head1 COPYRIGHT
 
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
new file mode 100644
index 0000000..be4a647
--- /dev/null
+++ b/include/openssl/core_names.h
@@ -0,0 +1,41 @@
+/*
+ * 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
+ */
+
+#ifndef OSSL_CORE_NAMES_H
+# define OSSL_CORE_NAMES_H
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/*
+ * Well known parameter names that Providers can define
+ */
+
+/*
+ * A printable name for this provider
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+#define OSSL_PROV_PARAM_NAME        "name"
+/*
+ * A version string for this provider
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+#define OSSL_PROV_PARAM_VERSION     "version"
+/*
+ * A string providing provider specific build information
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+#define OSSL_PROV_PARAM_BUILDINFO   "buildinfo"
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 7be2a2b..a723854 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -72,6 +72,32 @@ OSSL_CORE_MAKE_FUNC(const OSSL_ALGORITHM *,provider_query_operation,
                     (const OSSL_PROVIDER *, int operation_id,
                      const int *no_store))
 
+/* Digests */
+
+# define OSSL_OP_DIGEST                     1
+
+# define OSSL_FUNC_DIGEST_NEWCTX            1
+# define OSSL_FUNC_DIGEST_INIT              2
+# define OSSL_FUNC_DIGEST_UPDDATE           3
+# define OSSL_FUNC_DIGEST_FINAL             4
+# define OSSL_FUNC_DIGEST_DIGEST            5
+# define OSSL_FUNC_DIGEST_FREECTX           6
+# define OSSL_FUNC_DIGEST_DUPCTX            7
+# define OSSL_FUNC_DIGEST_SIZE              8
+
+OSSL_CORE_MAKE_FUNC(void *, OP_digest_newctx, (void))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_init, (void *vctx))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_update,
+                    (void *, const unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_final,
+                    (void *, unsigned char *out, size_t *outl))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_digest,
+                    (const unsigned char *in, size_t inl, unsigned char *out,
+                     size_t *out_l))
+OSSL_CORE_MAKE_FUNC(void, OP_digest_cleanctx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void, OP_digest_freectx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(void *, OP_digest_dupctx, (void *vctx))
+OSSL_CORE_MAKE_FUNC(size_t, OP_digest_size, (void))
 
 # ifdef __cplusplus
 }
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index ca7655d..db8eec1 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -77,6 +77,7 @@ extern "C" {
 # ifndef EVP_MD
 EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type);
 EVP_MD *EVP_MD_meth_dup(const EVP_MD *md);
+int EVP_MD_upref(EVP_MD *md);
 void EVP_MD_meth_free(EVP_MD *md);
 
 int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize);
@@ -561,6 +562,9 @@ __owur int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md,
 __owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md,
                               size_t len);
 
+__owur EVP_MD *EVP_MD_fetch(OPENSSL_CTX *ctx, const char *algorithm,
+                            const char *properties);
+
 int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify);
 int EVP_read_pw_string_min(char *buf, int minlen, int maxlen,
                            const char *prompt, int verify);
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index 445d173..598930a 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -55,7 +55,9 @@ int ERR_load_EVP_strings(void);
 # define EVP_F_EVP_DECRYPTFINAL_EX                        101
 # define EVP_F_EVP_DECRYPTUPDATE                          166
 # define EVP_F_EVP_DIGESTFINALXOF                         174
+# define EVP_F_EVP_DIGESTFINAL_EX                         230
 # define EVP_F_EVP_DIGESTINIT_EX                          128
+# define EVP_F_EVP_DIGESTUPDATE                           231
 # define EVP_F_EVP_ENCRYPTDECRYPTUPDATE                   219
 # define EVP_F_EVP_ENCRYPTFINAL_EX                        127
 # define EVP_F_EVP_ENCRYPTUPDATE                          167
@@ -170,6 +172,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_EXPECTING_A_EC_KEY                         142
 # define EVP_R_EXPECTING_A_POLY1305_KEY                   164
 # define EVP_R_EXPECTING_A_SIPHASH_KEY                    175
+# define EVP_R_FINAL_ERROR                                188
 # define EVP_R_FIPS_MODE_NOT_SUPPORTED                    167
 # define EVP_R_GET_RAW_KEY_FAILED                         182
 # define EVP_R_ILLEGAL_SCRYPT_PARAMETERS                  171
@@ -188,6 +191,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_MESSAGE_DIGEST_IS_NULL                     159
 # define EVP_R_METHOD_NOT_SUPPORTED                       144
 # define EVP_R_MISSING_PARAMETERS                         103
+# define EVP_R_NOT_ABLE_TO_COPY_CTX                       190
 # define EVP_R_NOT_XOF_OR_INVALID_LENGTH                  178
 # define EVP_R_NO_CIPHER_SET                              131
 # define EVP_R_NO_DEFAULT_DIGEST                          158
@@ -218,6 +222,7 @@ int ERR_load_EVP_strings(void);
 # define EVP_R_UNSUPPORTED_PRF                            125
 # define EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM          118
 # define EVP_R_UNSUPPORTED_SALT_TYPE                      126
+# define EVP_R_UPDATE_ERROR                               189
 # define EVP_R_WRAP_MODE_NOT_ALLOWED                      170
 # define EVP_R_WRONG_FINAL_BLOCK_LENGTH                   109
 
diff --git a/providers/build.info b/providers/build.info
new file mode 100644
index 0000000..ec4162b
--- /dev/null
+++ b/providers/build.info
@@ -0,0 +1 @@
+SUBDIRS=common default
diff --git a/providers/common/build.info b/providers/common/build.info
new file mode 100644
index 0000000..5cb7e43
--- /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 0000000..a3c2369
--- /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 0000000..b538ab9
--- /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/crypto/sm4/build.info b/providers/default/build.info
similarity index 70%
copy from crypto/sm4/build.info
copy to providers/default/build.info
index b65a7d1..eab90a3 100644
--- a/crypto/sm4/build.info
+++ b/providers/default/build.info
@@ -1,4 +1,3 @@
 LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
-        sm4.c
-
+        defltprov.c
diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c
new file mode 100644
index 0000000..9b52429
--- /dev/null
+++ b/providers/default/defltprov.c
@@ -0,0 +1,101 @@
+/*
+ * 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 <string.h>
+#include <stdio.h>
+#include <openssl/core.h>
+#include <openssl/core_numbers.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+
+/* Functions provided by the core */
+static OSSL_core_get_param_types_fn *c_get_param_types = NULL;
+static OSSL_core_get_params_fn *c_get_params = NULL;
+
+/* Parameters we provide to the core */
+static const OSSL_ITEM deflt_param_types[] = {
+    { OSSL_PARAM_UTF8_PTR, OSSL_PROV_PARAM_NAME },
+    { OSSL_PARAM_UTF8_PTR, OSSL_PROV_PARAM_VERSION },
+    { OSSL_PARAM_UTF8_PTR, OSSL_PROV_PARAM_BUILDINFO },
+    { 0, NULL }
+};
+
+static const OSSL_ITEM *deflt_get_param_types(const OSSL_PROVIDER *prov)
+{
+    return deflt_param_types;
+}
+
+static int deflt_get_params(const OSSL_PROVIDER *prov,
+                            const OSSL_PARAM params[])
+{
+    const OSSL_PARAM *p;
+
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, "OpenSSL Default Provider"))
+        return 0;
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_VERSION_STR))
+        return 0;
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
+    if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, OPENSSL_FULL_VERSION_STR))
+        return 0;
+
+    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 }
+};
+
+OSSL_provider_init_fn ossl_default_provider_init;
+
+int ossl_default_provider_init(const OSSL_PROVIDER *provider,
+                               const OSSL_DISPATCH *in,
+                               const OSSL_DISPATCH **out)
+{
+    for (; in->function_id != 0; in++) {
+        switch (in->function_id) {
+        case OSSL_FUNC_CORE_GET_PARAM_TYPES:
+            c_get_param_types = OSSL_get_core_get_param_types(in);
+            break;
+        case OSSL_FUNC_CORE_GET_PARAMS:
+            c_get_params = OSSL_get_core_get_params(in);
+            break;
+        default:
+            /* Just ignore anything we don't understand */
+            break;
+        }
+    }
+
+    *out = deflt_dispatch_table;
+    return 1;
+}
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index eac0c43..f68b013 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -18,6 +18,7 @@
 #include <openssl/x509.h>
 #include <openssl/pem.h>
 #include <openssl/kdf.h>
+#include <openssl/provider.h>
 #include "testutil.h"
 #include "internal/nelem.h"
 #include "internal/evp_int.h"
@@ -1009,6 +1010,106 @@ done:
 }
 #endif
 
+
+static int calculate_digest(const EVP_MD *md, const char *msg, size_t len,
+                            const unsigned char *exptd)
+{
+    unsigned char out[SHA256_DIGEST_LENGTH];
+    EVP_MD_CTX *ctx;
+    int ret = 0;
+
+    if (!TEST_ptr(ctx = EVP_MD_CTX_new())
+            || !TEST_true(EVP_DigestInit_ex(ctx, md, NULL))
+            || !TEST_true(EVP_DigestUpdate(ctx, msg, len))
+            || !TEST_true(EVP_DigestFinal_ex(ctx, out, NULL))
+            || !TEST_mem_eq(out, SHA256_DIGEST_LENGTH, exptd,
+                            SHA256_DIGEST_LENGTH))
+        goto err;
+
+    ret = 1;
+ err:
+    EVP_MD_CTX_free(ctx);
+    return ret;
+}
+/*
+ * Test EVP_MD_fetch()
+ *
+ * Test 0: Test with the default OPENSSL_CTX
+ * Test 1: Test with an explicit OPENSSL_CTX
+ * Test 2: Explicit OPENSSL_CTX with explicit load of default provider
+ */
+static int test_EVP_MD_fetch(int tst)
+{
+    OPENSSL_CTX *ctx = NULL;
+    EVP_MD *md = NULL;
+    OSSL_PROVIDER *prov = NULL;
+    int ret = 0;
+    const char testmsg[] = "Hello world";
+    const unsigned char exptd[] = {
+      0x27, 0x51, 0x8b, 0xa9, 0x68, 0x30, 0x11, 0xf6, 0xb3, 0x96, 0x07, 0x2c,
+      0x05, 0xf6, 0x65, 0x6d, 0x04, 0xf5, 0xfb, 0xc3, 0x78, 0x7c, 0xf9, 0x24,
+      0x90, 0xec, 0x60, 0x6e, 0x50, 0x92, 0xe3, 0x26
+    };
+
+    if (tst > 0) {
+        ctx = OPENSSL_CTX_new();
+        if (!TEST_ptr(ctx))
+            goto err;
+
+        if (tst == 2) {
+            prov = OSSL_PROVIDER_load(ctx, "default");
+            if (!TEST_ptr(prov))
+                goto err;
+        }
+    }
+
+    /* Implicit fetching of the MD should produce the expected result */
+    if (!TEST_true(calculate_digest(EVP_sha256(), testmsg, sizeof(testmsg),
+                                    exptd)))
+        goto err;
+    /*
+     * Test that without loading any providers or specifying any properties we
+     * can get a sha256 md from the default provider.
+     */
+    if (!TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", NULL))
+            || !TEST_ptr(md)
+            || !TEST_int_eq(EVP_MD_nid(md), NID_sha256)
+            || !TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd)))
+        goto err;
+
+    /* Also test EVP_MD_upref() while we're doing this */
+    if (!TEST_true(EVP_MD_upref(md)))
+        goto err;
+    /* Ref count should now be 2. Release both */
+    EVP_MD_meth_free(md);
+    EVP_MD_meth_free(md);
+    md = NULL;
+
+    /*
+     * We've only loaded the default provider so explicitly asking for a
+     * non-default implementation should fail.
+     */
+    if (!TEST_ptr_null(md = EVP_MD_fetch(ctx, "SHA256", "default=no")))
+        goto err;
+
+    /* Explicitly asking for the default implementation should succeeed */
+    if (!TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", "default=yes"))
+            || !TEST_int_eq(EVP_MD_nid(md), NID_sha256)
+            || !TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd)))
+        goto err;
+
+    EVP_MD_meth_free(md);
+    md = NULL;
+
+    ret = 1;
+
+ err:
+    EVP_MD_meth_free(md);
+    OSSL_PROVIDER_unload(prov);
+    OPENSSL_CTX_free(ctx);
+    return ret;
+}
+
 int setup_tests(void)
 {
     ADD_TEST(test_EVP_DigestSignInit);
@@ -1036,5 +1137,6 @@ int setup_tests(void)
 #ifndef OPENSSL_NO_EC
     ADD_TEST(test_X509_PUBKEY_inplace);
 #endif
+    ADD_ALL_TESTS(test_EVP_MD_fetch, 3);
     return 1;
 }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index bf14bbd..5b488d0 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4791,3 +4791,5 @@ OSSL_PARAM_set_octet_ptr                4738	3_0_0	EXIST::FUNCTION:
 X509_set_sm2_id                         4739	3_0_0	EXIST::FUNCTION:SM2
 X509_get0_sm2_id                        4740	3_0_0	EXIST::FUNCTION:SM2
 EVP_PKEY_get0_engine                    4741	3_0_0	EXIST::FUNCTION:ENGINE
+EVP_MD_upref                            4742	3_0_0	EXIST::FUNCTION:
+EVP_MD_fetch                            4743	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list