Adapt diverse code to provider based MACs.

CRMF, SSKDF, TLS1_PRF and SIV are affected by this.

This also forces the need to check MAC names, which leads to storing
the names in the created methods, which affects all EVP APIs, not just
EVP_MAC.  We will want that kind of information anyway (for example
for 'openssl list')...  Consequently, EVP_MAC_name() is re-implemented.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/8877)
This commit is contained in:
Richard Levitte 2019-06-04 18:00:04 +02:00
parent d747fb2ec5
commit 776796e818
5 changed files with 140 additions and 61 deletions

View File

@ -12,6 +12,8 @@
*/ */
#include <string.h>
#include <openssl/rand.h> #include <openssl/rand.h>
#include <openssl/evp.h> #include <openssl/evp.h>
@ -22,6 +24,8 @@
#include <openssl/crmf.h> #include <openssl/crmf.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/params.h>
#include <openssl/core_names.h>
/*- /*-
* creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4) * creates and initializes OSSL_CRMF_PBMPARAMETER (section 4.4)
@ -120,9 +124,10 @@ OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t slen, int owfnid,
int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp, int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp,
const unsigned char *msg, size_t msglen, const unsigned char *msg, size_t msglen,
const unsigned char *sec, size_t seclen, const unsigned char *sec, size_t seclen,
unsigned char **mac, size_t *maclen) unsigned char **out, size_t *outlen)
{ {
int mac_nid, hmac_md_nid = NID_undef; int mac_nid, hmac_md_nid = NID_undef;
const char *mdname = NULL;
const EVP_MD *m = NULL; const EVP_MD *m = NULL;
EVP_MD_CTX *ctx = NULL; EVP_MD_CTX *ctx = NULL;
unsigned char basekey[EVP_MAX_MD_SIZE]; unsigned char basekey[EVP_MAX_MD_SIZE];
@ -130,9 +135,12 @@ int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp,
int64_t iterations; int64_t iterations;
unsigned char *mac_res = 0; unsigned char *mac_res = 0;
int ok = 0; int ok = 0;
EVP_MAC *mac = NULL;
EVP_MAC_CTX *mctx = NULL; EVP_MAC_CTX *mctx = NULL;
OSSL_PARAM macparams[3] =
{ OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
if (mac == NULL || pbmp == NULL || pbmp->mac == NULL if (out == NULL || pbmp == NULL || pbmp->mac == NULL
|| pbmp->mac->algorithm == NULL || msg == NULL || sec == NULL) { || pbmp->mac->algorithm == NULL || msg == NULL || sec == NULL) {
CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_NULL_ARGUMENT); CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_NULL_ARGUMENT);
goto err; goto err;
@ -193,17 +201,22 @@ int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp,
mac_nid = OBJ_obj2nid(pbmp->mac->algorithm); mac_nid = OBJ_obj2nid(pbmp->mac->algorithm);
if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, mac_nid, NULL, &hmac_md_nid, NULL) if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, mac_nid, NULL, &hmac_md_nid, NULL)
|| ((m = EVP_get_digestbynid(hmac_md_nid)) == NULL)) { || ((mdname = OBJ_nid2sn(hmac_md_nid)) == NULL)) {
CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_UNSUPPORTED_ALGORITHM); CRMFerr(CRMF_F_OSSL_CRMF_PBM_NEW, CRMF_R_UNSUPPORTED_ALGORITHM);
goto err; goto err;
} }
if ((mctx = EVP_MAC_CTX_new(EVP_get_macbyname("HMAC"))) == NULL macparams[0] =
|| EVP_MAC_ctrl(mctx, EVP_MAC_CTRL_SET_MD, m) <= 0 OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
|| EVP_MAC_ctrl(mctx, EVP_MAC_CTRL_SET_KEY, basekey, bklen) <= 0 (char *)mdname, strlen(mdname) + 1);
macparams[1] =
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, basekey, bklen);
if ((mac = EVP_MAC_fetch(NULL, "HMAC", NULL)) == NULL
|| (mctx = EVP_MAC_CTX_new(mac)) == NULL
|| !EVP_MAC_CTX_set_params(mctx, macparams)
|| !EVP_MAC_init(mctx) || !EVP_MAC_init(mctx)
|| !EVP_MAC_update(mctx, msg, msglen) || !EVP_MAC_update(mctx, msg, msglen)
|| !EVP_MAC_final(mctx, mac_res, maclen)) || !EVP_MAC_final(mctx, mac_res, outlen, EVP_MAX_MD_SIZE))
goto err; goto err;
ok = 1; ok = 1;
@ -212,10 +225,11 @@ int OSSL_CRMF_pbm_new(const OSSL_CRMF_PBMPARAMETER *pbmp,
/* cleanup */ /* cleanup */
OPENSSL_cleanse(basekey, bklen); OPENSSL_cleanse(basekey, bklen);
EVP_MAC_CTX_free(mctx); EVP_MAC_CTX_free(mctx);
EVP_MAC_free(mac);
EVP_MD_CTX_free(ctx); EVP_MD_CTX_free(ctx);
if (ok == 1) { if (ok == 1) {
*mac = mac_res; *out = mac_res;
return 1; return 1;
} }

