1 /* 2 * Copyright 2019-2023 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 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); 70 return NULL; 71 } 72 if (!in->hw->dupctx(in, ret)) { 73 OPENSSL_free(ret); 74 ret = NULL; 75 } 76 return ret; 77 } 78 79 static int siv_init(void *vctx, const unsigned char *key, size_t keylen, 80 const unsigned char *iv, size_t ivlen, 81 const OSSL_PARAM params[], int enc) 82 { 83 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 84 85 if (!ossl_prov_is_running()) 86 return 0; 87 88 ctx->enc = enc; 89 90 if (key != NULL) { 91 if (keylen != ctx->keylen) { 92 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 93 return 0; 94 } 95 if (!ctx->hw->initkey(ctx, key, ctx->keylen)) 96 return 0; 97 } 98 return aes_siv_set_ctx_params(ctx, params); 99 } 100 101 static int siv_einit(void *vctx, const unsigned char *key, size_t keylen, 102 const unsigned char *iv, size_t ivlen, 103 const OSSL_PARAM params[]) 104 { 105 return siv_init(vctx, key, keylen, iv, ivlen, params, 1); 106 } 107 108 static int siv_dinit(void *vctx, const unsigned char *key, size_t keylen, 109 const unsigned char *iv, size_t ivlen, 110 const OSSL_PARAM params[]) 111 { 112 return siv_init(vctx, key, keylen, iv, ivlen, params, 0); 113 } 114 115 static int siv_cipher(void *vctx, unsigned char *out, size_t *outl, 116 size_t outsize, const unsigned char *in, size_t inl) 117 { 118 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 119 120 if (!ossl_prov_is_running()) 121 return 0; 122 123 /* Ignore just empty encryption/decryption call and not AAD. */ 124 if (out != NULL) { 125 if (inl == 0) { 126 if (outl != NULL) 127 *outl = 0; 128 return 1; 129 } 130 131 if (outsize < inl) { 132 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL); 133 return 0; 134 } 135 } 136 137 if (ctx->hw->cipher(ctx, out, in, inl) <= 0) 138 return 0; 139 140 if (outl != NULL) 141 *outl = inl; 142 return 1; 143 } 144 145 static int siv_stream_final(void *vctx, unsigned char *out, size_t *outl, 146 size_t outsize) 147 { 148 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 149 150 if (!ossl_prov_is_running()) 151 return 0; 152 153 if (!ctx->hw->cipher(vctx, out, NULL, 0)) 154 return 0; 155 156 if (outl != NULL) 157 *outl = 0; 158 return 1; 159 } 160 161 static int aes_siv_get_ctx_params(void *vctx, OSSL_PARAM params[]) 162 { 163 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 164 SIV128_CONTEXT *sctx = &ctx->siv; 165 OSSL_PARAM *p; 166 167 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG); 168 if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) { 169 if (!ctx->enc 170 || p->data_size != ctx->taglen 171 || !OSSL_PARAM_set_octet_string(p, &sctx->tag.byte, ctx->taglen)) { 172 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 173 return 0; 174 } 175 } 176 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN); 177 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->taglen)) { 178 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 179 return 0; 180 } 181 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 182 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) { 183 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 184 return 0; 185 } 186 return 1; 187 } 188 189 static const OSSL_PARAM aes_siv_known_gettable_ctx_params[] = { 190 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 191 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), 192 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), 193 OSSL_PARAM_END 194 }; 195 static const OSSL_PARAM *aes_siv_gettable_ctx_params(ossl_unused void *cctx, 196 ossl_unused void *provctx) 197 { 198 return aes_siv_known_gettable_ctx_params; 199 } 200 201 static int aes_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 202 { 203 PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx; 204 const OSSL_PARAM *p; 205 unsigned int speed = 0; 206 207 if (params == NULL) 208 return 1; 209 210 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG); 211 if (p != NULL) { 212 if (ctx->enc) 213 return 1; 214 if (p->data_type != OSSL_PARAM_OCTET_STRING 215 || !ctx->hw->settag(ctx, p->data, p->data_size)) { 216 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 217 return 0; 218 } 219 } 220 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED); 221 if (p != NULL) { 222 if (!OSSL_PARAM_get_uint(p, &speed)) { 223 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 224 return 0; 225 } 226 ctx->hw->setspeed(ctx, (int)speed); 227 } 228 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); 229 if (p != NULL) { 230 size_t keylen; 231 232 if (!OSSL_PARAM_get_size_t(p, &keylen)) { 233 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 234 return 0; 235 } 236 /* The key length can not be modified */ 237 if (keylen != ctx->keylen) 238 return 0; 239 } 240 return 1; 241 } 242 243 static const OSSL_PARAM aes_siv_known_settable_ctx_params[] = { 244 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 245 OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL), 246 OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0), 247 OSSL_PARAM_END 248 }; 249 static const OSSL_PARAM *aes_siv_settable_ctx_params(ossl_unused void *cctx, 250 ossl_unused void *provctx) 251 { 252 return aes_siv_known_settable_ctx_params; 253 } 254 255 #define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits) \ 256 static OSSL_FUNC_cipher_newctx_fn alg##kbits##lc##_newctx; \ 257 static OSSL_FUNC_cipher_freectx_fn alg##_##lc##_freectx; \ 258 static OSSL_FUNC_cipher_dupctx_fn lc##_dupctx; \ 259 static OSSL_FUNC_cipher_encrypt_init_fn lc##_einit; \ 260 static OSSL_FUNC_cipher_decrypt_init_fn lc##_dinit; \ 261 static OSSL_FUNC_cipher_update_fn lc##_stream_update; \ 262 static OSSL_FUNC_cipher_final_fn lc##_stream_final; \ 263 static OSSL_FUNC_cipher_cipher_fn lc##_cipher; \ 264 static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ 265 static OSSL_FUNC_cipher_get_ctx_params_fn alg##_##lc##_get_ctx_params; \ 266 static OSSL_FUNC_cipher_gettable_ctx_params_fn \ 267 alg##_##lc##_gettable_ctx_params; \ 268 static OSSL_FUNC_cipher_set_ctx_params_fn alg##_##lc##_set_ctx_params; \ 269 static OSSL_FUNC_cipher_settable_ctx_params_fn \ 270 alg##_##lc##_settable_ctx_params; \ 271 static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ 272 { \ 273 return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ 274 flags, 2*kbits, blkbits, ivbits); \ 275 } \ 276 static void * alg##kbits##lc##_newctx(void *provctx) \ 277 { \ 278 return alg##_##lc##_newctx(provctx, 2*kbits, EVP_CIPH_##UCMODE##_MODE, \ 279 flags); \ 280 } \ 281 const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = { \ 282 { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))alg##kbits##lc##_newctx }, \ 283 { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))alg##_##lc##_freectx }, \ 284 { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) lc##_dupctx }, \ 285 { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void)) lc##_einit }, \ 286 { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void)) lc##_dinit }, \ 287 { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void)) lc##_stream_update }, \ 288 { OSSL_FUNC_CIPHER_FINAL, (void (*)(void)) lc##_stream_final }, \ 289 { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void)) lc##_cipher }, \ 290 { OSSL_FUNC_CIPHER_GET_PARAMS, \ 291 (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \ 292 { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ 293 (void (*)(void))ossl_cipher_generic_gettable_params }, \ 294 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ 295 (void (*)(void)) alg##_##lc##_get_ctx_params }, \ 296 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ 297 (void (*)(void)) alg##_##lc##_gettable_ctx_params }, \ 298 { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ 299 (void (*)(void)) alg##_##lc##_set_ctx_params }, \ 300 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ 301 (void (*)(void)) alg##_##lc##_settable_ctx_params }, \ 302 { 0, NULL } \ 303 }; 304 305 IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 128, 8, 0) 306 IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 192, 8, 0) 307 IMPLEMENT_cipher(aes, siv, SIV, SIV_FLAGS, 256, 8, 0) 308