[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