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