Latest update
This commit is contained in:
@@ -12,7 +12,8 @@ SOURCE[../../libcrypto]=\
|
||||
evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c pbe_scrypt.c \
|
||||
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 cmeth_lib.c
|
||||
e_chacha20_poly1305.c cmeth_lib.c \
|
||||
mac_lib.c c_allm.c pkey_mac.c
|
||||
|
||||
INCLUDE[e_aes.o]=.. ../modes
|
||||
INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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/evp.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
void openssl_add_all_macs_int(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
EVP_add_mac(&cmac_meth);
|
||||
#endif
|
||||
EVP_add_mac(&hmac_meth);
|
||||
#ifndef OPENSSL_NO_SIPHASH
|
||||
EVP_add_mac(&siphash_meth);
|
||||
#endif
|
||||
}
|
||||
@@ -54,6 +54,11 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, 0),
|
||||
"EVP_EncryptFinal_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTUPDATE, 0), "EVP_EncryptUpdate"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL, 0), "EVP_MAC_ctrl"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTRL_STR, 0), "EVP_MAC_ctrl_str"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_COPY, 0), "EVP_MAC_CTX_copy"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_CTX_NEW, 0), "EVP_MAC_CTX_new"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MAC_INIT, 0), "EVP_MAC_init"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_CTX_COPY_EX, 0), "EVP_MD_CTX_copy_ex"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_MD_SIZE, 0), "EVP_MD_size"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_OPENINIT, 0), "EVP_OpenInit"},
|
||||
@@ -145,6 +150,7 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
|
||||
"PKCS5_v2_PBKDF2_keyivgen"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, 0),
|
||||
"PKCS5_v2_scrypt_keyivgen"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_MAC_INIT, 0), "pkey_mac_init"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_PKEY_SET_TYPE, 0), "pkey_set_type"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_RC2_MAGIC_TO_METH, 0), "rc2_magic_to_meth"},
|
||||
{ERR_PACK(ERR_LIB_EVP, EVP_F_RC5_CTRL, 0), "rc5_ctrl"},
|
||||
|
||||
@@ -526,3 +526,30 @@ int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags)
|
||||
{
|
||||
return (ctx->flags & flags);
|
||||
}
|
||||
|
||||
int EVP_str2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
|
||||
void *ctx, int cmd, const char *value)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(value);
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
return cb(ctx, cmd, (void *)value, len);
|
||||
}
|
||||
|
||||
int EVP_hex2ctrl(int (*cb)(void *ctx, int cmd, void *buf, size_t buflen),
|
||||
void *ctx, int cmd, const char *hex)
|
||||
{
|
||||
unsigned char *bin;
|
||||
long binlen;
|
||||
int rv = -1;
|
||||
|
||||
bin = OPENSSL_hexstr2buf(hex, &binlen);
|
||||
if (bin == NULL)
|
||||
return 0;
|
||||
if (binlen <= INT_MAX)
|
||||
rv = cb(ctx, cmd, bin, binlen);
|
||||
OPENSSL_free(bin);
|
||||
return rv;
|
||||
}
|
||||
@@ -41,6 +41,11 @@ struct evp_cipher_ctx_st {
|
||||
unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */
|
||||
} /* EVP_CIPHER_CTX */ ;
|
||||
|
||||
struct evp_mac_ctx_st {
|
||||
const EVP_MAC *meth; /* Method structure */
|
||||
void *data; /* Individual method data */
|
||||
} /* EVP_MAC_CTX */;
|
||||
|
||||
int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
|
||||
int passlen, ASN1_TYPE *param,
|
||||
const EVP_CIPHER *c, const EVP_MD *md,
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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 <stdarg.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ossl_typ.h>
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/evp_int.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 *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX));
|
||||
|
||||
if (ctx == NULL || (ctx->data = mac->new()) == NULL) {
|
||||
EVPerr(EVP_F_EVP_MAC_CTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(ctx);
|
||||
ctx = NULL;
|
||||
} else {
|
||||
ctx->meth = mac;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void EVP_MAC_CTX_free(EVP_MAC_CTX *ctx)
|
||||
{
|
||||
if (ctx != NULL && ctx->data != NULL) {
|
||||
ctx->meth->free(ctx->data);
|
||||
ctx->data = NULL;
|
||||
}
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
int EVP_MAC_CTX_copy(EVP_MAC_CTX *dst, EVP_MAC_CTX *src)
|
||||
{
|
||||
EVP_MAC_IMPL *macdata;
|
||||
|
||||
if (src->data != NULL && !dst->meth->copy(dst->data, src->data))
|
||||
return 0;
|
||||
|
||||
macdata = dst->data;
|
||||
*dst = *src;
|
||||
dst->data = macdata;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const 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 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_MAC_init(EVP_MAC_CTX *ctx)
|
||||
{
|
||||
return ctx->meth->init(ctx->data);
|
||||
}
|
||||
|
||||
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 l = ctx->meth->size(ctx->data);
|
||||
|
||||
if (l < 0)
|
||||
return 0;
|
||||
if (poutlen != NULL)
|
||||
*poutlen = 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;
|
||||
}
|
||||
|
||||
int EVP_MAC_str2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *value)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(value);
|
||||
if (len > INT_MAX)
|
||||
return -1;
|
||||
return EVP_MAC_ctrl(ctx, cmd, value, len);
|
||||
}
|
||||
|
||||
int EVP_MAC_hex2ctrl(EVP_MAC_CTX *ctx, int cmd, const char *hex)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int EVP_MAC_nid(const EVP_MAC *mac)
|
||||
{
|
||||
return mac->type;
|
||||
}
|
||||
+74
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -55,6 +55,22 @@ int EVP_add_digest(const EVP_MD *md)
|
||||
return r;
|
||||
}
|
||||
|
||||
int EVP_add_mac(const EVP_MAC *m)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (m == NULL)
|
||||
return 0;
|
||||
|
||||
r = OBJ_NAME_add(OBJ_nid2sn(m->type), OBJ_NAME_TYPE_MAC_METH,
|
||||
(const char *)m);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
r = OBJ_NAME_add(OBJ_nid2ln(m->type), OBJ_NAME_TYPE_MAC_METH,
|
||||
(const char *)m);
|
||||
return r;
|
||||
}
|
||||
|
||||
const EVP_CIPHER *EVP_get_cipherbyname(const char *name)
|
||||
{
|
||||
const EVP_CIPHER *cp;
|
||||
@@ -77,8 +93,20 @@ const EVP_MD *EVP_get_digestbyname(const char *name)
|
||||
return cp;
|
||||
}
|
||||
|
||||
const EVP_MAC *EVP_get_macbyname(const char *name)
|
||||
{
|
||||
const EVP_MAC *mp;
|
||||
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL))
|
||||
return NULL;
|
||||
|
||||
mp = (const EVP_MAC *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MAC_METH);
|
||||
return mp;
|
||||
}
|
||||
|
||||
void evp_cleanup_int(void)
|
||||
{
|
||||
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MAC_METH);
|
||||
OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH);
|
||||
OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH);
|
||||
/*
|
||||
@@ -178,3 +206,48 @@ void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md,
|
||||
dc.arg = arg;
|
||||
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc);
|
||||
}
|
||||
|
||||
struct doall_mac {
|
||||
void *arg;
|
||||
void (*fn) (const EVP_MAC *ciph,
|
||||
const char *from, const char *to, void *arg);
|
||||
};
|
||||
|
||||
static void do_all_mac_fn(const OBJ_NAME *nm, void *arg)
|
||||
{
|
||||
struct doall_mac *dc = arg;
|
||||
|
||||
if (nm->alias)
|
||||
dc->fn(NULL, nm->name, nm->data, dc->arg);
|
||||
else
|
||||
dc->fn((const EVP_MAC *)nm->data, nm->name, NULL, dc->arg);
|
||||
}
|
||||
|
||||
void EVP_MAC_do_all(void (*fn)
|
||||
(const EVP_MAC *ciph, const char *from, const char *to,
|
||||
void *x), void *arg)
|
||||
{
|
||||
struct doall_mac dc;
|
||||
|
||||
/* Ignore errors */
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL);
|
||||
|
||||
dc.fn = fn;
|
||||
dc.arg = arg;
|
||||
OBJ_NAME_do_all(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
|
||||
}
|
||||
|
||||
void EVP_MAC_do_all_sorted(void (*fn)
|
||||
(const EVP_MAC *ciph, const char *from,
|
||||
const char *to, void *x), void *arg)
|
||||
{
|
||||
struct doall_mac dc;
|
||||
|
||||
/* Ignore errors */
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_MACS, NULL);
|
||||
|
||||
dc.fn = fn;
|
||||
dc.arg = arg;
|
||||
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MAC_METH, do_all_mac_fn, &dc);
|
||||
}
|
||||
|
||||
+5
-3
@@ -319,7 +319,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
||||
{
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
EVP_PKEY *ret = EVP_PKEY_new();
|
||||
CMAC_CTX *cmctx = CMAC_CTX_new();
|
||||
EVP_MAC_CTX *cmctx = EVP_MAC_CTX_new_id(EVP_MAC_CMAC);
|
||||
|
||||
if (ret == NULL
|
||||
|| cmctx == NULL
|
||||
@@ -328,7 +328,9 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!CMAC_Init(cmctx, priv, len, cipher, e)) {
|
||||
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) {
|
||||
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
|
||||
goto err;
|
||||
}
|
||||
@@ -338,7 +340,7 @@ EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(ret);
|
||||
CMAC_CTX_free(cmctx);
|
||||
EVP_MAC_CTX_free(cmctx);
|
||||
return NULL;
|
||||
#else
|
||||
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (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/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/evp_int.h"
|
||||
|
||||
/* MAC PKEY context structure */
|
||||
|
||||
typedef struct {
|
||||
EVP_MAC_CTX *ctx;
|
||||
|
||||
/*
|
||||
* We know of two MAC types:
|
||||
*
|
||||
* 1. those who take a secret in raw form, i.e. raw data as a
|
||||
* ASN1_OCTET_STRING embedded in a EVP_PKEY. So far, that's
|
||||
* all of them but CMAC.
|
||||
* 2. those who take a secret with associated cipher in very generic
|
||||
* form, i.e. a complete EVP_MAC_CTX embedded in a PKEY. So far,
|
||||
* only CMAC does this.
|
||||
*
|
||||
* (one might wonder why the second form isn't used for all)
|
||||
*/
|
||||
#define MAC_TYPE_RAW 1 /* HMAC like MAC type (all but CMAC so far) */
|
||||
#define MAC_TYPE_MAC 2 /* CMAC like MAC type (only CMAC known so far) */
|
||||
int type;
|
||||
|
||||
/* The following is only used for MAC_TYPE_RAW implementations */
|
||||
struct {
|
||||
const EVP_MD *md; /* temp storage of MD */
|
||||
ASN1_OCTET_STRING ktmp; /* temp storage for key */
|
||||
} raw_data;
|
||||
} MAC_PKEY_CTX;
|
||||
|
||||
static int pkey_mac_init(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx;
|
||||
int nid = ctx->pmeth->pkey_id;
|
||||
|
||||
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);
|
||||
if (hctx->ctx == NULL) {
|
||||
OPENSSL_free(hctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nid == EVP_PKEY_CMAC) {
|
||||
hctx->type = MAC_TYPE_MAC;
|
||||
} else {
|
||||
hctx->type = MAC_TYPE_RAW;
|
||||
hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING;
|
||||
}
|
||||
|
||||
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, EVP_PKEY_CTX *src)
|
||||
{
|
||||
MAC_PKEY_CTX *sctx, *dctx;
|
||||
|
||||
if (!pkey_mac_init(dst))
|
||||
return 0;
|
||||
|
||||
sctx = EVP_PKEY_CTX_get_data(src);
|
||||
dctx = EVP_PKEY_CTX_get_data(dst);
|
||||
|
||||
if (!EVP_MAC_CTX_copy(dctx->ctx, sctx->ctx))
|
||||
goto err;
|
||||
|
||||
switch (dctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
dctx->raw_data.md = sctx->raw_data.md;
|
||||
if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL &&
|
||||
!ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp))
|
||||
goto err;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
/* Nothing more to do */
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
err:
|
||||
pkey_mac_cleanup (dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
if (hctx != NULL) {
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
OPENSSL_clear_free(hctx->raw_data.ktmp.data,
|
||||
hctx->raw_data.ktmp.length);
|
||||
break;
|
||||
}
|
||||
EVP_MAC_CTX_free(hctx->ctx);
|
||||
OPENSSL_free(hctx);
|
||||
EVP_PKEY_CTX_set_data(ctx, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
int nid = ctx->pmeth->pkey_id;
|
||||
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
{
|
||||
ASN1_OCTET_STRING *hkey = NULL;
|
||||
|
||||
if (!hctx->raw_data.ktmp.data)
|
||||
return 0;
|
||||
hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp);
|
||||
if (!hkey)
|
||||
return 0;
|
||||
EVP_PKEY_assign(pkey, nid, hkey);
|
||||
}
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
{
|
||||
EVP_MAC_CTX *cmkey = EVP_MAC_CTX_new_id(nid);
|
||||
|
||||
if (cmkey == NULL)
|
||||
return 0;
|
||||
if (!EVP_MAC_CTX_copy(cmkey, hctx->ctx)) {
|
||||
EVP_MAC_CTX_free(cmkey);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_assign(pkey, nid, cmkey);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
|
||||
|
||||
if (!EVP_MAC_update(hctx->ctx, data, count))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
ASN1_OCTET_STRING *key = NULL;
|
||||
int rv = 1;
|
||||
/*
|
||||
* For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that
|
||||
* gets the key passed as an ASN.1 OCTET STRING, we set the key here,
|
||||
* as this may be only time it's set during a DigestSign.
|
||||
*
|
||||
* MACs that pass around the key in form of EVP_MAC_CTX are setting
|
||||
* the key through other mechanisms. (this is only CMAC for now)
|
||||
*/
|
||||
int set_key =
|
||||
hctx->type == MAC_TYPE_RAW
|
||||
&& (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)))
|
||||
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;
|
||||
}
|
||||
|
||||
static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
|
||||
size_t *siglen, EVP_MD_CTX *mctx)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
return EVP_MAC_final(hctx->ctx, sig, siglen);
|
||||
}
|
||||
|
||||
static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
|
||||
{
|
||||
MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
|
||||
|
||||
switch (type) {
|
||||
|
||||
case EVP_PKEY_CTRL_CIPHER:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
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;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_MD:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
hctx->raw_data.md = p2;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
if (ctx->pkey != NULL
|
||||
&& !EVP_MAC_CTX_copy(hctx->ctx,
|
||||
(EVP_MAC_CTX *)ctx->pkey->pkey.ptr))
|
||||
return 0;
|
||||
if (!EVP_MAC_init(hctx->ctx))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
|
||||
return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1);
|
||||
|
||||
case EVP_PKEY_CTRL_SET_MAC_KEY:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
if ((!p2 && p1 > 0) || (p1 < -1))
|
||||
return 0;
|
||||
if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))
|
||||
return 0;
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVP_PKEY_CTRL_DIGESTINIT:
|
||||
switch (hctx->type) {
|
||||
case MAC_TYPE_RAW:
|
||||
/* Ensure that we have attached the implementation */
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case MAC_TYPE_MAC:
|
||||
return -2; /* The mac types don't support ciphers */
|
||||
default:
|
||||
/* This should be dead code */
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -2;
|
||||
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return EVP_MAC_ctrl_str(hctx->ctx, type, value);
|
||||
}
|
||||
|
||||
const EVP_PKEY_METHOD cmac_pkey_meth = {
|
||||
EVP_PKEY_CMAC,
|
||||
EVP_PKEY_FLAG_SIGCTX_CUSTOM,
|
||||
pkey_mac_init,
|
||||
pkey_mac_copy,
|
||||
pkey_mac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_mac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_signctx_init,
|
||||
pkey_mac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_ctrl,
|
||||
pkey_mac_ctrl_str
|
||||
};
|
||||
|
||||
const EVP_PKEY_METHOD hmac_pkey_meth = {
|
||||
EVP_PKEY_HMAC,
|
||||
0,
|
||||
pkey_mac_init,
|
||||
pkey_mac_copy,
|
||||
pkey_mac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_mac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_signctx_init,
|
||||
pkey_mac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_ctrl,
|
||||
pkey_mac_ctrl_str
|
||||
};
|
||||
|
||||
const EVP_PKEY_METHOD siphash_pkey_meth = {
|
||||
EVP_PKEY_SIPHASH,
|
||||
EVP_PKEY_FLAG_SIGCTX_CUSTOM,
|
||||
pkey_mac_init,
|
||||
pkey_mac_copy,
|
||||
pkey_mac_cleanup,
|
||||
|
||||
0, 0,
|
||||
|
||||
0,
|
||||
pkey_mac_keygen,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_signctx_init,
|
||||
pkey_mac_signctx,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
0, 0,
|
||||
|
||||
pkey_mac_ctrl,
|
||||
pkey_mac_ctrl_str
|
||||
};
|
||||
Reference in New Issue
Block a user