1 /* 2 * Copyright 2019-2025 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 /* Dispatch functions for AES SIV mode */ 11 12 /* 13 * This file uses the low level AES functions (which are deprecated for 14 * non-internal use) in order to implement provider AES ciphers. 15 */ 16 #include "internal/deprecated.h" 17 18 #include <openssl/proverr.h> 19 #include "prov/implementations.h" 20 #include "prov/providercommon.h" 21 #include "prov/ciphercommon_aead.h" 22 #include "prov/provider_ctx.h" 23 #include "cipher_aes_gcm_siv.h" 24 25 static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]); 26 27 static void *ossl_aes_gcm_siv_newctx(void *provctx, size_t keybits) 28 { 29 PROV_AES_GCM_SIV_CTX *ctx; 30 31 if (!ossl_prov_is_running()) 32 return NULL; 33 34 ctx = OPENSSL_zalloc(sizeof(*ctx)); 35 if (ctx != NULL) { 36 ctx->key_len = keybits / 8; 37 ctx->hw = ossl_prov_cipher_hw_aes_gcm_siv(keybits); 38 ctx->libctx = PROV_LIBCTX_OF(provctx); 39 ctx->provctx = provctx; 40 } 41 return ctx; 42 } 43 44 static void ossl_aes_gcm_siv_freectx(void *vctx) 45 { 46 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 47 48 if (ctx == NULL) 49 return; 50 51 OPENSSL_clear_free(ctx->aad, ctx->aad_len); 52 ctx->hw->clean_ctx(ctx); 53 OPENSSL_clear_free(ctx, sizeof(*ctx)); 54 } 55 56 static void *ossl_aes_gcm_siv_dupctx(void *vctx) 57 { 58 PROV_AES_GCM_SIV_CTX *in = (PROV_AES_GCM_SIV_CTX *)vctx; 59 PROV_AES_GCM_SIV_CTX *ret; 60 61 if (!ossl_prov_is_running()) 62 return NULL; 63 64 if (in->hw == NULL) 65 return NULL; 66 67 ret = OPENSSL_memdup(in, sizeof(*in)); 68 if (ret == NULL) 69 return NULL; 70 /* NULL-out these things we create later */ 71 ret->aad = NULL; 72 ret->ecb_ctx = NULL; 73 74 if (in->aad != NULL) { 75 if ((ret->aad = OPENSSL_memdup(in->aad, UP16(ret->aad_len))) == NULL) 76 goto err; 77 } 78 79 if (!in->hw->dup_ctx(ret, in)) 80 goto err; 81 82 return ret; 83 err: 84 if (ret != NULL) { 85 OPENSSL_clear_free(ret->aad, ret->aad_len); 86 OPENSSL_free(ret); 87 } 88 return NULL; 89 } 90 91 static int ossl_aes_gcm_siv_init(void *vctx, const unsigned char *key, size_t keylen, 92 const unsigned char *iv, size_t ivlen, 93 const OSSL_PARAM params[], int enc) 94 { 95 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 96 97 if (!ossl_prov_is_running()) 98 return 0; 99 100 ctx->enc = enc; 101 102 if (key != NULL) { 103 if (keylen != ctx->key_len) { 104 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 105 return 0; 106 } 107 memcpy(ctx->key_gen_key, key, ctx->key_len); 108 } 109 if (iv != NULL) { 110 if (ivlen != sizeof(ctx->nonce)) { 111 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); 112 return 0; 113 } 114 memcpy(ctx->nonce, iv, sizeof(ctx->nonce)); 115 } 116 117 if (!ctx->hw->initkey(ctx)) 118 return 0; 119 120 return ossl_aes_gcm_siv_set_ctx_params(ctx, params); 121 } 122 123 static int ossl_aes_gcm_siv_einit(void *vctx, const unsigned char *key, size_t keylen, 124 const unsigned char *iv, size_t ivlen, 125 const OSSL_PARAM params[]) 126 { 127 return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 1); 128 } 129 130 static int ossl_aes_gcm_siv_dinit(void *vctx, const unsigned char *key, size_t keylen, 131 const unsigned char *iv, size_t ivlen, 132 const OSSL_PARAM params[]) 133 { 134 return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 0); 135 } 136 137 #define ossl_aes_gcm_siv_stream_update ossl_aes_gcm_siv_cipher 138 static int ossl_aes_gcm_siv_cipher(void *vctx, unsigned char *out, size_t *outl, 139 size_t outsize, const unsigned char *in, size_t inl) 140 { 141 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 142 int error = 0; 143 144 if (!ossl_prov_is_running()) 145 return 0; 146 147 if (outsize < inl) { 148 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 149 return 0; 150 } 151 152 error |= !ctx->hw->cipher(ctx, out, in, inl); 153 154 if (outl != NULL && !error) 155 *outl = inl; 156 return !error; 157 } 158 159 static int ossl_aes_gcm_siv_stream_final(void *vctx, unsigned char *out, size_t *outl, 160 size_t outsize) 161 { 162 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 163 int error = 0; 164 165 if (!ossl_prov_is_running()) 166 return 0; 167 168 error |= !ctx->hw->cipher(vctx, out, NULL, 0); 169 170 if (outl != NULL && !error) 171 *outl = 0; 172 return !error; 173 } 174 175 static int ossl_aes_gcm_siv_get_ctx_params(void *vctx, OSSL_PARAM params[]) 176 { 177 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 178 OSSL_PARAM *p; 179 180 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); 181 if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) { 182 if (!ctx->enc || !ctx->generated_tag 183 || p->data_size != sizeof(ctx->tag) 184 || !OSSL_PARAM_set_octet_string(p, ctx->tag, sizeof(ctx->tag))) { 185 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 186 return 0; 187 } 188 } 189 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); 190 if (p != NULL && !OSSL_PARAM_set_size_t(p, sizeof(ctx->tag))) { 191 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 192 return 0; 193 } 194 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 195 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_len)) { 196 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 197 return 0; 198 } 199 return 1; 200 } 201 202 static const OSSL_PARAM aes_gcm_siv_known_gettable_ctx_params[] = { 203 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 204 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), 205 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), 206 OSSL_PARAM_END 207 }; 208 209 static const OSSL_PARAM *ossl_aes_gcm_siv_gettable_ctx_params(ossl_unused void *cctx, 210 ossl_unused void *provctx) 211 { 212 return aes_gcm_siv_known_gettable_ctx_params; 213 } 214 215 static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 216 { 217 PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx; 218 const OSSL_PARAM *p; 219 unsigned int speed = 0; 220 221 if (ossl_param_is_empty(params)) 222 return 1; 223 224 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); 225 if (p != NULL) { 226 if (p->data_type != OSSL_PARAM_OCTET_STRING 227 || p->data_size != sizeof(ctx->user_tag)) { 228 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 229 return 0; 230 } 231 if (!ctx->enc) { 232 memcpy(ctx->user_tag, p->data, sizeof(ctx->tag)); 233 ctx->have_user_tag = 1; 234 } 235 } 236 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED); 237 if (p != NULL) { 238 if (!OSSL_PARAM_get_uint(p, &speed)) { 239 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 240 return 0; 241 } 242 ctx->speed = !!speed; 243 } 244 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); 245 if (p != NULL) { 246 size_t key_len; 247 248 if (!OSSL_PARAM_get_size_t(p, &key_len)) { 249 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 250 return 0; 251 } 252 /* The key length can not be modified */ 253 if (key_len != ctx->key_len) { 254 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 255 return 0; 256 } 257 } 258 return 1; 259 } 260 261 static const OSSL_PARAM aes_gcm_siv_known_settable_ctx_params[] = { 262 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 263 OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL), 264 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), 265 OSSL_PARAM_END 266 }; 267 static const OSSL_PARAM *ossl_aes_gcm_siv_settable_ctx_params(ossl_unused void *cctx, 268 ossl_unused void *provctx) 269 { 270 return aes_gcm_siv_known_settable_ctx_params; 271 } 272 273 #define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ 274 static OSSL_FUNC_cipher_newctx_fn ossl_##alg##kbits##_##lc##_newctx; \ 275 static OSSL_FUNC_cipher_freectx_fn ossl_##alg##_##lc##_freectx; \ 276 static OSSL_FUNC_cipher_dupctx_fn ossl_##alg##_##lc##_dupctx; \ 277 static OSSL_FUNC_cipher_encrypt_init_fn ossl_##alg##_##lc##_einit; \ 278 static OSSL_FUNC_cipher_decrypt_init_fn ossl_##alg##_##lc##_dinit; \ 279 static OSSL_FUNC_cipher_update_fn ossl_##alg##_##lc##_stream_update; \ 280 static OSSL_FUNC_cipher_final_fn ossl_##alg##_##lc##_stream_final; \ 281 static OSSL_FUNC_cipher_cipher_fn ossl_##alg##_##lc##_cipher; \ 282 static OSSL_FUNC_cipher_get_params_fn ossl_##alg##_##kbits##_##lc##_get_params; \ 283 static OSSL_FUNC_cipher_get_ctx_params_fn ossl_##alg##_##lc##_get_ctx_params; \ 284 static OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_##alg##_##lc##_gettable_ctx_params; \ 285 static OSSL_FUNC_cipher_set_ctx_params_fn ossl_##alg##_##lc##_set_ctx_params; \ 286 static OSSL_FUNC_cipher_settable_ctx_params_fn ossl_##alg##_##lc##_settable_ctx_params; \ 287 static int ossl_##alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ 288 { \ 289 return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ 290 flags, kbits, blkbits, ivbits); \ 291 } \ 292 static void *ossl_##alg##kbits##_##lc##_newctx(void *provctx) \ 293 { \ 294 return ossl_##alg##_##lc##_newctx(provctx, kbits); \ 295 } \ 296 const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \ 297 { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))ossl_##alg##kbits##_##lc##_newctx }, \ 298 { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_##alg##_##lc##_freectx }, \ 299 { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))ossl_##alg##_##lc##_dupctx }, \ 300 { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_einit }, \ 301 { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_dinit }, \ 302 { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##alg##_##lc##_stream_update }, \ 303 { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_##alg##_##lc##_stream_final }, \ 304 { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_##alg##_##lc##_cipher }, \ 305 { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))ossl_##alg##_##kbits##_##lc##_get_params }, \ 306 { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))ossl_cipher_generic_gettable_params }, \ 307 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_get_ctx_params }, \ 308 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_gettable_ctx_params }, \ 309 { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_set_ctx_params }, \ 310 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_settable_ctx_params }, \ 311 OSSL_DISPATCH_END \ 312 } 313 314 IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 128, 8, 96); 315 IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 192, 8, 96); 316 IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 256, 8, 96); 317