2 * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #include <openssl/err.h>
11 #include <openssl/evp.h>
12 #include "internal/evp_int.h"
14 /* MAC PKEY context structure */
20 * We know of two MAC types:
22 * 1. those who take a secret in raw form, i.e. raw data as a
23 * ASN1_OCTET_STRING embedded in a EVP_PKEY. So far, that's
24 * all of them but CMAC.
25 * 2. those who take a secret with associated cipher in very generic
26 * form, i.e. a complete EVP_MAC_CTX embedded in a PKEY. So far,
27 * only CMAC does this.
29 * (one might wonder why the second form isn't used for all)
31 #define MAC_TYPE_RAW 1 /* HMAC like MAC type (all but CMAC so far) */
32 #define MAC_TYPE_MAC 2 /* CMAC like MAC type (only CMAC known so far) */
35 /* The following is only used for MAC_TYPE_RAW implementations */
37 const EVP_MD *md; /* temp storage of MD */
38 ASN1_OCTET_STRING ktmp; /* temp storage for key */
42 static int pkey_mac_init(EVP_PKEY_CTX *ctx)
45 int nid = ctx->pmeth->pkey_id;
47 if ((hctx = OPENSSL_zalloc(sizeof(*hctx))) == NULL) {
48 EVPerr(EVP_F_PKEY_MAC_INIT, ERR_R_MALLOC_FAILURE);
52 /* We're being smart and using the same base NIDs for PKEY and for MAC */
53 hctx->ctx = EVP_MAC_CTX_new_id(nid);
54 if (hctx->ctx == NULL) {
59 if (nid == EVP_PKEY_CMAC) {
60 hctx->type = MAC_TYPE_MAC;
62 hctx->type = MAC_TYPE_RAW;
63 hctx->raw_data.ktmp.type = V_ASN1_OCTET_STRING;
66 EVP_PKEY_CTX_set_data(ctx, hctx);
67 ctx->keygen_info_count = 0;
72 static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx);
74 static int pkey_mac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
76 MAC_PKEY_CTX *sctx, *dctx;
78 if (!pkey_mac_init(dst))
81 sctx = EVP_PKEY_CTX_get_data(src);
82 dctx = EVP_PKEY_CTX_get_data(dst);
84 if (!EVP_MAC_CTX_copy(dctx->ctx, sctx->ctx))
89 dctx->raw_data.md = sctx->raw_data.md;
90 if (ASN1_STRING_get0_data(&sctx->raw_data.ktmp) != NULL &&
91 !ASN1_STRING_copy(&dctx->raw_data.ktmp, &sctx->raw_data.ktmp))
95 /* Nothing more to do */
98 /* This should be dead code */
103 pkey_mac_cleanup (dst);
107 static void pkey_mac_cleanup(EVP_PKEY_CTX *ctx)
109 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
112 switch (hctx->type) {
114 OPENSSL_clear_free(hctx->raw_data.ktmp.data,
115 hctx->raw_data.ktmp.length);
118 EVP_MAC_CTX_free(hctx->ctx);
120 EVP_PKEY_CTX_set_data(ctx, NULL);
124 static int pkey_mac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
126 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
127 int nid = ctx->pmeth->pkey_id;
129 switch (hctx->type) {
132 ASN1_OCTET_STRING *hkey = NULL;
134 if (!hctx->raw_data.ktmp.data)
136 hkey = ASN1_OCTET_STRING_dup(&hctx->raw_data.ktmp);
139 EVP_PKEY_assign(pkey, nid, hkey);
144 EVP_MAC_CTX *cmkey = EVP_MAC_CTX_new_id(nid);
148 if (!EVP_MAC_CTX_copy(cmkey, hctx->ctx)) {
149 EVP_MAC_CTX_free(cmkey);
152 EVP_PKEY_assign(pkey, nid, cmkey);
156 /* This should be dead code */
163 static int int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
165 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
167 if (!EVP_MAC_update(hctx->ctx, data, count))
172 static int pkey_mac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
174 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
175 ASN1_OCTET_STRING *key = NULL;
178 * For MACs with the EVP_PKEY_FLAG_SIGCTX_CUSTOM flag set and that
179 * gets the key passed as an ASN.1 OCTET STRING, we set the key here,
180 * as this may be only time it's set during a DigestSign.
182 * MACs that pass around the key in form of EVP_MAC_CTX are setting
183 * the key through other mechanisms. (this is only CMAC for now)
186 hctx->type == MAC_TYPE_RAW
187 && (ctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) != 0;
190 if (EVP_PKEY_id(EVP_PKEY_CTX_get0_pkey(ctx))
191 != EVP_MAC_nid(EVP_MAC_CTX_mac(hctx->ctx)))
193 key = EVP_PKEY_get0(EVP_PKEY_CTX_get0_pkey(ctx));
198 /* Some MACs don't support this control... that's fine */
199 EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_FLAGS,
200 EVP_MD_CTX_test_flags(mctx, ~EVP_MD_CTX_FLAG_NO_INIT));
202 EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
203 EVP_MD_CTX_set_update_fn(mctx, int_update);
206 rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, key->data,
211 static int pkey_mac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
212 size_t *siglen, EVP_MD_CTX *mctx)
214 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
216 return EVP_MAC_final(hctx->ctx, sig, siglen);
219 static int pkey_mac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
221 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
225 case EVP_PKEY_CTRL_CIPHER:
226 switch (hctx->type) {
228 return -2; /* The raw types don't support ciphers */
233 if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
235 || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_CIPHER,
237 || !(rv = EVP_MAC_init(hctx->ctx)))
242 /* This should be dead code */
247 case EVP_PKEY_CTRL_MD:
248 switch (hctx->type) {
250 hctx->raw_data.md = p2;
253 if (ctx->pkey != NULL
254 && !EVP_MAC_CTX_copy(hctx->ctx,
255 (EVP_MAC_CTX *)ctx->pkey->pkey.ptr))
257 if (!EVP_MAC_init(hctx->ctx))
261 /* This should be dead code */
266 case EVP_PKEY_CTRL_SET_DIGEST_SIZE:
267 return EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_SIZE, (size_t)p1);
269 case EVP_PKEY_CTRL_SET_MAC_KEY:
270 switch (hctx->type) {
272 if ((!p2 && p1 > 0) || (p1 < -1))
274 if (!ASN1_OCTET_STRING_set(&hctx->raw_data.ktmp, p2, p1))
278 if (!EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY, p2, p1))
282 /* This should be dead code */
287 case EVP_PKEY_CTRL_DIGESTINIT:
288 switch (hctx->type) {
290 /* Ensure that we have attached the implementation */
291 if (!EVP_MAC_init(hctx->ctx))
295 ASN1_OCTET_STRING *key =
296 (ASN1_OCTET_STRING *)ctx->pkey->pkey.ptr;
298 if ((rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_ENGINE,
300 || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_MD,
301 hctx->raw_data.md)) < 0
302 || (rv = EVP_MAC_ctrl(hctx->ctx, EVP_MAC_CTRL_SET_KEY,
303 key->data, key->length)) < 0)
308 return -2; /* The mac types don't support ciphers */
310 /* This should be dead code */
322 static int pkey_mac_ctrl_str(EVP_PKEY_CTX *ctx,
323 const char *type, const char *value)
325 MAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
327 return EVP_MAC_ctrl_str(hctx->ctx, type, value);
330 const EVP_PKEY_METHOD cmac_pkey_meth = {
332 EVP_PKEY_FLAG_SIGCTX_CUSTOM,
348 pkey_mac_signctx_init,
363 const EVP_PKEY_METHOD hmac_pkey_meth = {
381 pkey_mac_signctx_init,
396 const EVP_PKEY_METHOD siphash_pkey_meth = {
398 EVP_PKEY_FLAG_SIGCTX_CUSTOM,
414 pkey_mac_signctx_init,