1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2018-2022 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci#include <string.h> 11e1051a39Sopenharmony_ci#include <stdarg.h> 12e1051a39Sopenharmony_ci#include <openssl/evp.h> 13e1051a39Sopenharmony_ci#include <openssl/err.h> 14e1051a39Sopenharmony_ci#include <openssl/core.h> 15e1051a39Sopenharmony_ci#include <openssl/core_names.h> 16e1051a39Sopenharmony_ci#include <openssl/types.h> 17e1051a39Sopenharmony_ci#include "internal/nelem.h" 18e1051a39Sopenharmony_ci#include "crypto/evp.h" 19e1051a39Sopenharmony_ci#include "internal/provider.h" 20e1051a39Sopenharmony_ci#include "evp_local.h" 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ciEVP_MAC_CTX *EVP_MAC_CTX_new(EVP_MAC *mac) 23e1051a39Sopenharmony_ci{ 24e1051a39Sopenharmony_ci EVP_MAC_CTX *ctx = OPENSSL_zalloc(sizeof(EVP_MAC_CTX)); 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci if (ctx == NULL 27e1051a39Sopenharmony_ci || (ctx->algctx = mac->newctx(ossl_provider_ctx(mac->prov))) == NULL 28e1051a39Sopenharmony_ci || !EVP_MAC_up_ref(mac)) { 29e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 30e1051a39Sopenharmony_ci if (ctx != NULL) 31e1051a39Sopenharmony_ci mac->freectx(ctx->algctx); 32e1051a39Sopenharmony_ci OPENSSL_free(ctx); 33e1051a39Sopenharmony_ci ctx = NULL; 34e1051a39Sopenharmony_ci } else { 35e1051a39Sopenharmony_ci ctx->meth = mac; 36e1051a39Sopenharmony_ci } 37e1051a39Sopenharmony_ci return ctx; 38e1051a39Sopenharmony_ci} 39e1051a39Sopenharmony_ci 40e1051a39Sopenharmony_civoid EVP_MAC_CTX_free(EVP_MAC_CTX *ctx) 41e1051a39Sopenharmony_ci{ 42e1051a39Sopenharmony_ci if (ctx == NULL) 43e1051a39Sopenharmony_ci return; 44e1051a39Sopenharmony_ci ctx->meth->freectx(ctx->algctx); 45e1051a39Sopenharmony_ci ctx->algctx = NULL; 46e1051a39Sopenharmony_ci /* refcnt-- */ 47e1051a39Sopenharmony_ci EVP_MAC_free(ctx->meth); 48e1051a39Sopenharmony_ci OPENSSL_free(ctx); 49e1051a39Sopenharmony_ci} 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ciEVP_MAC_CTX *EVP_MAC_CTX_dup(const EVP_MAC_CTX *src) 52e1051a39Sopenharmony_ci{ 53e1051a39Sopenharmony_ci EVP_MAC_CTX *dst; 54e1051a39Sopenharmony_ci 55e1051a39Sopenharmony_ci if (src->algctx == NULL) 56e1051a39Sopenharmony_ci return NULL; 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci dst = OPENSSL_malloc(sizeof(*dst)); 59e1051a39Sopenharmony_ci if (dst == NULL) { 60e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 61e1051a39Sopenharmony_ci return NULL; 62e1051a39Sopenharmony_ci } 63e1051a39Sopenharmony_ci 64e1051a39Sopenharmony_ci *dst = *src; 65e1051a39Sopenharmony_ci if (!EVP_MAC_up_ref(dst->meth)) { 66e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 67e1051a39Sopenharmony_ci OPENSSL_free(dst); 68e1051a39Sopenharmony_ci return NULL; 69e1051a39Sopenharmony_ci } 70e1051a39Sopenharmony_ci 71e1051a39Sopenharmony_ci dst->algctx = src->meth->dupctx(src->algctx); 72e1051a39Sopenharmony_ci if (dst->algctx == NULL) { 73e1051a39Sopenharmony_ci EVP_MAC_CTX_free(dst); 74e1051a39Sopenharmony_ci return NULL; 75e1051a39Sopenharmony_ci } 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci return dst; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ciEVP_MAC *EVP_MAC_CTX_get0_mac(EVP_MAC_CTX *ctx) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci return ctx->meth; 83e1051a39Sopenharmony_ci} 84e1051a39Sopenharmony_ci 85e1051a39Sopenharmony_cistatic size_t get_size_t_ctx_param(EVP_MAC_CTX *ctx, const char *name) 86e1051a39Sopenharmony_ci{ 87e1051a39Sopenharmony_ci size_t sz = 0; 88e1051a39Sopenharmony_ci 89e1051a39Sopenharmony_ci if (ctx->algctx != NULL) { 90e1051a39Sopenharmony_ci OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_size_t(name, &sz); 93e1051a39Sopenharmony_ci if (ctx->meth->get_ctx_params != NULL) { 94e1051a39Sopenharmony_ci if (ctx->meth->get_ctx_params(ctx->algctx, params)) 95e1051a39Sopenharmony_ci return sz; 96e1051a39Sopenharmony_ci } else if (ctx->meth->get_params != NULL) { 97e1051a39Sopenharmony_ci if (ctx->meth->get_params(params)) 98e1051a39Sopenharmony_ci return sz; 99e1051a39Sopenharmony_ci } 100e1051a39Sopenharmony_ci } 101e1051a39Sopenharmony_ci /* 102e1051a39Sopenharmony_ci * If the MAC hasn't been initialized yet, or there is no size to get, 103e1051a39Sopenharmony_ci * we return zero 104e1051a39Sopenharmony_ci */ 105e1051a39Sopenharmony_ci return 0; 106e1051a39Sopenharmony_ci} 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_cisize_t EVP_MAC_CTX_get_mac_size(EVP_MAC_CTX *ctx) 109e1051a39Sopenharmony_ci{ 110e1051a39Sopenharmony_ci return get_size_t_ctx_param(ctx, OSSL_MAC_PARAM_SIZE); 111e1051a39Sopenharmony_ci} 112e1051a39Sopenharmony_ci 113e1051a39Sopenharmony_cisize_t EVP_MAC_CTX_get_block_size(EVP_MAC_CTX *ctx) 114e1051a39Sopenharmony_ci{ 115e1051a39Sopenharmony_ci return get_size_t_ctx_param(ctx, OSSL_MAC_PARAM_BLOCK_SIZE); 116e1051a39Sopenharmony_ci} 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ciint EVP_MAC_init(EVP_MAC_CTX *ctx, const unsigned char *key, size_t keylen, 119e1051a39Sopenharmony_ci const OSSL_PARAM params[]) 120e1051a39Sopenharmony_ci{ 121e1051a39Sopenharmony_ci return ctx->meth->init(ctx->algctx, key, keylen, params); 122e1051a39Sopenharmony_ci} 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ciint EVP_MAC_update(EVP_MAC_CTX *ctx, const unsigned char *data, size_t datalen) 125e1051a39Sopenharmony_ci{ 126e1051a39Sopenharmony_ci return ctx->meth->update(ctx->algctx, data, datalen); 127e1051a39Sopenharmony_ci} 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_cistatic int evp_mac_final(EVP_MAC_CTX *ctx, int xof, 130e1051a39Sopenharmony_ci unsigned char *out, size_t *outl, size_t outsize) 131e1051a39Sopenharmony_ci{ 132e1051a39Sopenharmony_ci size_t l; 133e1051a39Sopenharmony_ci int res; 134e1051a39Sopenharmony_ci OSSL_PARAM params[2]; 135e1051a39Sopenharmony_ci size_t macsize; 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci if (ctx == NULL || ctx->meth == NULL) { 138e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_NULL_ALGORITHM); 139e1051a39Sopenharmony_ci return 0; 140e1051a39Sopenharmony_ci } 141e1051a39Sopenharmony_ci if (ctx->meth->final == NULL) { 142e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_FINAL_ERROR); 143e1051a39Sopenharmony_ci return 0; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci macsize = EVP_MAC_CTX_get_mac_size(ctx); 147e1051a39Sopenharmony_ci if (out == NULL) { 148e1051a39Sopenharmony_ci if (outl == NULL) { 149e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); 150e1051a39Sopenharmony_ci return 0; 151e1051a39Sopenharmony_ci } 152e1051a39Sopenharmony_ci *outl = macsize; 153e1051a39Sopenharmony_ci return 1; 154e1051a39Sopenharmony_ci } 155e1051a39Sopenharmony_ci if (outsize < macsize) { 156e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_BUFFER_TOO_SMALL); 157e1051a39Sopenharmony_ci return 0; 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci if (xof) { 160e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_XOF, &xof); 161e1051a39Sopenharmony_ci params[1] = OSSL_PARAM_construct_end(); 162e1051a39Sopenharmony_ci 163e1051a39Sopenharmony_ci if (EVP_MAC_CTX_set_params(ctx, params) <= 0) { 164e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, EVP_R_SETTING_XOF_FAILED); 165e1051a39Sopenharmony_ci return 0; 166e1051a39Sopenharmony_ci } 167e1051a39Sopenharmony_ci } 168e1051a39Sopenharmony_ci res = ctx->meth->final(ctx->algctx, out, &l, outsize); 169e1051a39Sopenharmony_ci if (outl != NULL) 170e1051a39Sopenharmony_ci *outl = l; 171e1051a39Sopenharmony_ci return res; 172e1051a39Sopenharmony_ci} 173e1051a39Sopenharmony_ci 174e1051a39Sopenharmony_ciint EVP_MAC_final(EVP_MAC_CTX *ctx, 175e1051a39Sopenharmony_ci unsigned char *out, size_t *outl, size_t outsize) 176e1051a39Sopenharmony_ci{ 177e1051a39Sopenharmony_ci return evp_mac_final(ctx, 0, out, outl, outsize); 178e1051a39Sopenharmony_ci} 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ciint EVP_MAC_finalXOF(EVP_MAC_CTX *ctx, unsigned char *out, size_t outsize) 181e1051a39Sopenharmony_ci{ 182e1051a39Sopenharmony_ci return evp_mac_final(ctx, 1, out, NULL, outsize); 183e1051a39Sopenharmony_ci} 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci/* 186e1051a39Sopenharmony_ci * The {get,set}_params functions return 1 if there is no corresponding 187e1051a39Sopenharmony_ci * function in the implementation. This is the same as if there was one, 188e1051a39Sopenharmony_ci * but it didn't recognise any of the given params, i.e. nothing in the 189e1051a39Sopenharmony_ci * bag of parameters was useful. 190e1051a39Sopenharmony_ci */ 191e1051a39Sopenharmony_ciint EVP_MAC_get_params(EVP_MAC *mac, OSSL_PARAM params[]) 192e1051a39Sopenharmony_ci{ 193e1051a39Sopenharmony_ci if (mac->get_params != NULL) 194e1051a39Sopenharmony_ci return mac->get_params(params); 195e1051a39Sopenharmony_ci return 1; 196e1051a39Sopenharmony_ci} 197e1051a39Sopenharmony_ci 198e1051a39Sopenharmony_ciint EVP_MAC_CTX_get_params(EVP_MAC_CTX *ctx, OSSL_PARAM params[]) 199e1051a39Sopenharmony_ci{ 200e1051a39Sopenharmony_ci if (ctx->meth->get_ctx_params != NULL) 201e1051a39Sopenharmony_ci return ctx->meth->get_ctx_params(ctx->algctx, params); 202e1051a39Sopenharmony_ci return 1; 203e1051a39Sopenharmony_ci} 204e1051a39Sopenharmony_ci 205e1051a39Sopenharmony_ciint EVP_MAC_CTX_set_params(EVP_MAC_CTX *ctx, const OSSL_PARAM params[]) 206e1051a39Sopenharmony_ci{ 207e1051a39Sopenharmony_ci if (ctx->meth->set_ctx_params != NULL) 208e1051a39Sopenharmony_ci return ctx->meth->set_ctx_params(ctx->algctx, params); 209e1051a39Sopenharmony_ci return 1; 210e1051a39Sopenharmony_ci} 211e1051a39Sopenharmony_ci 212e1051a39Sopenharmony_ciint evp_mac_get_number(const EVP_MAC *mac) 213e1051a39Sopenharmony_ci{ 214e1051a39Sopenharmony_ci return mac->name_id; 215e1051a39Sopenharmony_ci} 216e1051a39Sopenharmony_ci 217e1051a39Sopenharmony_ciconst char *EVP_MAC_get0_name(const EVP_MAC *mac) 218e1051a39Sopenharmony_ci{ 219e1051a39Sopenharmony_ci return mac->type_name; 220e1051a39Sopenharmony_ci} 221e1051a39Sopenharmony_ci 222e1051a39Sopenharmony_ciconst char *EVP_MAC_get0_description(const EVP_MAC *mac) 223e1051a39Sopenharmony_ci{ 224e1051a39Sopenharmony_ci return mac->description; 225e1051a39Sopenharmony_ci} 226e1051a39Sopenharmony_ci 227e1051a39Sopenharmony_ciint EVP_MAC_is_a(const EVP_MAC *mac, const char *name) 228e1051a39Sopenharmony_ci{ 229e1051a39Sopenharmony_ci return mac != NULL && evp_is_a(mac->prov, mac->name_id, NULL, name); 230e1051a39Sopenharmony_ci} 231e1051a39Sopenharmony_ci 232e1051a39Sopenharmony_ciint EVP_MAC_names_do_all(const EVP_MAC *mac, 233e1051a39Sopenharmony_ci void (*fn)(const char *name, void *data), 234e1051a39Sopenharmony_ci void *data) 235e1051a39Sopenharmony_ci{ 236e1051a39Sopenharmony_ci if (mac->prov != NULL) 237e1051a39Sopenharmony_ci return evp_names_do_all(mac->prov, mac->name_id, fn, data); 238e1051a39Sopenharmony_ci 239e1051a39Sopenharmony_ci return 1; 240e1051a39Sopenharmony_ci} 241e1051a39Sopenharmony_ci 242e1051a39Sopenharmony_ciunsigned char *EVP_Q_mac(OSSL_LIB_CTX *libctx, 243e1051a39Sopenharmony_ci const char *name, const char *propq, 244e1051a39Sopenharmony_ci const char *subalg, const OSSL_PARAM *params, 245e1051a39Sopenharmony_ci const void *key, size_t keylen, 246e1051a39Sopenharmony_ci const unsigned char *data, size_t datalen, 247e1051a39Sopenharmony_ci unsigned char *out, size_t outsize, size_t *outlen) 248e1051a39Sopenharmony_ci{ 249e1051a39Sopenharmony_ci EVP_MAC *mac = EVP_MAC_fetch(libctx, name, propq); 250e1051a39Sopenharmony_ci OSSL_PARAM subalg_param[] = { OSSL_PARAM_END, OSSL_PARAM_END }; 251e1051a39Sopenharmony_ci EVP_MAC_CTX *ctx = NULL; 252e1051a39Sopenharmony_ci size_t len = 0; 253e1051a39Sopenharmony_ci unsigned char *res = NULL; 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci if (outlen != NULL) 256e1051a39Sopenharmony_ci *outlen = 0; 257e1051a39Sopenharmony_ci if (mac == NULL) 258e1051a39Sopenharmony_ci return NULL; 259e1051a39Sopenharmony_ci if (subalg != NULL) { 260e1051a39Sopenharmony_ci const OSSL_PARAM *defined_params = EVP_MAC_settable_ctx_params(mac); 261e1051a39Sopenharmony_ci const char *param_name = OSSL_MAC_PARAM_DIGEST; 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci /* 264e1051a39Sopenharmony_ci * The underlying algorithm may be a cipher or a digest. 265e1051a39Sopenharmony_ci * We don't know which it is, but we can ask the MAC what it 266e1051a39Sopenharmony_ci * should be and bet on that. 267e1051a39Sopenharmony_ci */ 268e1051a39Sopenharmony_ci if (OSSL_PARAM_locate_const(defined_params, param_name) == NULL) { 269e1051a39Sopenharmony_ci param_name = OSSL_MAC_PARAM_CIPHER; 270e1051a39Sopenharmony_ci if (OSSL_PARAM_locate_const(defined_params, param_name) == NULL) { 271e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT); 272e1051a39Sopenharmony_ci goto err; 273e1051a39Sopenharmony_ci } 274e1051a39Sopenharmony_ci } 275e1051a39Sopenharmony_ci subalg_param[0] = 276e1051a39Sopenharmony_ci OSSL_PARAM_construct_utf8_string(param_name, (char *)subalg, 0); 277e1051a39Sopenharmony_ci } 278e1051a39Sopenharmony_ci /* Single-shot - on NULL key input, set dummy key value for EVP_MAC_Init. */ 279e1051a39Sopenharmony_ci if (key == NULL && keylen == 0) 280e1051a39Sopenharmony_ci key = data; 281e1051a39Sopenharmony_ci if ((ctx = EVP_MAC_CTX_new(mac)) != NULL 282e1051a39Sopenharmony_ci && EVP_MAC_CTX_set_params(ctx, subalg_param) 283e1051a39Sopenharmony_ci && EVP_MAC_CTX_set_params(ctx, params) 284e1051a39Sopenharmony_ci && EVP_MAC_init(ctx, key, keylen, params) 285e1051a39Sopenharmony_ci && EVP_MAC_update(ctx, data, datalen) 286e1051a39Sopenharmony_ci && EVP_MAC_final(ctx, out, &len, outsize)) { 287e1051a39Sopenharmony_ci if (out == NULL) { 288e1051a39Sopenharmony_ci out = OPENSSL_malloc(len); 289e1051a39Sopenharmony_ci if (out != NULL && !EVP_MAC_final(ctx, out, NULL, len)) { 290e1051a39Sopenharmony_ci OPENSSL_free(out); 291e1051a39Sopenharmony_ci out = NULL; 292e1051a39Sopenharmony_ci } 293e1051a39Sopenharmony_ci } 294e1051a39Sopenharmony_ci res = out; 295e1051a39Sopenharmony_ci if (res != NULL && outlen != NULL) 296e1051a39Sopenharmony_ci *outlen = len; 297e1051a39Sopenharmony_ci } 298e1051a39Sopenharmony_ci 299e1051a39Sopenharmony_ci err: 300e1051a39Sopenharmony_ci EVP_MAC_CTX_free(ctx); 301e1051a39Sopenharmony_ci EVP_MAC_free(mac); 302e1051a39Sopenharmony_ci return res; 303e1051a39Sopenharmony_ci} 304