summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2019-05-07 12:39:58 +0200
committerRichard Levitte <levitte@openssl.org>2019-08-15 22:12:25 +0200
commite74bd29053a543ab4908ae8545b46f2e38c98bab (patch)
treeee0d540bd5f8319549c1ab0d4b356f8b166d021e /crypto
parent3ded2288a45d2cc3a27a1b08d29499cbcec52c0e (diff)
Prepare EVP_MAC infrastructure for moving all MACs to providers
Quite a few adaptations are needed, most prominently the added code to allow provider based MACs. As part of this, all the old information functions are gone, except for EVP_MAC_name(). Some of them will reappear later, for example EVP_MAC_do_all() in some form. MACs by EVP_PKEY was particularly difficult to deal with, as they need to allocate and deallocate EVP_MAC_CTXs "under the hood", and thereby implicitly fetch the corresponding EVP_MAC. This means that EVP_MACs can't be constant in a EVP_MAC_CTX, as their reference count may need to be incremented and decremented as part of the allocation or deallocation of the EVP_MAC_CTX. It may be that other provider based EVP operation types may need to be handled in a similar manner. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/8877)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/cmac/cm_ameth.c3
-rw-r--r--crypto/evp/build.info2
-rw-r--r--crypto/evp/evp_locl.h2
-rw-r--r--crypto/evp/mac_lib.c162
-rw-r--r--crypto/evp/mac_meth.c195
-rw-r--r--crypto/evp/p_lib.c32
-rw-r--r--crypto/evp/pkey_mac.c186
-rw-r--r--crypto/include/internal/evp_int.h40
-rw-r--r--crypto/provider_core.c7
9 files changed, 464 insertions, 165 deletions
diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c
index ed513b113f..b1ee0d3d2f 100644
--- a/crypto/cmac/cm_ameth.c
+++ b/crypto/cmac/cm_ameth.c
@@ -25,7 +25,10 @@ static int cmac_size(const EVP_PKEY *pkey)
static void cmac_key_free(EVP_PKEY *pkey)
{
EVP_MAC_CTX *cmctx = EVP_PKEY_get0(pkey);
+ EVP_MAC *mac = cmctx == NULL ? NULL : EVP_MAC_CTX_mac(cmctx);
+
EVP_MAC_CTX_free(cmctx);
+ EVP_MAC_free(mac);
}
const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = {
diff --git a/crypto/evp/build.info b/crypto/evp/build.info
index c650c28882..eb675f3f97 100644
--- a/crypto/evp/build.info
+++ b/crypto/evp/build.info
@@ -16,7 +16,7 @@ SOURCE[../../libcrypto]=$COMMON\
e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \
e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \
e_chacha20_poly1305.c \
- mac_lib.c c_allm.c pkey_mac.c exchange.c
+ mac_lib.c mac_meth.c c_allm.c pkey_mac.c exchange.c
SOURCE[../../providers/fips]=$COMMON
INCLUDE[e_aes.o]=.. ../modes
diff --git a/crypto/evp/evp_locl.h b/crypto/evp/evp_locl.h
index 59072e368b..3fd73212a4 100644
--- a/crypto/evp/evp_locl.h
+++ b/crypto/evp/evp_locl.h
@@ -56,7 +56,7 @@ struct evp_cipher_ctx_st {
} /* EVP_CIPHER_CTX */ ;
struct evp_mac_ctx_st {
- const EVP_MAC *meth; /* Method structure */
+ EVP_MAC *meth; /* Method structure */
void *data; /* Individual method data */
} /* EVP_MAC_CTX */;
diff --git a/crypto/evp/mac_lib.c b/crypto/evp/mac_lib.c
index ee4a68f459..7b07b55e3d 100644
--- a/crypto/evp/mac_lib.c
+++ b/crypto/evp/mac_lib.c
@@ -11,26 +11,24 @@
#include <stdarg.h>
#include <openssl/evp.h>
#include <openssl/err.h>
+#include <openssl/core.h>
+#include <openssl/core_names.h>
#include <openssl/ossl_typ.h>
#include "internal/nelem.h"
#include "internal/evp_int.h"
+#include "internal/provider.h"
#include "evp_locl.h"
-EVP_MAC_CTX *EVP_MAC_CTX_new_id(int id)
-{
- const EVP_MAC *mac = EVP_get_macbynid(id);
-
- if (mac == NULL)
- return NULL;
- return EVP_MAC_CTX_new(mac);
-}
-
-EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac)
+EVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac)
{
EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX));
- if (ctx == NULL || (ctx->data = mac->new()) == NULL) {
+ if (ctx == NULL
+ || (ctx->data = mac->newctx(ossl_provider_ctx(mac->prov))) == NULL
+ || !EVP_MAC_up_ref(mac)) {
EVPerr(EVP_F_EVP_MAC_CTX_NEW, ERR_R_MALLOC_FAILURE);
+ if (ctx != NULL)
+ mac->freectx(ctx->data);
OPENSSL_free(ctx);
ctx = NULL;
} else {
@@ -41,9 +39,11 @@ EVP_MAC_CTX *EVP_MAC_CTX_new(const EVP_MAC *mac)
void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx)
{
- if (ctx != NULL && ctx->data != NULL) {
- ctx->meth->free(ctx->data);
+ if (ctx != NULL) {
+ ctx->meth->freectx(ctx->data);
ctx->data = NULL;
+ /* refcnt-- */
+ EVP_MAC_free(ctx->meth);
}
OPENSSL_free(ctx);
}
@@ -62,8 +62,13 @@ EVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src)
}
*dst = *src;
+ if (!EVP_MAC_up_ref(dst->meth)) {
+ EVPerr(EVP_F_EVP_MAC_CTX_DUP, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(dst);
+ return NULL;
+ }
- dst->data = src->meth->dup(src->data);
+ dst->data = src->meth->dupctx(src->data);
if (dst->data == NULL) {
EVP_MAC_CTX_free(dst);
return NULL;
@@ -72,16 +77,31 @@ EVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src)
return dst;
}
-const EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx)
+EVP_MAC *EVP_MAC_CTX_mac(EVP_MAC_CTX *ctx)
{
return ctx->meth;
}
size_t EVP_MAC_size(EVP_MAC_CTX *ctx)
{
- if (ctx->data != NULL)
- return ctx->meth->size(ctx->data);
- /* If the MAC hasn't been initialized yet, we return zero */
+ size_t sz = 0;
+
+ if (ctx->data != NULL) {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+
+ params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN, &sz);
+ if (ctx->meth->ctx_get_params != NULL) {
+ if (ctx->meth->ctx_get_params(ctx->data, params))
+ return sz;
+ } else if (ctx->meth->get_params != NULL) {
+ if (ctx->meth->get_params(params))
+ return sz;
+ }
+ }
+ /*
+ * If the MAC hasn't been initialized yet, or there is no size to get,
+ * we return zero
+ */
return 0;
}
@@ -97,101 +117,43 @@ int EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen)
return ctx->meth->update(ctx->data, data, datalen);
}
-int EVP_MAC_final(EVP_MAC_CTX *ctx, unsigned char *out, size_t *poutlen)
+int EVP_MAC_final(EVP_MAC_CTX *ctx,
+ unsigned char *out, size_t *outl, size_t outsize)
{
- int l = ctx->meth->size(ctx->data);
+ int l = EVP_MAC_size(ctx);
if (l < 0)
return 0;
- if (poutlen != NULL)
- *poutlen = l;
+ if (outl != NULL)
+ *outl = l;
if (out == NULL)
return 1;
- return ctx->meth->final(ctx->data, out);
-}
-
-int EVP_MAC_ctrl(EVP_MAC_CTX *ctx, int cmd, ...)
-{
- int ok = -1;
- va_list args;
-
- va_start(args, cmd);
- ok = EVP_MAC_vctrl(ctx, cmd, args);
- va_end(args);
-
- if (ok == -2)
- EVPerr(EVP_F_EVP_MAC_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
-
- return ok;
-}
-
-int EVP_MAC_vctrl(EVP_MAC_CTX *ctx, int cmd, va_list args)
-{
- int ok = 1;
-
- if (ctx == NULL || ctx->meth == NULL)
- return -2;
-
- switch (cmd) {
-#if 0
- case ...:
- /* code */
- ok = 1;
- break;
-#endif
- default:
- if (ctx->meth->ctrl != NULL)
- ok = ctx->meth->ctrl(ctx->data, cmd, args);
- else
- ok = -2;
- break;
- }
-
- return ok;
-}
-
-int EVP_MAC_ctrl_str(EVP_MAC_CTX *ctx, const char *type, const char *value)
-{
- int ok = 1;
-
- if (ctx == NULL || ctx->meth == NULL || ctx->meth->ctrl_str == NULL) {
- EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
- return -2;
- }
-
- ok = ctx->meth->ctrl_str(ctx->data, type, value);
-
- if (ok == -2)
- EVPerr(EVP_F_EVP_MAC_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED);
- return ok;
+ return ctx->meth->final(ctx->data, out, outl, outsize);
}
-int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value)
+/*
+ * The {get,set}_params functions return 1 if there is no corresponding
+ * function in the implementation. This is the same as if there was one,
+ * but it didn't recognise any of the given params, i.e. nothing in the
+ * bag of parameters was useful.
+ */
+int EVP_MAC_get_params(EVP_MAC *mac, OSSL_PARAM params[])
{
- size_t len;
-
- len = strlen(value);
- if (len > INT_MAX)
- return -1;
- return EVP_MAC_ctrl(ctx, cmd, value, len);
+ if (mac->get_params != NULL)
+ return mac->get_params(params);
+ return 1;
}
-int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *hex)
+int EVP_MAC_CTX_get_params(EVP_MAC_CTX *ctx, OSSL_PARAM params[])
{
- unsigned char *bin;
- long binlen;
- int rv = -1;
-
- bin = OPENSSL_hexstr2buf(hex, &binlen);
- if (bin == NULL)
- return 0;
- if (binlen <= INT_MAX)
- rv = EVP_MAC_ctrl(ctx, cmd, bin, (size_t)binlen);
- OPENSSL_free(bin);
- return rv;
+ if (ctx->meth->ctx_get_params != NULL)
+ return ctx->meth->ctx_get_params(ctx->data, params);
+ return 1;
}
-int EVP_MAC_nid(const EVP_MAC *mac)
+int EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[])
{
- return mac->type;
+ if (ctx->meth->ctx_set_params != NULL)
+ return ctx->meth->ctx_set_params(ctx->data, params);
+ return 1;
}
diff --git a/crypto/evp/mac_meth.c b/crypto/evp/mac_meth.c
new file mode 100644
index 0000000000..983b2dbd2e
--- /dev/null
+++ b/crypto/evp/mac_meth.c
@@ -0,0 +1,195 @@
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/core.h>
+#include <openssl/core_numbers.h>
+#include "internal/evp_int.h"
+#include "internal/provider.h"
+#include "evp_locl.h"
+
+static int evp_mac_up_ref(void *vmac)
+{
+ EVP_MAC *mac = vmac;
+ int ref = 0;
+
+ CRYPTO_UP_REF(&mac->refcnt, &ref, mac->lock);
+ return 1;
+}
+
+static void evp_mac_free(void *vmac)
+{
+ EVP_MAC *mac = vmac;
+ int ref = 0;
+
+ if (mac == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&mac->refcnt, &ref, mac->lock);
+ if (ref > 0)
+ return;
+ ossl_provider_free(mac->prov);
+ OPENSSL_free(mac->name);
+ CRYPTO_THREAD_lock_free(mac->lock);
+ OPENSSL_free(mac);
+}
+
+static void *evp_mac_new(void)
+{
+ EVP_MAC *mac = NULL;
+
+ if ((mac = OPENSSL_zalloc(sizeof(*mac))) == NULL
+ || (mac->lock = CRYPTO_THREAD_lock_new()) == NULL) {
+ evp_mac_free(mac);
+ return NULL;
+ }
+
+ mac->refcnt = 1;
+
+ return mac;
+}
+
+static void *evp_mac_from_dispatch(const char *name, const OSSL_DISPATCH *fns,
+ OSSL_PROVIDER *prov)
+{
+ EVP_MAC *mac = NULL;
+ int fnmaccnt = 0, fnctxcnt = 0;
+
+ if ((mac = evp_mac_new()) == NULL
+ || (mac->name = OPENSSL_strdup(name)) == NULL) {
+ EVP_MAC_free(mac);
+ EVPerr(0, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ for (; fns->function_id != 0; fns++) {
+ switch (fns->function_id) {
+ case OSSL_FUNC_MAC_NEWCTX:
+ if (mac->newctx != NULL)
+ break;
+ mac->newctx = OSSL_get_OP_mac_newctx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_MAC_DUPCTX:
+ if (mac->dupctx != NULL)
+ break;
+ mac->dupctx = OSSL_get_OP_mac_dupctx(fns);
+ break;
+ case OSSL_FUNC_MAC_FREECTX:
+ if (mac->freectx != NULL)
+ break;
+ mac->freectx = OSSL_get_OP_mac_freectx(fns);
+ fnctxcnt++;
+ break;
+ case OSSL_FUNC_MAC_INIT:
+ if (mac->init != NULL)
+ break;
+ mac->init = OSSL_get_OP_mac_init(fns);
+ fnmaccnt++;
+ break;
+ case OSSL_FUNC_MAC_UPDATE:
+ if (mac->update != NULL)
+ break;
+ mac->update = OSSL_get_OP_mac_update(fns);
+ fnmaccnt++;
+ break;
+ case OSSL_FUNC_MAC_FINAL:
+ if (mac->final != NULL)
+ break;
+ mac->final = OSSL_get_OP_mac_final(fns);
+ fnmaccnt++;
+ break;
+ case OSSL_FUNC_MAC_GETTABLE_PARAMS:
+ if (mac->gettable_params != NULL)
+ break;
+ mac->gettable_params =
+ OSSL_get_OP_mac_gettable_params(fns);
+ break;
+ case OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS:
+ if (mac->gettable_ctx_params != NULL)
+ break;
+ mac->gettable_ctx_params =
+ OSSL_get_OP_mac_gettable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS:
+ if (mac->settable_ctx_params != NULL)
+ break;
+ mac->settable_ctx_params =
+ OSSL_get_OP_mac_settable_ctx_params(fns);
+ break;
+ case OSSL_FUNC_MAC_GET_PARAMS:
+ if (mac->get_params != NULL)
+ break;
+ mac->get_params = OSSL_get_OP_mac_get_params(fns);
+ break;
+ case OSSL_FUNC_MAC_CTX_GET_PARAMS:
+ if (mac->ctx_get_params != NULL)
+ break;
+ mac->ctx_get_params = OSSL_get_OP_mac_ctx_get_params(fns);
+ break;
+ case OSSL_FUNC_MAC_CTX_SET_PARAMS:
+ if (mac->ctx_set_params != NULL)
+ break;
+ mac->ctx_set_params = OSSL_get_OP_mac_ctx_set_params(fns);
+ break;
+ }
+ }
+ if (fnmaccnt != 3
+ || fnctxcnt != 2) {
+ /*
+ * In order to be a consistent set of functions we must have at least
+ * a complete set of "mac" functions, and a complete set of context
+ * management functions, as well as the size function.
+ */
+ evp_mac_free(mac);
+ ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
+ return NULL;
+ }
+ mac->prov = prov;
+ if (prov != NULL)
+ ossl_provider_up_ref(prov);
+
+ return mac;
+}
+
+EVP_MAC *EVP_MAC_fetch(OPENSSL_CTX *libctx, const char *algorithm,
+ const char *properties)
+{
+ return evp_generic_fetch(libctx, OSSL_OP_MAC, algorithm, properties,
+ evp_mac_from_dispatch, evp_mac_up_ref,
+ evp_mac_free);
+}
+
+int EVP_MAC_up_ref(EVP_MAC *mac)
+{
+ return evp_mac_up_ref(mac);
+}
+
+void EVP_MAC_free(EVP_MAC *mac)
+{
+ evp_mac_free(mac);
+}
+
+const char *EVP_MAC_name(const EVP_MAC *mac)
+{
+ return mac->name;
+}
+
+const OSSL_PARAM *EVP_MAC_gettable_params(const EVP_MAC *mac)
+{
+ if (mac->gettable_params == NULL)
+ return NULL;
+ return mac->gettable_params();
+}
+
+const OSSL_PARAM *EVP_MAC_CTX_gettable_params(const EVP_MAC *mac)
+{
+ if (mac->gettable_ctx_params == NULL)
+ return NULL;
+ return mac->gettable_ctx_params();
+}
+
+const OSSL_PARAM *EVP_MAC_CTX_settable_params(const EVP_MAC *mac)
+{
+ if (mac->settable_ctx_params == NULL)
+ return NULL;
+ return mac->settable_ctx_params();
+}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 653693e1dc..90e13f4854 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -20,9 +20,12 @@
#include <openssl/dh.h>
#include <openssl/cmac.h>
#include <openssl/engine.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
+#include "internal/provider.h"
static void EVP_PKEY_free_it(EVP_PKEY *x);
@@ -318,8 +321,16 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t len, const EVP_CIPHER *cipher)
{
#ifndef OPENSSL_NO_CMAC
+ const char *engine_name = e != NULL ? ENGINE_get_name(e) : NULL;
+ const char *cipher_name = EVP_CIPHER_name(cipher);
+ const OSSL_PROVIDER *prov = EVP_CIPHER_provider(cipher);
+ OPENSSL_CTX *libctx =
+ prov == NULL ? NULL : ossl_provider_library_context(prov);
EVP_PKEY *ret = EVP_PKEY_new();
- EVP_MAC_CTX *cmctx = EVP_MAC_CTX_new_id(EVP_MAC_CMAC);
+ EVP_MAC *cmac = EVP_MAC_fetch(libctx, "CMAC", NULL);
+ EVP_MAC_CTX *cmctx = cmac != NULL ? EVP_MAC_CTX_new(cmac) : NULL;
+ OSSL_PARAM params[4];
+ size_t paramsn = 0;
if (ret == NULL
|| cmctx == NULL
@@ -328,9 +339,21 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
goto err;
}
- if (EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_ENGINE, e) <= 0
- || EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_CIPHER, cipher) <= 0
- || EVP_MAC_ctrl(cmctx, EVP_MAC_CTRL_SET_KEY, priv, len) <= 0) {
+ if (engine_name != NULL)
+ params[paramsn++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
+ (char *)engine_name,
+ strlen(engine_name) + 1);
+ params[paramsn++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
+ (char *)cipher_name,
+ strlen(cipher_name) + 1);
+ params[paramsn++] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *)priv, len);
+ params[paramsn] = OSSL_PARAM_construct_end();
+
+ if (!EVP_MAC_CTX_set_params(cmctx, params)) {
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
goto err;
}
@@ -341,6 +364,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
err:
EVP_PKEY_free(ret);
EVP_MAC_CTX_free(cmctx);
+ EVP_MAC_free(cmac);
return NULL;
#else
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
diff --git a/crypto/evp/pkey_mac.c b/crypto/evp/pkey_mac.c
index fafe3c96f2..07421183ea 100644
--- a/crypto/evp/pkey_mac.c
+++ b/crypto/evp/pkey_mac.c
@@ -7,8 +7,12 @@
* https://www.openssl.org/source/license.html
*/
+#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
+#include <openssl/engine.h>
+#include <openssl/params.h>
+#include <openssl/core_names.h>
#include "internal/evp_int.h"
#include "evp_locl.h"
@@ -40,18 +44,21 @@ typedef struct {
} raw_data;
} MAC_PKEY_CTX;
+static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
+
static int pkey_mac_init(EVP_PKEY_CTX *ctx)
{
MAC_PKEY_CTX *hctx;
+ /* We're being smart and using the same base NIDs for PKEY and for MAC */
int nid = ctx->pmeth->pkey_id;
+ EVP_MAC *mac = EVP_MAC_fetch(NULL, OBJ_nid2sn(nid), NULL);
if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
- /* We're being smart and using the same base NIDs for PKEY and for MAC */
- hctx->ctx = EVP_MAC_CTX_new_id(nid);
+ hctx->ctx = EVP_MAC_CTX_new(mac);
if (hctx->ctx == NULL) {
OPENSSL_free(hctx);
return 0;
@@ -64,14 +71,13 @@ static int pkey_mac_init(EVP_PKEY_CTX *ctx)
hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING;
}
+ pkey_mac_cleanup(ctx);
EVP_PKEY_CTX_set_data(ctx, hctx);
ctx->keygen_info_count = 0;
return 1;
}
-static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
-
static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
{
MAC_PKEY_CTX *sctx, *dctx;
@@ -93,6 +99,17 @@ static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
if (dctx->ctx == NULL)
goto err;
+ /*
+ * Normally, nothing special would be done with the MAC method. In
+ * this particular case, though, the MAC method was fetched internally
+ * by pkey_mac_init() above or by EVP_PKEY_new_CMAC_key() and passed
+ * via the EVP_MAC_CTX, so it is effectively like every new EVP_MAC_CTX
+ * fetches the MAC method anew in this case. Therefore, its reference
+ * count must be adjusted here.
+ */
+ if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(dctx->ctx)))
+ goto err;
+
dctx->type = sctx->type;
switch (dctx->type) {
@@ -117,9 +134,16 @@ static int pkey_mac_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
{
- MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+ /*
+ * For the exact same reasons the MAC reference count is incremented
+ * in pkey_mac_copy() above, it must be explicitly freed here.
+ */
+
+ MAC_PKEY_CTX *hctx = ctx == NULL ? NULL : EVP_PKEY_CTX_get_data(ctx);
if (hctx != NULL) {
+ EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
+
switch (hctx->type) {
case MAC_TYPE_RAW:
OPENSSL_clear_free(hctx->raw_data.ktmp.data,
@@ -127,6 +151,7 @@ static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
break;
}
EVP_MAC_CTX_free(hctx->ctx);
+ EVP_MAC_free(mac);
OPENSSL_free(hctx);
EVP_PKEY_CTX_set_data(ctx, NULL);
}
@@ -156,6 +181,8 @@ static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
if (cmkey == NULL)
return 0;
+ if (!EVP_MAC_up_ref(EVP_MAC_CTX_mac(hctx->ctx)))
+ return 0;
EVP_PKEY_assign(pkey, nid, cmkey);
}
break;
@@ -194,25 +221,34 @@ static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
&& (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
if (set_key) {
- if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))
- != EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx)))
+ if (strcmp(OBJ_nid2sn(EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))),
+ EVP_MAC_name(EVP_MAC_CTX_mac(hctx->ctx))) != 0)
return 0;
key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx));
if (key == NULL)
return 0;
}
- /* Some MACs don't support this control... that's fine */
- EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS,
- EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT));
-
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
EVP_MD_CTX_set_update_fn(mctx, int_update);
- if (set_key)
- rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data,
- key->length);
- return rv > 0;
+ /* Some MACs don't support this control... that's fine */
+ {
+ OSSL_PARAM params[3];
+ size_t params_n = 0;
+ int flags = EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT);
+
+ /* TODO(3.0) "flags" isn't quite right, i.e. a quick hack for now */
+ params[params_n++] =
+ OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &flags);
+ if (set_key)
+ params[params_n++] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ key->data, key->length);
+ params[params_n++] = OSSL_PARAM_construct_end();
+ rv = EVP_MAC_CTX_set_params(hctx->ctx, params);
+ }
+ return rv;
}
static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
@@ -220,7 +256,7 @@ static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
{
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
- return EVP_MAC_final(hctx->ctx, sig, siglen);
+ return EVP_MAC_final(hctx->ctx, sig, siglen, EVP_MAC_size(hctx->ctx));
}
static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
@@ -235,14 +271,24 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return -2; /* The raw types don't support ciphers */
case MAC_TYPE_MAC:
{
- int rv;
-
- if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
- ctx->engine)) <= 0
- || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER,
- p2)) <= 0
- || !(rv = EVP_MAC_init(hctx->ctx)))
- return rv;
+ OSSL_PARAM params[3];
+ size_t params_n = 0;
+ char *ciphname = (char *)OBJ_nid2sn(EVP_CIPHER_nid(p2));
+ char *engineid = (char *)ENGINE_get_id(ctx->engine);
+
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
+ engineid,
+ strlen(engineid) + 1);
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
+ ciphname,
+ strlen(ciphname) + 1);
+ params[params_n] = OSSL_PARAM_construct_end();
+
+ if (!EVP_MAC_CTX_set_params(hctx->ctx, params)
+ || !EVP_MAC_init(hctx->ctx))
+ return 0;
}
break;
default:
@@ -276,8 +322,40 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
break;
case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
- return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1);
+ {
+ OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
+ size_t size = (size_t)p1;
+ size_t verify = 0;
+
+ /*
+ * We verify that the length is actually set by getting back
+ * the same parameter and checking that it matches what we
+ * tried to set.
+ * TODO(3.0) when we have a more direct mechanism to check if
+ * a parameter was used, we must refactor this to use that.
+ */
+
+ params[0] =
+ OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN, &size);
+
+ if (!EVP_MAC_CTX_set_params(hctx->ctx, params))
+ return 0;
+ params[0] =
+ OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN, &verify);
+
+ if (!EVP_MAC_CTX_get_params(hctx->ctx, params))
+ return 0;
+
+ /*
+ * Since EVP_MAC_CTX_{get,set}_params() returned successfully,
+ * we can only assume that the size was ignored, i.e. this
+ * control is unsupported.
+ */
+ if (verify != size)
+ return -2;
+ }
+ break;
case EVP_PKEY_CTRL_SET_MAC_KEY:
switch (hctx->type) {
case MAC_TYPE_RAW:
@@ -287,8 +365,17 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
return 0;
break;
case MAC_TYPE_MAC:
- if (EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1) <= 0)
- return 0;
+ {
+ OSSL_PARAM params[2];
+ size_t params_n = 0;
+
+ params[params_n++] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ p2, p1);
+ params[params_n] = OSSL_PARAM_construct_end();
+
+ return EVP_MAC_CTX_set_params(hctx->ctx, params);
+ }
break;
default:
/* This should be dead code */
@@ -303,17 +390,32 @@ static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
if (!EVP_MAC_init(hctx->ctx))
return 0;
{
- int rv;
ASN1_OCTET_STRING *key =
(ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
-
- if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
- ctx->engine)) <= 0
- || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD,
- hctx->raw_data.md)) <= 0
- || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY,
- key->data, key->length)) <= 0)
- return rv;
+ OSSL_PARAM params[4];
+ size_t params_n = 0;
+ char *mdname =
+ (char *)OBJ_nid2sn(EVP_MD_nid(hctx->raw_data.md));
+ char *engineid = ctx->engine == NULL
+ ? NULL : (char *)ENGINE_get_id(ctx->engine);
+
+ if (engineid != NULL) {
+ size_t engineid_l = strlen(engineid) + 1;
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ENGINE,
+ engineid,
+ engineid_l);
+ }
+ params[params_n++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
+ mdname,
+ strlen(mdname) + 1);
+ params[params_n++] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ key->data, key->length);
+ params[params_n] = OSSL_PARAM_construct_end();
+
+ return EVP_MAC_CTX_set_params(hctx->ctx, params);
}
break;
case MAC_TYPE_MAC:
@@ -335,8 +437,18 @@ static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+ const EVP_MAC *mac = EVP_MAC_CTX_mac(hctx->ctx);
+ OSSL_PARAM params[2];
+ int ok = 0;
- return EVP_MAC_ctrl_str(hctx->ctx, type, value);
+ if (!OSSL_PARAM_allocate_from_text(&params[0],
+ EVP_MAC_CTX_settable_params(mac),
+ type, value, strlen(value) + 1))
+ return 0;
+ params[1] = OSSL_PARAM_construct_end();
+ ok = EVP_MAC_CTX_set_params(hctx->ctx, params);
+ OPENSSL_free(params[0].data);
+ return ok;
}
const EVP_PKEY_METHOD cmac_pkey_meth = {
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index ce9b9b8f51..fb443b1484 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -121,28 +121,26 @@ extern const EVP_PKEY_METHOD siphash_pkey_meth;
/* struct evp_mac_impl_st is defined by the implementation */
typedef struct evp_mac_impl_st EVP_MAC_IMPL;
struct evp_mac_st {
- int type;
- EVP_MAC_IMPL *(*new) (void);
- EVP_MAC_IMPL *(*dup) (const EVP_MAC_IMPL *macsrc);
- void (*free) (EVP_MAC_IMPL *macctx);
- size_t (*size) (EVP_MAC_IMPL *macctx);
- int (*init) (EVP_MAC_IMPL *macctx);
- int (*update) (EVP_MAC_IMPL *macctx, const unsigned char *data,
- size_t datalen);
- int (*final) (EVP_MAC_IMPL *macctx, unsigned char *out);
- int (*ctrl) (EVP_MAC_IMPL *macctx, int cmd, va_list args);
- int (*ctrl_str) (EVP_MAC_IMPL *macctx, const char *type, const char *value);
-};
+ OSSL_PROVIDER *prov;
+ char *name;
-extern const EVP_MAC blake2b_mac_meth;
-extern const EVP_MAC blake2s_mac_meth;
-extern const EVP_MAC cmac_meth;
-extern const EVP_MAC gmac_meth;
-extern const EVP_MAC hmac_meth;
-extern const EVP_MAC kmac128_meth;
-extern const EVP_MAC kmac256_meth;
-extern const EVP_MAC siphash_meth;
-extern const EVP_MAC poly1305_meth;
+ CRYPTO_REF_COUNT refcnt;
+ CRYPTO_RWLOCK *lock;
+
+ OSSL_OP_mac_newctx_fn *newctx;
+ OSSL_OP_mac_dupctx_fn *dupctx;
+ OSSL_OP_mac_freectx_fn *freectx;
+ OSSL_OP_mac_size_fn *size;
+ OSSL_OP_mac_init_fn *init;
+ OSSL_OP_mac_update_fn *update;
+ OSSL_OP_mac_final_fn *final;
+ OSSL_OP_mac_gettable_params_fn *gettable_params;
+ OSSL_OP_mac_gettable_ctx_params_fn *gettable_ctx_params;
+ OSSL_OP_mac_settable_ctx_params_fn *settable_ctx_params;
+ OSSL_OP_mac_get_params_fn *get_params;
+ OSSL_OP_mac_ctx_get_params_fn *ctx_get_params;
+ OSSL_OP_mac_ctx_set_params_fn *ctx_set_params;