View File

@ -211,6 +211,7 @@ struct siv128_context {
SIV_BLOCK d; SIV_BLOCK d;
SIV_BLOCK tag; SIV_BLOCK tag;
EVP_CIPHER_CTX *cipher_ctx; EVP_CIPHER_CTX *cipher_ctx;
EVP_MAC *mac;
EVP_MAC_CTX *mac_ctx_init; EVP_MAC_CTX *mac_ctx_init;
int final_ret; int final_ret;
int crypto_ok; int crypto_ok;

View File

@ -40,12 +40,14 @@
#include <openssl/hmac.h> #include <openssl/hmac.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/kdf.h> #include <openssl/kdf.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include "internal/evp_int.h" #include "internal/evp_int.h"
#include "kdf_local.h" #include "kdf_local.h"
struct evp_kdf_impl_st { struct evp_kdf_impl_st {
const EVP_MAC *mac; /* H(x) = HMAC_hash OR H(x) = KMAC */ EVP_MAC *mac; /* H(x) = HMAC_hash OR H(x) = KMAC */
const EVP_MD *md; /* H(x) = hash OR when H(x) = HMAC_hash */ const EVP_MD *md; /* H(x) = hash OR when H(x) = HMAC_hash */
unsigned char *secret; unsigned char *secret;
size_t secret_len; size_t secret_len;
@ -141,11 +143,17 @@ static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
size_t custom_len, size_t kmac_out_len, size_t custom_len, size_t kmac_out_len,
size_t derived_key_len, unsigned char **out) size_t derived_key_len, unsigned char **out)
{ {
OSSL_PARAM params[2];
/* Only KMAC has custom data - so return if not KMAC */ /* Only KMAC has custom data - so return if not KMAC */
if (custom == NULL) if (custom == NULL)
return 1; return 1;
if (EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_CUSTOM, custom, custom_len) <= 0) params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM,
(void *)custom, custom_len);
params[1] = OSSL_PARAM_construct_end();
if (!EVP_MAC_CTX_set_params(ctx, params))
return 0; return 0;
/* By default only do one iteration if kmac_out_len is not specified */ /* By default only do one iteration if kmac_out_len is not specified */
@ -160,7 +168,10 @@ static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
|| kmac_out_len == 64)) || kmac_out_len == 64))
return 0; return 0;
if (EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_SIZE, kmac_out_len) <= 0) params[0] = OSSL_PARAM_construct_size_t(OSSL_MAC_PARAM_OUTLEN,
&kmac_out_len);
if (EVP_MAC_CTX_set_params(ctx, params) <= 0)
return 0; return 0;
/* /*
@ -181,7 +192,7 @@ static int kmac_init(EVP_MAC_CTX *ctx, const unsigned char *custom,
* H(x) = HMAC-hash(salt, x) OR * H(x) = HMAC-hash(salt, x) OR
* H(x) = KMAC#(salt, x, outbits, CustomString='KDF') * H(x) = KMAC#(salt, x, outbits, CustomString='KDF')
*/ */
static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md, static int SSKDF_mac_kdm(EVP_MAC *kdf_mac, const EVP_MD *hmac_md,
const unsigned char *kmac_custom, const unsigned char *kmac_custom,
size_t kmac_custom_len, size_t kmac_out_len, size_t kmac_custom_len, size_t kmac_out_len,
const unsigned char *salt, size_t salt_len, const unsigned char *salt, size_t salt_len,
@ -196,6 +207,8 @@ static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md,
unsigned char *out = derived_key; unsigned char *out = derived_key;
EVP_MAC_CTX *ctx = NULL, *ctx_init = NULL; EVP_MAC_CTX *ctx = NULL, *ctx_init = NULL;
unsigned char *mac = mac_buf, *kmac_buffer = NULL; unsigned char *mac = mac_buf, *kmac_buffer = NULL;
OSSL_PARAM params[3];
size_t params_n = 0;
if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN if (z_len > SSKDF_MAX_INLEN || info_len > SSKDF_MAX_INLEN
|| derived_key_len > SSKDF_MAX_INLEN || derived_key_len > SSKDF_MAX_INLEN
@ -205,11 +218,20 @@ static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md,
ctx_init = EVP_MAC_CTX_new(kdf_mac); ctx_init = EVP_MAC_CTX_new(kdf_mac);
if (ctx_init == NULL) if (ctx_init == NULL)
goto end; goto end;
if (hmac_md != NULL &&
EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, hmac_md) <= 0)
goto end;
if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, salt, salt_len) <= 0) if (hmac_md != NULL) {
const char *mdname = EVP_MD_name(hmac_md);
params[params_n++] =
OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
(char *)mdname,
strlen(mdname) + 1);
}
params[params_n++] =
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, (void *)salt,
salt_len);
params[params_n] = OSSL_PARAM_construct_end();
if (!EVP_MAC_CTX_set_params(ctx_init, params))
goto end; goto end;
if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len, if (!kmac_init(ctx_init, kmac_custom, kmac_custom_len, kmac_out_len,
@ -239,14 +261,14 @@ static int SSKDF_mac_kdm(const EVP_MAC *kdf_mac, const EVP_MD *hmac_md,
&& EVP_MAC_update(ctx, info, info_len))) && EVP_MAC_update(ctx, info, info_len)))
goto end; goto end;
if (len >= out_len) { if (len >= out_len) {
if (!EVP_MAC_final(ctx, out, NULL)) if (!EVP_MAC_final(ctx, out, NULL, len))
goto end; goto end;
out += out_len; out += out_len;
len -= out_len; len -= out_len;
if (len == 0) if (len == 0)
break; break;
} else { } else {
if (!EVP_MAC_final(ctx, mac, NULL)) if (!EVP_MAC_final(ctx, mac, NULL, len))
goto end; goto end;
memcpy(out, mac, len); memcpy(out, mac, len);
break; break;
@ -280,6 +302,10 @@ static void sskdf_reset(EVP_KDF_IMPL *impl)
OPENSSL_clear_free(impl->secret, impl->secret_len); OPENSSL_clear_free(impl->secret, impl->secret_len);
OPENSSL_clear_free(impl->info, impl->info_len); OPENSSL_clear_free(impl->info, impl->info_len);
OPENSSL_clear_free(impl->salt, impl->salt_len); OPENSSL_clear_free(impl->salt, impl->salt_len);
EVP_MAC_free(impl->mac);
#if 0 /* TODO(3.0) When we switch to fetched MDs */
EVP_MD_meth_free(impl->md);
#endif
memset(impl, 0, sizeof(*impl)); memset(impl, 0, sizeof(*impl));
} }
@ -311,7 +337,6 @@ static int sskdf_set_buffer(va_list args, unsigned char **out, size_t *out_len)
static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args) static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
{ {
const EVP_MD *md; const EVP_MD *md;
const EVP_MAC *mac;
switch (cmd) { switch (cmd) {
case EVP_KDF_CTRL_SET_KEY: case EVP_KDF_CTRL_SET_KEY:
@ -325,17 +350,34 @@ static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
if (md == NULL) if (md == NULL)
return 0; return 0;
#if 0 /* TODO(3.0) When we switch to fetched MDs */
EVP_MD_meth_free(impl->md);
#endif
impl->md = md; impl->md = md;
return 1; return 1;
case EVP_KDF_CTRL_SET_MAC: case EVP_KDF_CTRL_SET_MAC:
mac = va_arg(args, const EVP_MAC *); {
if (mac == NULL) const char *name;
return 0; EVP_MAC *mac;
impl->mac = mac; name = va_arg(args, const char *);
return 1; if (name == NULL)
return 0;
EVP_MAC_free(impl->mac);
impl->mac = NULL;
/*
* TODO(3.0) add support for OPENSSL_CTX and properties in KDFs
*/
mac = EVP_MAC_fetch(NULL, name, NULL);
if (mac == NULL)
return 0;
impl->mac = mac;
return 1;
}
case EVP_KDF_CTRL_SET_SALT: case EVP_KDF_CTRL_SET_SALT:
return sskdf_set_buffer(args, &impl->salt, &impl->salt_len); return sskdf_set_buffer(args, &impl->salt, &impl->salt_len);
@ -348,20 +390,6 @@ static int sskdf_ctrl(EVP_KDF_IMPL *impl, int cmd, va_list args)
} }
} }
/* Pass a mac to a ctrl */
static int sskdf_mac2ctrl(EVP_KDF_IMPL *impl,
int (*ctrl)(EVP_KDF_IMPL *impl, int cmd, va_list args),
int cmd, const char *mac_name)
{
const EVP_MAC *mac;
if (mac_name == NULL || (mac = EVP_get_macbyname(mac_name)) == NULL) {
KDFerr(KDF_F_SSKDF_MAC2CTRL, KDF_R_INVALID_MAC_TYPE);
return 0;
}
return call_ctrl(ctrl, impl, cmd, mac);
}
static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type, static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
const char *value) const char *value)
{ {
@ -385,7 +413,7 @@ static int sskdf_ctrl_str(EVP_KDF_IMPL *impl, const char *type,
return kdf_md2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MD, value); return kdf_md2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MD, value);
if (strcmp(type, "mac") == 0) if (strcmp(type, "mac") == 0)
return sskdf_mac2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MAC, value); return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_MAC, value);
if (strcmp(type, "salt") == 0) if (strcmp(type, "salt") == 0)
return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value); return kdf_str2ctrl(impl, sskdf_ctrl, EVP_KDF_CTRL_SET_SALT, value);
@ -430,11 +458,16 @@ static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
int ret; int ret;
const unsigned char *custom = NULL; const unsigned char *custom = NULL;
size_t custom_len = 0; size_t custom_len = 0;
int nid; const char *macname;
int default_salt_len; int default_salt_len;
nid = EVP_MAC_nid(impl->mac); /*
if (nid == EVP_MAC_HMAC) { * TODO(3.0) investigate the necessity to have all these controls.
* Why does KMAC require a salt length that's shorter than the MD
* block size?
*/
macname = EVP_MAC_name(impl->mac);
if (strcmp(macname, "HMAC") == 0) {
/* H(x) = HMAC(x, salt, hash) */ /* H(x) = HMAC(x, salt, hash) */
if (impl->md == NULL) { if (impl->md == NULL) {
KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST); KDFerr(KDF_F_SSKDF_DERIVE, KDF_R_MISSING_MESSAGE_DIGEST);
@ -443,11 +476,12 @@ static int sskdf_derive(EVP_KDF_IMPL *impl, unsigned char *key, size_t keylen)
default_salt_len = EVP_MD_block_size(impl->md); default_salt_len = EVP_MD_block_size(impl->md);
if (default_salt_len <= 0) if (default_salt_len <= 0)
return 0; return 0;
} else if (nid == EVP_MAC_KMAC128 || nid == EVP_MAC_KMAC256) { } else if (strcmp(macname, "KMAC128") == 0
|| strcmp(macname, "KMAC256") == 0) {
/* H(x) = KMACzzz(x, salt, custom) */ /* H(x) = KMACzzz(x, salt, custom) */
custom = kmac_custom_str; custom = kmac_custom_str;
custom_len = sizeof(kmac_custom_str); custom_len = sizeof(kmac_custom_str);
if (nid == EVP_MAC_KMAC128) if (strcmp(macname, "KMAC128") == 0)
default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE; default_salt_len = SSKDF_KMAC128_DEFAULT_SALT_SIZE;
else else
default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE; default_salt_len = SSKDF_KMAC256_DEFAULT_SALT_SIZE;

View File

@ -51,6 +51,8 @@
#include "internal/cryptlib.h" #include "internal/cryptlib.h"
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/kdf.h> #include <openssl/kdf.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "internal/evp_int.h" #include "internal/evp_int.h"
#include "kdf_local.h" #include "kdf_local.h"
@ -232,19 +234,30 @@ static int tls1_prf_P_hash(const EVP_MD *md,
unsigned char *out, size_t olen) unsigned char *out, size_t olen)
{ {
size_t chunk; size_t chunk;
EVP_MAC *mac = NULL;
EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL, *ctx_init = NULL; EVP_MAC_CTX *ctx = NULL, *ctx_Ai = NULL, *ctx_init = NULL;
unsigned char Ai[EVP_MAX_MD_SIZE]; unsigned char Ai[EVP_MAX_MD_SIZE];
size_t Ai_len; size_t Ai_len;
int ret = 0; int ret = 0;
OSSL_PARAM params[4];
int mac_flags;
const char *mdname = EVP_MD_name(md);
ctx_init = EVP_MAC_CTX_new_id(EVP_MAC_HMAC); mac = EVP_MAC_fetch(NULL, "HMAC", NULL); /* Implicit fetch */
ctx_init = EVP_MAC_CTX_new(mac);
if (ctx_init == NULL) if (ctx_init == NULL)
goto err; goto err;
if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_FLAGS, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW) != 1)
goto err; /* TODO(3.0) rethink "flags", also see hmac.c in providers */
if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_MD, md) != 1) mac_flags = EVP_MD_CTX_FLAG_NON_FIPS_ALLOW;
goto err; params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FLAGS, &mac_flags);
if (EVP_MAC_ctrl(ctx_init, EVP_MAC_CTRL_SET_KEY, sec, sec_len) != 1) params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
(char *)mdname,
strlen(mdname) + 1);
params[2] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
(void *)sec, sec_len);
params[3] = OSSL_PARAM_construct_end();
if (!EVP_MAC_CTX_set_params(ctx_init, params))
goto err; goto err;
if (!EVP_MAC_init(ctx_init)) if (!EVP_MAC_init(ctx_init))
goto err; goto err;
@ -260,7 +273,7 @@ static int tls1_prf_P_hash(const EVP_MD *md,
for (;;) { for (;;) {
/* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */ /* calc: A(i) = HMAC_<hash>(secret, A(i-1)) */
if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len)) if (!EVP_MAC_final(ctx_Ai, Ai, &Ai_len, sizeof(Ai)))
goto err; goto err;
EVP_MAC_CTX_free(ctx_Ai); EVP_MAC_CTX_free(ctx_Ai);
ctx_Ai = NULL; ctx_Ai = NULL;
@ -281,12 +294,12 @@ static int tls1_prf_P_hash(const EVP_MD *md,
goto err; goto err;
if (olen <= chunk) { if (olen <= chunk) {
/* last chunk - use Ai as temp bounce buffer */ /* last chunk - use Ai as temp bounce buffer */
if (!EVP_MAC_final(ctx, Ai, &Ai_len)) if (!EVP_MAC_final(ctx, Ai, &Ai_len, sizeof(Ai)))
goto err; goto err;
memcpy(out, Ai, olen); memcpy(out, Ai, olen);
break; break;
} }
if (!EVP_MAC_final(ctx, out, NULL)) if (!EVP_MAC_final(ctx, out, NULL, olen))
goto err; goto err;
EVP_MAC_CTX_free(ctx); EVP_MAC_CTX_free(ctx);
ctx = NULL; ctx = NULL;
@ -298,6 +311,7 @@ static int tls1_prf_P_hash(const EVP_MD *md,
EVP_MAC_CTX_free(ctx); EVP_MAC_CTX_free(ctx);
EVP_MAC_CTX_free(ctx_Ai); EVP_MAC_CTX_free(ctx_Ai);
EVP_MAC_CTX_free(ctx_init); EVP_MAC_CTX_free(ctx_init);
EVP_MAC_free(mac);
OPENSSL_cleanse(Ai, sizeof(Ai)); OPENSSL_cleanse(Ai, sizeof(Ai));
return ret; return ret;
} }

View File

@ -11,6 +11,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/core_names.h>
#include <openssl/params.h>
#include "internal/modes_int.h" #include "internal/modes_int.h"
#include "internal/siv_int.h" #include "internal/siv_int.h"
@ -117,7 +119,7 @@ __owur static ossl_inline int siv128_do_s2v_p(SIV128_CONTEXT *ctx, SIV_BLOCK *ou
if (!EVP_MAC_update(mac_ctx, t.byte, SIV_LEN)) if (!EVP_MAC_update(mac_ctx, t.byte, SIV_LEN))
goto err; goto err;
} }
if (!EVP_MAC_final(mac_ctx, out->byte, &out_len) if (!EVP_MAC_final(mac_ctx, out->byte, &out_len, sizeof(out->byte))
|| out_len != SIV_LEN) || out_len != SIV_LEN)
goto err; goto err;
@ -167,6 +169,15 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
static const unsigned char zero[SIV_LEN] = { 0 }; static const unsigned char zero[SIV_LEN] = { 0 };
size_t out_len = SIV_LEN; size_t out_len = SIV_LEN;
EVP_MAC_CTX *mac_ctx = NULL; EVP_MAC_CTX *mac_ctx = NULL;
OSSL_PARAM params[3];
const char *cbc_name = EVP_CIPHER_name(cbc);
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_ALGORITHM,
(char *)cbc_name,
strlen(cbc_name) + 1);
params[1] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
(void *)key, klen);
params[2] = OSSL_PARAM_construct_end();
memset(&ctx->d, 0, sizeof(ctx->d)); memset(&ctx->d, 0, sizeof(ctx->d));
ctx->cipher_ctx = NULL; ctx->cipher_ctx = NULL;
@ -174,16 +185,19 @@ int CRYPTO_siv128_init(SIV128_CONTEXT *ctx, const unsigned char *key, int klen,
if (key == NULL || cbc == NULL || ctr == NULL if (key == NULL || cbc == NULL || ctr == NULL
|| (ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL || (ctx->cipher_ctx = EVP_CIPHER_CTX_new()) == NULL
|| (ctx->mac_ctx_init = EVP_MAC_CTX_new_id(EVP_MAC_CMAC)) == NULL /* TODO(3.0) library context */
|| EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_CIPHER, cbc) <= 0 || (ctx->mac = EVP_MAC_fetch(NULL, "CMAC", NULL)) == NULL
|| EVP_MAC_ctrl(ctx->mac_ctx_init, EVP_MAC_CTRL_SET_KEY, key, klen) <= 0 || (ctx->mac_ctx_init = EVP_MAC_CTX_new(ctx->mac)) == NULL
|| !EVP_MAC_CTX_set_params(ctx->mac_ctx_init, params)
|| !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL) || !EVP_EncryptInit_ex(ctx->cipher_ctx, ctr, NULL, key + klen, NULL)
|| (mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL || (mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL
|| !EVP_MAC_update(mac_ctx, zero, sizeof(zero)) || !EVP_MAC_update(mac_ctx, zero, sizeof(zero))
|| !EVP_MAC_final(mac_ctx, ctx->d.byte, &out_len)) { || !EVP_MAC_final(mac_ctx, ctx->d.byte, &out_len,
sizeof(ctx->d.byte))) {
EVP_CIPHER_CTX_free(ctx->cipher_ctx); EVP_CIPHER_CTX_free(ctx->cipher_ctx);
EVP_MAC_CTX_free(ctx->mac_ctx_init); EVP_MAC_CTX_free(ctx->mac_ctx_init);
EVP_MAC_CTX_free(mac_ctx); EVP_MAC_CTX_free(mac_ctx);
EVP_MAC_free(ctx->mac);
return 0; return 0;
} }
EVP_MAC_CTX_free(mac_ctx); EVP_MAC_CTX_free(mac_ctx);
@ -223,10 +237,10 @@ int CRYPTO_siv128_aad(SIV128_CONTEXT *ctx, const unsigned char *aad,
siv128_dbl(&ctx->d); siv128_dbl(&ctx->d);
mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init); if ((mac_ctx = EVP_MAC_CTX_dup(ctx->mac_ctx_init)) == NULL
if (mac_ctx == NULL
|| !EVP_MAC_update(mac_ctx, aad, len) || !EVP_MAC_update(mac_ctx, aad, len)
|| !EVP_MAC_final(mac_ctx, mac_out.byte, &out_len) || !EVP_MAC_final(mac_ctx, mac_out.byte, &out_len,
sizeof(mac_out.byte))
|| out_len != SIV_LEN) { || out_len != SIV_LEN) {
EVP_MAC_CTX_free(mac_ctx); EVP_MAC_CTX_free(mac_ctx);
return 0; return 0;
@ -345,6 +359,8 @@ int CRYPTO_siv128_cleanup(SIV128_CONTEXT *ctx)
ctx->cipher_ctx = NULL; ctx->cipher_ctx = NULL;
EVP_MAC_CTX_free(ctx->mac_ctx_init); EVP_MAC_CTX_free(ctx->mac_ctx_init);
ctx->mac_ctx_init = NULL; ctx->mac_ctx_init = NULL;
EVP_MAC_free(ctx->mac);
ctx->mac = NULL;
OPENSSL_cleanse(&ctx->d, sizeof(ctx->d)); OPENSSL_cleanse(&ctx->d, sizeof(ctx->d));
OPENSSL_cleanse(&ctx->tag, sizeof(ctx->tag)); OPENSSL_cleanse(&ctx->tag, sizeof(ctx->tag));
ctx->final_ret = -1; ctx->final_ret = -1;