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 "cipher_aes_siv.h" 20 #include "prov/implementations.h" 21 #include "prov/providercommon.h" 22 #include "prov/ciphercommon_aead.h" 23 #include "prov/provider_ctx.h" 24 25 #define siv_stream_update siv_cipher 26 #define SIV_FLAGS AEAD_FLAGS 27 28 static OSSL_FUNC_cipher_set_ctx_params_fn aes_siv_set_ctx_params; 29 30 static void *aes_siv_newctx(void *provctx, size_t keybits, unsigned int mode, 31 uint64_t flags) 32 { 33 PROV_AES_SIV_CTX *ctx; 34 35 if (!ossl_prov_is_running()) 36 return NULL; 37 38 ctx = OPENSSL_zalloc(sizeof(*ctx)); 39 if (ctx != NULL) { 40 ctx->taglen = SIV_LEN; 41 ctx->mode = mode; 42 ctx->keylen = keybits / 8; 43 ctx->hw = ossl_prov_cipher_hw_aes_siv(keybits); 44 ctx->libctx = PROV_LIBCTX_OF(provctx); 45 } 46 return ctx; 47 } 48 49 static void aes_siv_freectx(void *vctx) 50 { 51 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 52 53 if (ctx != NULL) { 54 ctx->hw->cleanup(ctx); 55 OPENSSL_clear_free(ctx, sizeof(*ctx)); 56 } 57 } 58 59 static void *siv_dupctx(void *vctx) 60 { 61 PROV_AES_SIV_CTX *in = (PROV_AES_SIV_CTX *)vctx; 62 PROV_AES_SIV_CTX *ret; 63 64 if (!ossl_prov_is_running()) 65 return NULL; 66 67 ret = OPENSSL_malloc(sizeof(*ret)); 68 if (ret == NULL) 69 return NULL; 70 if (!in->hw->dupctx(in, ret)) { 71 OPENSSL_free(ret); 72 ret = NULL; 73 } 74 return ret; 75 } 76 77 static int siv_init(void *vctx, const unsigned char *key, size_t keylen, 78 const unsigned char *iv, size_t ivlen, 79 const OSSL_PARAM params[], int enc) 80 { 81 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 82 83 if (!ossl_prov_is_running()) 84 return 0; 85 86 ctx->enc = enc; 87 88 if (key != NULL) { 89 if (keylen != ctx->keylen) { 90 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 91 return 0; 92 } 93 if (!ctx->hw->initkey(ctx, key, ctx->keylen)) 94 return 0; 95 } 96 return aes_siv_set_ctx_params(ctx, params); 97 } 98 99 static int siv_einit(void *vctx, const unsigned char *key, size_t keylen, 100 const unsigned char *iv, size_t ivlen, 101 const OSSL_PARAM params[]) 102 { 103 return siv_init(vctx, key, keylen, iv, ivlen, params, 1); 104 } 105 106 static int siv_dinit(void *vctx, const unsigned char *key, size_t keylen, 107 const unsigned char *iv, size_t ivlen, 108 const OSSL_PARAM params[]) 109 { 110 return siv_init(vctx, key, keylen, iv, ivlen, params, 0); 111 } 112 113 static int siv_cipher(void *vctx, unsigned char *out, size_t *outl, 114 size_t outsize, const unsigned char *in, size_t inl) 115 { 116 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 117 118 if (!ossl_prov_is_running()) 119 return 0; 120 121 if (out != NULL && outsize < inl) { 122 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 123 return 0; 124 } 125 126 if (ctx->hw->cipher(ctx, out, in, inl) <= 0) 127 return 0; 128 129 if (outl != NULL) 130 *outl = inl; 131 return 1; 132 } 133 134 static int siv_stream_final(void *vctx, unsigned char *out, size_t *outl, 135 size_t outsize) 136 { 137 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 138 139 if (!ossl_prov_is_running()) 140 return 0; 141 142 if (!ctx->hw->cipher(vctx, out, NULL, 0)) 143 return 0; 144 145 if (outl != NULL) 146 *outl = 0; 147 return 1; 148 } 149 150 static int aes_siv_get_ctx_params(void *vctx, OSSL_PARAM params[]) 151 { 152 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 153 SIV128_CONTEXT *sctx = &ctx->siv; 154 OSSL_PARAM *p; 155 156 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); 157 if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) { 158 if (!ctx->enc 159 || p->data_size != ctx->taglen 160 || !OSSL_PARAM_set_octet_string(p, &sctx->tag.byte, ctx->taglen)) { 161 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 162 return 0; 163 } 164 } 165 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); 166 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->taglen)) { 167 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 168 return 0; 169 } 170 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 171 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { 172 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 173 return 0; 174 } 175 return 1; 176 } 177 178 static const OSSL_PARAM aes_siv_known_gettable_ctx_params[] = { 179 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 180 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), 181 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), 182 OSSL_PARAM_END 183 }; 184 static const OSSL_PARAM *aes_siv_gettable_ctx_params(ossl_unused void *cctx, 185 ossl_unused void *provctx) 186 { 187 return aes_siv_known_gettable_ctx_params; 188 } 189 190 static int aes_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 191 { 192 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 193 const OSSL_PARAM *p; 194 unsigned int speed = 0; 195 196 if (ossl_param_is_empty(params)) 197 return 1; 198 199 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); 200 if (p != NULL) { 201 if (ctx->enc) 202 return 1; 203 if (p->data_type != OSSL_PARAM_OCTET_STRING 204 || !ctx->hw->settag(ctx, p->data, p->data_size)) { 205 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 206 return 0; 207 } 208 } 209 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED); 210 if (p != NULL) { 211 if (!OSSL_PARAM_get_uint(p, &speed)) { 212 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 213 return 0; 214 } 215 ctx->hw->setspeed(ctx, (int)speed); 216 } 217 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); 218 if (p != NULL) { 219 size_t keylen; 220 221 if (!OSSL_PARAM_get_size_t(p, &keylen)) { 222 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 223 return 0; 224 } 225 /* The key length can not be modified */ 226 if (keylen != ctx->keylen) 227 return 0; 228 } 229 return 1; 230 } 231 232 static const OSSL_PARAM aes_siv_known_settable_ctx_params[] = { 233 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 234 OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL), 235 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), 236 OSSL_PARAM_END 237 }; 238 static const OSSL_PARAM *aes_siv_settable_ctx_params(ossl_unused void *cctx, 239 ossl_unused void *provctx) 240 { 241 return aes_siv_known_settable_ctx_params; 242 } 243 244 #define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ 245 static OSSL_FUNC_cipher_newctx_fn alg##kbits##lc##_newctx; \ 246 static OSSL_FUNC_cipher_freectx_fn alg##_##lc##_freectx; \ 247 static OSSL_FUNC_cipher_dupctx_fn lc##_dupctx; \ 248 static OSSL_FUNC_cipher_encrypt_init_fn lc##_einit; \ 249 static OSSL_FUNC_cipher_decrypt_init_fn lc##_dinit; \ 250 static OSSL_FUNC_cipher_update_fn lc##_stream_update; \ 251 static OSSL_FUNC_cipher_final_fn lc##_stream_final; \ 252 static OSSL_FUNC_cipher_cipher_fn lc##_cipher; \ 253 static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ 254 static OSSL_FUNC_cipher_get_ctx_params_fn alg##_##lc##_get_ctx_params; \ 255 static OSSL_FUNC_cipher_gettable_ctx_params_fn \ 256 alg##_##lc##_gettable_ctx_params; \ 257 static OSSL_FUNC_cipher_set_ctx_params_fn alg##_##lc##_set_ctx_params; \ 258 static OSSL_FUNC_cipher_settable_ctx_params_fn \ 259 alg##_##lc##_settable_ctx_params; \ 260 static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ 261 { \ 262 return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ 263 flags, 2*kbits, blkbits, ivbits); \ 264 } \ 265 static void *alg##kbits##lc##_newctx(void *provctx) \ 266 { \ 267 return alg##_##lc##_newctx(provctx, 2*kbits, EVP_CIPH_##UCMODE##_MODE, \ 268 flags); \ 269 } \ 270 const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \ 271 { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \ 272 { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \ 273 { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) lc##_dupctx }, \ 274 { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \ 275 { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \ 276 { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \ 277 { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \ 278 { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \ 279 { OSSL_FUNC_CIPHER_GET_PARAMS, \ 280 (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \ 281 { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ 282 (void (*)(void))ossl_cipher_generic_gettable_params }, \ 283 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ 284 (void (*)(void)) alg##_##lc##_get_ctx_params }, \ 285 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ 286 (void (*)(void)) alg##_##lc##_gettable_ctx_params }, \ 287 { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ 288 (void (*)(void)) alg##_##lc##_set_ctx_params }, \ 289 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ 290 (void (*)(void)) alg##_##lc##_settable_ctx_params }, \ 291 OSSL_DISPATCH_END \ 292 }; 293 294 IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 128, 8, 0) 295 IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 192, 8, 0) 296 IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 256, 8, 0) 297