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