summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2019-03-13 14:49:40 +0000
committerMatt Caswell <matt@openssl.org>2019-03-21 09:23:38 +0000
commit3653d0c224593ef55830c2fb17941aba9ea26ea8 (patch)
tree0353f4795a70a3f4fd07566172bc6210ae1959f3
parent8a73348be02fabc367c375dd3c543753649b2a58 (diff)
Implement EVP_MD_fetch()
Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from https://github.com/openssl/openssl/pull/8513)
-rw-r--r--crypto/evp/digest.c92
-rw-r--r--crypto/evp/evp_lib.c27
-rw-r--r--crypto/include/internal/evp_int.h18
-rw-r--r--include/openssl/core_numbers.h22
-rw-r--r--include/openssl/evp.h4
-rw-r--r--util/libcrypto.num2
6 files changed, 164 insertions, 1 deletions
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 86be9aec57..08b5198f04 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 */
@@ -296,3 +297,94 @@ 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;
+
+ if ((md = EVP_MD_meth_new(mdtype, NID_undef)) == NULL)
+ return NULL;
+
+ for (; fns->function_id != 0; fns++) {
+ int fncnt = 0;
+
+ 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_CLEANCTX:
+ if (md->cleanctx != NULL)
+ break;
+ md->cleanctx = OSSL_get_OP_digest_cleanctx(fns);
+ fncnt++;
+ break;
+ case OSSL_FUNC_DIGEST_FREECTX:
+ if (md->freectx != NULL)
+ break;
+ md->freectx = OSSL_get_OP_digest_freectx(fns);
+ fncnt++;
+ break;
+ }
+ if ((fncnt != 0 && fncnt != 6) || (fncnt == 0 && md->digest == 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_lib.c b/crypto/evp/evp_lib.c
index f0ee6ab663..ed95dd5eec 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)
@@ -331,6 +332,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 +349,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/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index f6f99edb14..ba0eedd46b 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,19 @@ 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;
+
} /* EVP_MD */ ;
struct evp_cipher_st {
diff --git a/include/openssl/core_numbers.h b/include/openssl/core_numbers.h
index 7be2a2bb75..9bce619e99 100644
--- a/include/openssl/core_numbers.h
+++ b/include/openssl/core_numbers.h
@@ -72,6 +72,28 @@ 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
+
+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 *vctx, unsigned char *in, size_t inl))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_final,
+ (void *vctx, unsigned char *out, size_t *outl))
+OSSL_CORE_MAKE_FUNC(int, OP_digest_digest,
+ (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))
# ifdef __cplusplus
}
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index ca7655d5e4..db8eec12f2 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/util/libcrypto.num b/util/libcrypto.num
index bf14bbd28d..5b488d0e4d 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: