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