1 /* 2 * Copyright 2020-2024 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 /* 11 * This file uses the low level AES functions (which are deprecated for 12 * non-internal use) in order to implement provider AES ciphers. 13 */ 14 #include "internal/deprecated.h" 15 16 #include <openssl/core.h> 17 #include <openssl/core_names.h> 18 #include <openssl/params.h> 19 #include <openssl/proverr.h> 20 #include "prov/providercommon.h" 21 #include "prov/ciphercommon.h" 22 #include "prov/ciphercommon_aead.h" 23 #include "testutil.h" 24 #include "fake_pipelineprov.h" 25 26 /* 27 * This file provides a fake provider that implements a pipeline cipher 28 * for AES GCM. 29 */ 30 31 typedef struct fake_pipeline_ctx_st { 32 size_t keylen; 33 size_t ivlen; 34 size_t numpipes; 35 EVP_CIPHER *cipher; 36 EVP_CIPHER_CTX *cipher_ctxs[EVP_MAX_PIPES]; 37 } CIPHER_PIPELINE_CTX; 38 39 static void *fake_pipeline_newctx(void *provctx, char *ciphername, 40 size_t kbits, size_t ivbits) 41 { 42 CIPHER_PIPELINE_CTX *ctx; 43 44 if (!ossl_prov_is_running()) 45 return NULL; 46 47 ctx = OPENSSL_zalloc(sizeof(*ctx)); 48 if (ctx == NULL) 49 return NULL; 50 51 ctx->keylen = kbits / 8; 52 ctx->ivlen = ivbits / 8; 53 ctx->numpipes = 0; 54 ctx->cipher = EVP_CIPHER_fetch(provctx, ciphername, "provider=default"); 55 56 return ctx; 57 } 58 59 static OSSL_FUNC_cipher_freectx_fn fake_pipeline_freectx; 60 static void fake_pipeline_freectx(void *vctx) 61 { 62 CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; 63 size_t i; 64 65 EVP_CIPHER_free(ctx->cipher); 66 for (i = 0; i < ctx->numpipes; i++) 67 EVP_CIPHER_CTX_free(ctx->cipher_ctxs[i]); 68 OPENSSL_clear_free(ctx, sizeof(*ctx)); 69 } 70 71 OSSL_FUNC_cipher_pipeline_encrypt_init_fn fake_pipeline_einit; 72 OSSL_FUNC_cipher_pipeline_decrypt_init_fn fake_pipeline_dinit; 73 OSSL_FUNC_cipher_pipeline_update_fn fake_pipeline_update; 74 OSSL_FUNC_cipher_pipeline_final_fn fake_pipeline_final; 75 OSSL_FUNC_cipher_gettable_ctx_params_fn fake_pipeline_aead_gettable_ctx_params; 76 OSSL_FUNC_cipher_get_ctx_params_fn fake_pipeline_aead_get_ctx_params; 77 OSSL_FUNC_cipher_settable_ctx_params_fn fake_pipeline_aead_settable_ctx_params; 78 OSSL_FUNC_cipher_set_ctx_params_fn fake_pipeline_aead_set_ctx_params; 79 80 static int fake_pipeline_init(void *vctx, 81 const unsigned char *key, size_t keylen, 82 size_t numpipes, const unsigned char **iv, 83 size_t ivlen, int enc) 84 { 85 CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; 86 size_t i = 0; 87 88 ctx->numpipes = numpipes; 89 for (i = 0; i < numpipes; i++) { 90 ctx->cipher_ctxs[i] = EVP_CIPHER_CTX_new(); 91 if (ctx->cipher_ctxs[i] == NULL) 92 return 0; 93 if (!EVP_CipherInit(ctx->cipher_ctxs[i], ctx->cipher, key, iv[i], enc)) 94 return 0; 95 } 96 97 return 1; 98 } 99 100 int fake_pipeline_einit(void *vctx, 101 const unsigned char *key, size_t keylen, 102 size_t numpipes, const unsigned char **iv, 103 size_t ivlen, const OSSL_PARAM params[]) 104 { 105 return fake_pipeline_init(vctx, key, keylen, numpipes, iv, ivlen, 1); 106 } 107 108 int fake_pipeline_dinit(void *vctx, 109 const unsigned char *key, size_t keylen, 110 size_t numpipes, const unsigned char **iv, 111 size_t ivlen, const OSSL_PARAM params[]) 112 { 113 return fake_pipeline_init(vctx, key, keylen, numpipes, iv, ivlen, 0); 114 } 115 116 int fake_pipeline_update(void *vctx, size_t numpipes, 117 unsigned char **out, size_t *outl, 118 const size_t *outsize, 119 const unsigned char **in, const size_t *inl) 120 { 121 CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; 122 int ioutl, inl_; 123 size_t i = 0; 124 125 for (i = 0; i < numpipes; i++) { 126 inl_ = (int)inl[i]; 127 if (!EVP_CipherUpdate(ctx->cipher_ctxs[i], 128 (out != NULL) ? out[i] : NULL, 129 &ioutl, 130 in[i], inl_)) 131 return 0; 132 outl[i] = (size_t)ioutl; 133 } 134 return 1; 135 } 136 137 int fake_pipeline_final(void *vctx, size_t numpipes, 138 unsigned char **out, size_t *outl, 139 const size_t *outsize) 140 { 141 CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; 142 int ioutl; 143 size_t i = 0; 144 145 for (i = 0; i < numpipes; i++) { 146 if (!EVP_CipherFinal(ctx->cipher_ctxs[i], out[i], &ioutl)) 147 return 0; 148 outl[i] = (size_t)ioutl; 149 } 150 return 1; 151 } 152 153 static const OSSL_PARAM fake_pipeline_aead_known_gettable_ctx_params[] = { 154 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 155 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), 156 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL), 157 OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, NULL, 0), 158 OSSL_PARAM_END 159 }; 160 const OSSL_PARAM *fake_pipeline_aead_gettable_ctx_params(ossl_unused void *cctx, 161 ossl_unused void *provctx) 162 { 163 return fake_pipeline_aead_known_gettable_ctx_params; 164 } 165 166 static const OSSL_PARAM fake_pipeline_aead_known_settable_ctx_params[] = { 167 OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, NULL, 0), 168 OSSL_PARAM_END 169 }; 170 const OSSL_PARAM *fake_pipeline_aead_settable_ctx_params(ossl_unused void *cctx, 171 ossl_unused void *provctx) 172 { 173 return fake_pipeline_aead_known_settable_ctx_params; 174 } 175 176 int fake_pipeline_aead_get_ctx_params(void *vctx, OSSL_PARAM params[]) 177 { 178 CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; 179 OSSL_PARAM *p; 180 size_t taglen, i; 181 unsigned char **aead_tags = NULL; 182 OSSL_PARAM aead_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 183 184 if (ossl_param_is_empty(params)) 185 return 1; 186 187 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); 188 if (p != NULL) { 189 if (!OSSL_PARAM_set_size_t(p, ctx->ivlen)) { 190 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 191 return 0; 192 } 193 } 194 195 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 196 if (p != NULL) { 197 if (!OSSL_PARAM_set_size_t(p, ctx->keylen)) { 198 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 199 return 0; 200 } 201 } 202 203 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG); 204 if (p != NULL) { 205 if (!OSSL_PARAM_get_octet_ptr(p, (const void **)&aead_tags, &taglen)) { 206 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 207 return 0; 208 } 209 for (i = 0; i < ctx->numpipes; i++) { 210 aead_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, 211 (void *)aead_tags[i], 212 taglen); 213 if (!EVP_CIPHER_CTX_get_params(ctx->cipher_ctxs[i], aead_params)) { 214 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 215 return 0; 216 } 217 } 218 } 219 220 return 1; 221 } 222 223 int fake_pipeline_aead_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 224 { 225 CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx; 226 const OSSL_PARAM *p; 227 size_t taglen, i; 228 unsigned char **aead_tags = NULL; 229 OSSL_PARAM aead_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; 230 231 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG); 232 if (p != NULL) { 233 if (!OSSL_PARAM_get_octet_ptr(p, (const void **)&aead_tags, &taglen)) { 234 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 235 return 0; 236 } 237 for (i = 0; i < ctx->numpipes; i++) { 238 aead_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, 239 (void *)aead_tags[i], 240 taglen); 241 if (!EVP_CIPHER_CTX_set_params(ctx->cipher_ctxs[i], aead_params)) { 242 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 243 return 0; 244 } 245 } 246 } 247 248 /* No other settable ctx param */ 249 return 1; 250 } 251 252 #define IMPLEMENT_aead_cipher_pipeline(alg, lc, UCMODE, flags, kbits, blkbits, \ 253 ivbits, ciphername) \ 254 static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params; \ 255 static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[]) \ 256 { \ 257 return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ 258 flags, kbits, blkbits, ivbits); \ 259 } \ 260 static OSSL_FUNC_cipher_newctx_fn fake_pipeline_##alg##_##kbits##_##lc##_newctx; \ 261 static void * fake_pipeline_##alg##_##kbits##_##lc##_newctx(void *provctx) \ 262 { \ 263 return fake_pipeline_newctx(provctx, ciphername, kbits, ivbits); \ 264 } \ 265 static const OSSL_DISPATCH fake_pipeline_##alg##kbits##lc##_functions[] = { \ 266 { OSSL_FUNC_CIPHER_NEWCTX, \ 267 (void (*)(void))fake_pipeline_##alg##_##kbits##_##lc##_newctx }, \ 268 { OSSL_FUNC_CIPHER_FREECTX, \ 269 (void (*)(void))fake_pipeline_freectx }, \ 270 { OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT, \ 271 (void (*)(void))fake_pipeline_einit }, \ 272 { OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT, \ 273 (void (*)(void))fake_pipeline_dinit }, \ 274 { OSSL_FUNC_CIPHER_PIPELINE_UPDATE, \ 275 (void (*)(void))fake_pipeline_update }, \ 276 { OSSL_FUNC_CIPHER_PIPELINE_FINAL, \ 277 (void (*)(void))fake_pipeline_final }, \ 278 { OSSL_FUNC_CIPHER_GET_PARAMS, \ 279 (void (*)(void)) alg##_##kbits##_##lc##_get_params }, \ 280 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ 281 (void (*)(void)) fake_pipeline_aead_get_ctx_params }, \ 282 { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ 283 (void (*)(void)) fake_pipeline_aead_set_ctx_params }, \ 284 { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ 285 (void (*)(void)) ossl_cipher_generic_gettable_params }, \ 286 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ 287 (void (*)(void)) fake_pipeline_aead_gettable_ctx_params }, \ 288 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ 289 (void (*)(void)) fake_pipeline_aead_settable_ctx_params }, \ 290 OSSL_DISPATCH_END \ 291 } 292 293 IMPLEMENT_aead_cipher_pipeline(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96, "AES-256-GCM"); 294 295 static const OSSL_ALGORITHM fake_ciphers[] = { 296 {"AES-256-GCM", "provider=fake-pipeline", fake_pipeline_aes256gcm_functions}, 297 {NULL, NULL, NULL} 298 }; 299 300 static const OSSL_ALGORITHM *fake_pipeline_query(OSSL_PROVIDER *prov, 301 int operation_id, 302 int *no_cache) 303 { 304 *no_cache = 0; 305 switch (operation_id) { 306 case OSSL_OP_CIPHER: 307 return fake_ciphers; 308 } 309 return NULL; 310 } 311 312 /* Functions we provide to the core */ 313 static const OSSL_DISPATCH fake_pipeline_method[] = { 314 { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free }, 315 { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_pipeline_query }, 316 OSSL_DISPATCH_END 317 }; 318 319 static int fake_pipeline_provider_init(const OSSL_CORE_HANDLE *handle, 320 const OSSL_DISPATCH *in, 321 const OSSL_DISPATCH **out, void **provctx) 322 { 323 if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new())) 324 return 0; 325 *out = fake_pipeline_method; 326 return 1; 327 } 328 329 OSSL_PROVIDER *fake_pipeline_start(OSSL_LIB_CTX *libctx) 330 { 331 OSSL_PROVIDER *p; 332 333 if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "fake-pipeline", 334 fake_pipeline_provider_init)) 335 || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, "fake-pipeline", 1))) 336 return NULL; 337 338 return p; 339 } 340 341 void fake_pipeline_finish(OSSL_PROVIDER *p) 342 { 343 OSSL_PROVIDER_unload(p); 344 } 345