123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- /*
- * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (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
- };
- const EVP_PKEY_METHOD poly1305_pkey_meth = {
- EVP_PKEY_POLY1305,
- 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
- };
|