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 <stdlib.h> 11e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h> 12e1051a39Sopenharmony_ci#include <openssl/core_names.h> 13e1051a39Sopenharmony_ci#include <openssl/params.h> 14e1051a39Sopenharmony_ci#include <openssl/evp.h> 15e1051a39Sopenharmony_ci#include <openssl/err.h> 16e1051a39Sopenharmony_ci#include <openssl/proverr.h> 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci#include "prov/implementations.h" 19e1051a39Sopenharmony_ci#include "prov/provider_ctx.h" 20e1051a39Sopenharmony_ci#include "prov/provider_util.h" 21e1051a39Sopenharmony_ci#include "prov/providercommon.h" 22e1051a39Sopenharmony_ci 23e1051a39Sopenharmony_ci/* 24e1051a39Sopenharmony_ci * Forward declaration of everything implemented here. This is not strictly 25e1051a39Sopenharmony_ci * necessary for the compiler, but provides an assurance that the signatures 26e1051a39Sopenharmony_ci * of the functions in the dispatch table are correct. 27e1051a39Sopenharmony_ci */ 28e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_newctx_fn gmac_new; 29e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_dupctx_fn gmac_dup; 30e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_freectx_fn gmac_free; 31e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_gettable_params_fn gmac_gettable_params; 32e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_get_params_fn gmac_get_params; 33e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_settable_ctx_params_fn gmac_settable_ctx_params; 34e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_set_ctx_params_fn gmac_set_ctx_params; 35e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_init_fn gmac_init; 36e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_update_fn gmac_update; 37e1051a39Sopenharmony_cistatic OSSL_FUNC_mac_final_fn gmac_final; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci/* local GMAC pkey structure */ 40e1051a39Sopenharmony_ci 41e1051a39Sopenharmony_cistruct gmac_data_st { 42e1051a39Sopenharmony_ci void *provctx; 43e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx; /* Cipher context */ 44e1051a39Sopenharmony_ci PROV_CIPHER cipher; 45e1051a39Sopenharmony_ci}; 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_cistatic void gmac_free(void *vmacctx) 48e1051a39Sopenharmony_ci{ 49e1051a39Sopenharmony_ci struct gmac_data_st *macctx = vmacctx; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci if (macctx != NULL) { 52e1051a39Sopenharmony_ci EVP_CIPHER_CTX_free(macctx->ctx); 53e1051a39Sopenharmony_ci ossl_prov_cipher_reset(&macctx->cipher); 54e1051a39Sopenharmony_ci OPENSSL_free(macctx); 55e1051a39Sopenharmony_ci } 56e1051a39Sopenharmony_ci} 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_cistatic void *gmac_new(void *provctx) 59e1051a39Sopenharmony_ci{ 60e1051a39Sopenharmony_ci struct gmac_data_st *macctx; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 63e1051a39Sopenharmony_ci return NULL; 64e1051a39Sopenharmony_ci 65e1051a39Sopenharmony_ci if ((macctx = OPENSSL_zalloc(sizeof(*macctx))) == NULL 66e1051a39Sopenharmony_ci || (macctx->ctx = EVP_CIPHER_CTX_new()) == NULL) { 67e1051a39Sopenharmony_ci gmac_free(macctx); 68e1051a39Sopenharmony_ci return NULL; 69e1051a39Sopenharmony_ci } 70e1051a39Sopenharmony_ci macctx->provctx = provctx; 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci return macctx; 73e1051a39Sopenharmony_ci} 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_cistatic void *gmac_dup(void *vsrc) 76e1051a39Sopenharmony_ci{ 77e1051a39Sopenharmony_ci struct gmac_data_st *src = vsrc; 78e1051a39Sopenharmony_ci struct gmac_data_st *dst; 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 81e1051a39Sopenharmony_ci return NULL; 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci dst = gmac_new(src->provctx); 84e1051a39Sopenharmony_ci if (dst == NULL) 85e1051a39Sopenharmony_ci return NULL; 86e1051a39Sopenharmony_ci 87e1051a39Sopenharmony_ci if (!EVP_CIPHER_CTX_copy(dst->ctx, src->ctx) 88e1051a39Sopenharmony_ci || !ossl_prov_cipher_copy(&dst->cipher, &src->cipher)) { 89e1051a39Sopenharmony_ci gmac_free(dst); 90e1051a39Sopenharmony_ci return NULL; 91e1051a39Sopenharmony_ci } 92e1051a39Sopenharmony_ci return dst; 93e1051a39Sopenharmony_ci} 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_cistatic size_t gmac_size(void) 96e1051a39Sopenharmony_ci{ 97e1051a39Sopenharmony_ci return EVP_GCM_TLS_TAG_LEN; 98e1051a39Sopenharmony_ci} 99e1051a39Sopenharmony_ci 100e1051a39Sopenharmony_cistatic int gmac_setkey(struct gmac_data_st *macctx, 101e1051a39Sopenharmony_ci const unsigned char *key, size_t keylen) 102e1051a39Sopenharmony_ci{ 103e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx = macctx->ctx; 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ci if (keylen != (size_t)EVP_CIPHER_CTX_get_key_length(ctx)) { 106e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 107e1051a39Sopenharmony_ci return 0; 108e1051a39Sopenharmony_ci } 109e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL)) 110e1051a39Sopenharmony_ci return 0; 111e1051a39Sopenharmony_ci return 1; 112e1051a39Sopenharmony_ci} 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_cistatic int gmac_init(void *vmacctx, const unsigned char *key, 115e1051a39Sopenharmony_ci size_t keylen, const OSSL_PARAM params[]) 116e1051a39Sopenharmony_ci{ 117e1051a39Sopenharmony_ci struct gmac_data_st *macctx = vmacctx; 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ci if (!ossl_prov_is_running() || !gmac_set_ctx_params(macctx, params)) 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci if (key != NULL) 122e1051a39Sopenharmony_ci return gmac_setkey(macctx, key, keylen); 123e1051a39Sopenharmony_ci return EVP_EncryptInit_ex(macctx->ctx, NULL, NULL, NULL, NULL); 124e1051a39Sopenharmony_ci} 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_cistatic int gmac_update(void *vmacctx, const unsigned char *data, 127e1051a39Sopenharmony_ci size_t datalen) 128e1051a39Sopenharmony_ci{ 129e1051a39Sopenharmony_ci struct gmac_data_st *macctx = vmacctx; 130e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx = macctx->ctx; 131e1051a39Sopenharmony_ci int outlen; 132e1051a39Sopenharmony_ci 133e1051a39Sopenharmony_ci if (datalen == 0) 134e1051a39Sopenharmony_ci return 1; 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci while (datalen > INT_MAX) { 137e1051a39Sopenharmony_ci if (!EVP_EncryptUpdate(ctx, NULL, &outlen, data, INT_MAX)) 138e1051a39Sopenharmony_ci return 0; 139e1051a39Sopenharmony_ci data += INT_MAX; 140e1051a39Sopenharmony_ci datalen -= INT_MAX; 141e1051a39Sopenharmony_ci } 142e1051a39Sopenharmony_ci return EVP_EncryptUpdate(ctx, NULL, &outlen, data, datalen); 143e1051a39Sopenharmony_ci} 144e1051a39Sopenharmony_ci 145e1051a39Sopenharmony_cistatic int gmac_final(void *vmacctx, unsigned char *out, size_t *outl, 146e1051a39Sopenharmony_ci size_t outsize) 147e1051a39Sopenharmony_ci{ 148e1051a39Sopenharmony_ci OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 149e1051a39Sopenharmony_ci struct gmac_data_st *macctx = vmacctx; 150e1051a39Sopenharmony_ci int hlen = 0; 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 153e1051a39Sopenharmony_ci return 0; 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci if (!EVP_EncryptFinal_ex(macctx->ctx, out, &hlen)) 156e1051a39Sopenharmony_ci return 0; 157e1051a39Sopenharmony_ci 158e1051a39Sopenharmony_ci hlen = gmac_size(); 159e1051a39Sopenharmony_ci params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, 160e1051a39Sopenharmony_ci out, (size_t)hlen); 161e1051a39Sopenharmony_ci if (!EVP_CIPHER_CTX_get_params(macctx->ctx, params)) 162e1051a39Sopenharmony_ci return 0; 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci *outl = hlen; 165e1051a39Sopenharmony_ci return 1; 166e1051a39Sopenharmony_ci} 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_cistatic const OSSL_PARAM known_gettable_params[] = { 169e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL), 170e1051a39Sopenharmony_ci OSSL_PARAM_END 171e1051a39Sopenharmony_ci}; 172e1051a39Sopenharmony_cistatic const OSSL_PARAM *gmac_gettable_params(void *provctx) 173e1051a39Sopenharmony_ci{ 174e1051a39Sopenharmony_ci return known_gettable_params; 175e1051a39Sopenharmony_ci} 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_cistatic int gmac_get_params(OSSL_PARAM params[]) 178e1051a39Sopenharmony_ci{ 179e1051a39Sopenharmony_ci OSSL_PARAM *p; 180e1051a39Sopenharmony_ci 181e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_SIZE)) != NULL) 182e1051a39Sopenharmony_ci return OSSL_PARAM_set_size_t(p, gmac_size()); 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_ci return 1; 185e1051a39Sopenharmony_ci} 186e1051a39Sopenharmony_ci 187e1051a39Sopenharmony_cistatic const OSSL_PARAM known_settable_ctx_params[] = { 188e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, NULL, 0), 189e1051a39Sopenharmony_ci OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_PROPERTIES, NULL, 0), 190e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_MAC_PARAM_KEY, NULL, 0), 191e1051a39Sopenharmony_ci OSSL_PARAM_octet_string(OSSL_MAC_PARAM_IV, NULL, 0), 192e1051a39Sopenharmony_ci OSSL_PARAM_END 193e1051a39Sopenharmony_ci}; 194e1051a39Sopenharmony_cistatic const OSSL_PARAM *gmac_settable_ctx_params(ossl_unused void *ctx, 195e1051a39Sopenharmony_ci ossl_unused void *provctx) 196e1051a39Sopenharmony_ci{ 197e1051a39Sopenharmony_ci return known_settable_ctx_params; 198e1051a39Sopenharmony_ci} 199e1051a39Sopenharmony_ci 200e1051a39Sopenharmony_ci/* 201e1051a39Sopenharmony_ci * ALL parameters should be set before init(). 202e1051a39Sopenharmony_ci */ 203e1051a39Sopenharmony_cistatic int gmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[]) 204e1051a39Sopenharmony_ci{ 205e1051a39Sopenharmony_ci struct gmac_data_st *macctx = vmacctx; 206e1051a39Sopenharmony_ci EVP_CIPHER_CTX *ctx = macctx->ctx; 207e1051a39Sopenharmony_ci OSSL_LIB_CTX *provctx = PROV_LIBCTX_OF(macctx->provctx); 208e1051a39Sopenharmony_ci const OSSL_PARAM *p; 209e1051a39Sopenharmony_ci 210e1051a39Sopenharmony_ci if (params == NULL) 211e1051a39Sopenharmony_ci return 1; 212e1051a39Sopenharmony_ci if (ctx == NULL) 213e1051a39Sopenharmony_ci return 0; 214e1051a39Sopenharmony_ci 215e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_CIPHER)) != NULL) { 216e1051a39Sopenharmony_ci if (!ossl_prov_cipher_load_from_params(&macctx->cipher, params, provctx)) 217e1051a39Sopenharmony_ci return 0; 218e1051a39Sopenharmony_ci if (EVP_CIPHER_get_mode(ossl_prov_cipher_cipher(&macctx->cipher)) 219e1051a39Sopenharmony_ci != EVP_CIPH_GCM_MODE) { 220e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MODE); 221e1051a39Sopenharmony_ci return 0; 222e1051a39Sopenharmony_ci } 223e1051a39Sopenharmony_ci if (!EVP_EncryptInit_ex(ctx, ossl_prov_cipher_cipher(&macctx->cipher), 224e1051a39Sopenharmony_ci ossl_prov_cipher_engine(&macctx->cipher), NULL, 225e1051a39Sopenharmony_ci NULL)) 226e1051a39Sopenharmony_ci return 0; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci 229e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) 230e1051a39Sopenharmony_ci if (p->data_type != OSSL_PARAM_OCTET_STRING 231e1051a39Sopenharmony_ci || !gmac_setkey(macctx, p->data, p->data_size)) 232e1051a39Sopenharmony_ci return 0; 233e1051a39Sopenharmony_ci 234e1051a39Sopenharmony_ci if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_IV)) != NULL) { 235e1051a39Sopenharmony_ci if (p->data_type != OSSL_PARAM_OCTET_STRING) 236e1051a39Sopenharmony_ci return 0; 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ci if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 239e1051a39Sopenharmony_ci p->data_size, NULL) <= 0 240e1051a39Sopenharmony_ci || !EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, p->data)) 241e1051a39Sopenharmony_ci return 0; 242e1051a39Sopenharmony_ci } 243e1051a39Sopenharmony_ci return 1; 244e1051a39Sopenharmony_ci} 245e1051a39Sopenharmony_ci 246e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_gmac_functions[] = { 247e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))gmac_new }, 248e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))gmac_dup }, 249e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_FREECTX, (void (*)(void))gmac_free }, 250e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_INIT, (void (*)(void))gmac_init }, 251e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_UPDATE, (void (*)(void))gmac_update }, 252e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_FINAL, (void (*)(void))gmac_final }, 253e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_GETTABLE_PARAMS, (void (*)(void))gmac_gettable_params }, 254e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_GET_PARAMS, (void (*)(void))gmac_get_params }, 255e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS, 256e1051a39Sopenharmony_ci (void (*)(void))gmac_settable_ctx_params }, 257e1051a39Sopenharmony_ci { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))gmac_set_ctx_params }, 258e1051a39Sopenharmony_ci { 0, NULL } 259e1051a39Sopenharmony_ci}; 260