1 1.1 christos /* 2 1.1 christos * Copyright 2019-2025 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 /* We need to use some engine deprecated APIs */ 11 1.1 christos #define OPENSSL_SUPPRESS_DEPRECATED 12 1.1 christos 13 1.1 christos #include <openssl/evp.h> 14 1.1 christos #include <openssl/core_names.h> 15 1.1 christos #include <openssl/err.h> 16 1.1 christos #include <openssl/proverr.h> 17 1.1 christos #ifndef FIPS_MODULE 18 1.1.1.2 christos #include <openssl/engine.h> 19 1.1.1.2 christos #include "crypto/evp.h" 20 1.1 christos #endif 21 1.1 christos #include "prov/providercommon.h" 22 1.1 christos #include "prov/provider_util.h" 23 1.1 christos 24 1.1 christos void ossl_prov_cipher_reset(PROV_CIPHER *pc) 25 1.1 christos { 26 1.1 christos EVP_CIPHER_free(pc->alloc_cipher); 27 1.1 christos pc->alloc_cipher = NULL; 28 1.1 christos pc->cipher = NULL; 29 1.1 christos #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 30 1.1 christos ENGINE_finish(pc->engine); 31 1.1 christos #endif 32 1.1 christos pc->engine = NULL; 33 1.1 christos } 34 1.1 christos 35 1.1 christos int ossl_prov_cipher_copy(PROV_CIPHER *dst, const PROV_CIPHER *src) 36 1.1 christos { 37 1.1 christos if (src->alloc_cipher != NULL && !EVP_CIPHER_up_ref(src->alloc_cipher)) 38 1.1 christos return 0; 39 1.1 christos #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 40 1.1 christos if (src->engine != NULL && !ENGINE_init(src->engine)) { 41 1.1 christos EVP_CIPHER_free(src->alloc_cipher); 42 1.1 christos return 0; 43 1.1 christos } 44 1.1 christos #endif 45 1.1 christos dst->engine = src->engine; 46 1.1 christos dst->cipher = src->cipher; 47 1.1 christos dst->alloc_cipher = src->alloc_cipher; 48 1.1 christos return 1; 49 1.1 christos } 50 1.1 christos 51 1.1 christos static int load_common(const OSSL_PARAM params[], const char **propquery, 52 1.1.1.2 christos ENGINE **engine) 53 1.1 christos { 54 1.1 christos const OSSL_PARAM *p; 55 1.1 christos 56 1.1 christos *propquery = NULL; 57 1.1 christos p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_PROPERTIES); 58 1.1 christos if (p != NULL) { 59 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 60 1.1 christos return 0; 61 1.1 christos *propquery = p->data; 62 1.1 christos } 63 1.1 christos 64 1.1 christos #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 65 1.1 christos ENGINE_finish(*engine); 66 1.1 christos #endif 67 1.1 christos *engine = NULL; 68 1.1 christos /* Inside the FIPS module, we don't support legacy ciphers */ 69 1.1 christos #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 70 1.1 christos p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE); 71 1.1 christos if (p != NULL) { 72 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 73 1.1 christos return 0; 74 1.1 christos /* Get a structural reference */ 75 1.1 christos *engine = ENGINE_by_id(p->data); 76 1.1 christos if (*engine == NULL) 77 1.1 christos return 0; 78 1.1 christos /* Get a functional reference */ 79 1.1 christos if (!ENGINE_init(*engine)) { 80 1.1 christos ENGINE_free(*engine); 81 1.1 christos *engine = NULL; 82 1.1 christos return 0; 83 1.1 christos } 84 1.1 christos /* Free the structural reference */ 85 1.1 christos ENGINE_free(*engine); 86 1.1 christos } 87 1.1 christos #endif 88 1.1 christos return 1; 89 1.1 christos } 90 1.1 christos 91 1.1 christos int ossl_prov_cipher_load_from_params(PROV_CIPHER *pc, 92 1.1.1.2 christos const OSSL_PARAM params[], 93 1.1.1.2 christos OSSL_LIB_CTX *ctx) 94 1.1 christos { 95 1.1 christos const OSSL_PARAM *p; 96 1.1 christos const char *propquery; 97 1.1 christos 98 1.1 christos if (ossl_param_is_empty(params)) 99 1.1 christos return 1; 100 1.1 christos 101 1.1 christos if (!load_common(params, &propquery, &pc->engine)) 102 1.1 christos return 0; 103 1.1 christos 104 1.1 christos p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_CIPHER); 105 1.1 christos if (p == NULL) 106 1.1 christos return 1; 107 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 108 1.1 christos return 0; 109 1.1 christos 110 1.1 christos EVP_CIPHER_free(pc->alloc_cipher); 111 1.1 christos ERR_set_mark(); 112 1.1 christos pc->cipher = pc->alloc_cipher = EVP_CIPHER_fetch(ctx, p->data, propquery); 113 1.1 christos #ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy ciphers */ 114 1.1 christos if (pc->cipher == NULL) { 115 1.1 christos const EVP_CIPHER *cipher; 116 1.1 christos 117 1.1 christos cipher = EVP_get_cipherbyname(p->data); 118 1.1 christos /* Do not use global EVP_CIPHERs */ 119 1.1 christos if (cipher != NULL && cipher->origin != EVP_ORIG_GLOBAL) 120 1.1 christos pc->cipher = cipher; 121 1.1 christos } 122 1.1 christos #endif 123 1.1 christos if (pc->cipher != NULL) 124 1.1 christos ERR_pop_to_mark(); 125 1.1 christos else 126 1.1 christos ERR_clear_last_mark(); 127 1.1 christos return pc->cipher != NULL; 128 1.1 christos } 129 1.1 christos 130 1.1 christos const EVP_CIPHER *ossl_prov_cipher_cipher(const PROV_CIPHER *pc) 131 1.1 christos { 132 1.1 christos return pc->cipher; 133 1.1 christos } 134 1.1 christos 135 1.1 christos ENGINE *ossl_prov_cipher_engine(const PROV_CIPHER *pc) 136 1.1 christos { 137 1.1 christos return pc->engine; 138 1.1 christos } 139 1.1 christos 140 1.1 christos void ossl_prov_digest_reset(PROV_DIGEST *pd) 141 1.1 christos { 142 1.1 christos EVP_MD_free(pd->alloc_md); 143 1.1 christos pd->alloc_md = NULL; 144 1.1 christos pd->md = NULL; 145 1.1 christos #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 146 1.1 christos ENGINE_finish(pd->engine); 147 1.1 christos #endif 148 1.1 christos pd->engine = NULL; 149 1.1 christos } 150 1.1 christos 151 1.1 christos int ossl_prov_digest_copy(PROV_DIGEST *dst, const PROV_DIGEST *src) 152 1.1 christos { 153 1.1 christos if (src->alloc_md != NULL && !EVP_MD_up_ref(src->alloc_md)) 154 1.1 christos return 0; 155 1.1 christos #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 156 1.1 christos if (src->engine != NULL && !ENGINE_init(src->engine)) { 157 1.1 christos EVP_MD_free(src->alloc_md); 158 1.1 christos return 0; 159 1.1 christos } 160 1.1 christos #endif 161 1.1 christos dst->engine = src->engine; 162 1.1 christos dst->md = src->md; 163 1.1 christos dst->alloc_md = src->alloc_md; 164 1.1 christos return 1; 165 1.1 christos } 166 1.1 christos 167 1.1 christos const EVP_MD *ossl_prov_digest_fetch(PROV_DIGEST *pd, OSSL_LIB_CTX *libctx, 168 1.1.1.2 christos const char *mdname, const char *propquery) 169 1.1 christos { 170 1.1 christos EVP_MD_free(pd->alloc_md); 171 1.1 christos pd->md = pd->alloc_md = EVP_MD_fetch(libctx, mdname, propquery); 172 1.1 christos 173 1.1 christos return pd->md; 174 1.1 christos } 175 1.1 christos 176 1.1 christos int ossl_prov_digest_load_from_params(PROV_DIGEST *pd, 177 1.1.1.2 christos const OSSL_PARAM params[], 178 1.1.1.2 christos OSSL_LIB_CTX *ctx) 179 1.1 christos { 180 1.1 christos const OSSL_PARAM *p; 181 1.1 christos const char *propquery; 182 1.1 christos 183 1.1 christos if (ossl_param_is_empty(params)) 184 1.1 christos return 1; 185 1.1 christos 186 1.1 christos if (!load_common(params, &propquery, &pd->engine)) 187 1.1 christos return 0; 188 1.1 christos 189 1.1 christos p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST); 190 1.1 christos if (p == NULL) 191 1.1 christos return 1; 192 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 193 1.1 christos return 0; 194 1.1 christos 195 1.1 christos ERR_set_mark(); 196 1.1 christos ossl_prov_digest_fetch(pd, ctx, p->data, propquery); 197 1.1 christos #ifndef FIPS_MODULE /* Inside the FIPS module, we don't support legacy digests */ 198 1.1 christos if (pd->md == NULL) { 199 1.1 christos const EVP_MD *md; 200 1.1 christos 201 1.1 christos md = EVP_get_digestbyname(p->data); 202 1.1 christos /* Do not use global EVP_MDs */ 203 1.1 christos if (md != NULL && md->origin != EVP_ORIG_GLOBAL) 204 1.1 christos pd->md = md; 205 1.1 christos } 206 1.1 christos #endif 207 1.1 christos if (pd->md != NULL) 208 1.1 christos ERR_pop_to_mark(); 209 1.1 christos else 210 1.1 christos ERR_clear_last_mark(); 211 1.1 christos return pd->md != NULL; 212 1.1 christos } 213 1.1 christos 214 1.1 christos void ossl_prov_digest_set_md(PROV_DIGEST *pd, EVP_MD *md) 215 1.1 christos { 216 1.1 christos ossl_prov_digest_reset(pd); 217 1.1 christos pd->md = pd->alloc_md = md; 218 1.1 christos } 219 1.1 christos 220 1.1 christos const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd) 221 1.1 christos { 222 1.1 christos return pd->md; 223 1.1 christos } 224 1.1 christos 225 1.1 christos ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd) 226 1.1 christos { 227 1.1 christos return pd->engine; 228 1.1 christos } 229 1.1 christos 230 1.1 christos int ossl_prov_set_macctx(EVP_MAC_CTX *macctx, 231 1.1.1.2 christos const OSSL_PARAM params[], 232 1.1.1.2 christos const char *ciphername, 233 1.1.1.2 christos const char *mdname, 234 1.1.1.2 christos const char *engine, 235 1.1.1.2 christos const char *properties, 236 1.1.1.2 christos const unsigned char *key, 237 1.1.1.2 christos size_t keylen) 238 1.1 christos { 239 1.1 christos const OSSL_PARAM *p; 240 1.1 christos OSSL_PARAM mac_params[6], *mp = mac_params; 241 1.1 christos 242 1.1 christos if (params != NULL) { 243 1.1 christos if (mdname == NULL) { 244 1.1 christos if ((p = OSSL_PARAM_locate_const(params, 245 1.1.1.2 christos OSSL_ALG_PARAM_DIGEST)) 246 1.1.1.2 christos != NULL) { 247 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 248 1.1 christos return 0; 249 1.1 christos mdname = p->data; 250 1.1 christos } 251 1.1 christos } 252 1.1 christos if (ciphername == NULL) { 253 1.1 christos if ((p = OSSL_PARAM_locate_const(params, 254 1.1.1.2 christos OSSL_ALG_PARAM_CIPHER)) 255 1.1.1.2 christos != NULL) { 256 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 257 1.1 christos return 0; 258 1.1 christos ciphername = p->data; 259 1.1 christos } 260 1.1 christos } 261 1.1 christos if (engine == NULL) { 262 1.1 christos if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE)) 263 1.1.1.2 christos != NULL) { 264 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 265 1.1 christos return 0; 266 1.1 christos engine = p->data; 267 1.1 christos } 268 1.1 christos } 269 1.1 christos } 270 1.1 christos 271 1.1 christos if (mdname != NULL) 272 1.1 christos *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 273 1.1.1.2 christos (char *)mdname, 0); 274 1.1 christos if (ciphername != NULL) 275 1.1 christos *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, 276 1.1.1.2 christos (char *)ciphername, 0); 277 1.1 christos if (properties != NULL) 278 1.1 christos *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, 279 1.1.1.2 christos (char *)properties, 0); 280 1.1 christos 281 1.1 christos #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) 282 1.1 christos if (engine != NULL) 283 1.1 christos *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE, 284 1.1.1.2 christos (char *)engine, 0); 285 1.1 christos #endif 286 1.1 christos 287 1.1 christos if (key != NULL) 288 1.1 christos *mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 289 1.1.1.2 christos (unsigned char *)key, 290 1.1.1.2 christos keylen); 291 1.1 christos 292 1.1 christos *mp = OSSL_PARAM_construct_end(); 293 1.1 christos 294 1.1 christos return EVP_MAC_CTX_set_params(macctx, mac_params); 295 1.1 christos } 296 1.1 christos 297 1.1 christos int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, 298 1.1.1.2 christos const OSSL_PARAM params[], 299 1.1.1.2 christos const char *macname, 300 1.1.1.2 christos const char *ciphername, 301 1.1.1.2 christos const char *mdname, 302 1.1.1.2 christos OSSL_LIB_CTX *libctx) 303 1.1 christos { 304 1.1 christos const OSSL_PARAM *p; 305 1.1 christos const char *properties = NULL; 306 1.1 christos 307 1.1 christos if (macname == NULL 308 1.1 christos && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) { 309 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 310 1.1 christos return 0; 311 1.1 christos macname = p->data; 312 1.1 christos } 313 1.1 christos if ((p = OSSL_PARAM_locate_const(params, 314 1.1.1.2 christos OSSL_ALG_PARAM_PROPERTIES)) 315 1.1.1.2 christos != NULL) { 316 1.1 christos if (p->data_type != OSSL_PARAM_UTF8_STRING) 317 1.1 christos return 0; 318 1.1 christos properties = p->data; 319 1.1 christos } 320 1.1 christos 321 1.1 christos /* If we got a new mac name, we make a new EVP_MAC_CTX */ 322 1.1 christos if (macname != NULL) { 323 1.1 christos EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties); 324 1.1 christos 325 1.1 christos EVP_MAC_CTX_free(*macctx); 326 1.1 christos *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac); 327 1.1 christos /* The context holds on to the MAC */ 328 1.1 christos EVP_MAC_free(mac); 329 1.1 christos if (*macctx == NULL) 330 1.1 christos return 0; 331 1.1 christos } 332 1.1 christos 333 1.1 christos /* 334 1.1 christos * If there is no MAC yet (and therefore, no MAC context), we ignore 335 1.1 christos * all other parameters. 336 1.1 christos */ 337 1.1 christos if (*macctx == NULL) 338 1.1 christos return 1; 339 1.1 christos 340 1.1 christos if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL, 341 1.1.1.2 christos properties, NULL, 0)) 342 1.1 christos return 1; 343 1.1 christos 344 1.1 christos EVP_MAC_CTX_free(*macctx); 345 1.1 christos *macctx = NULL; 346 1.1 christos return 0; 347 1.1 christos } 348 1.1 christos 349 1.1 christos void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, 350 1.1.1.2 christos OSSL_ALGORITHM *out) 351 1.1 christos { 352 1.1 christos int i, j; 353 1.1 christos 354 1.1 christos if (out[0].algorithm_names == NULL) { 355 1.1 christos for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) { 356 1.1 christos if (in[i].capable == NULL || in[i].capable()) 357 1.1 christos out[j++] = in[i].alg; 358 1.1 christos } 359 1.1 christos out[j++] = in[i].alg; 360 1.1 christos } 361 1.1 christos } 362 1.1 christos 363 1.1 christos /* Duplicate a lump of memory safely */ 364 1.1 christos int ossl_prov_memdup(const void *src, size_t src_len, 365 1.1.1.2 christos unsigned char **dest, size_t *dest_len) 366 1.1 christos { 367 1.1 christos if (src != NULL) { 368 1.1 christos if ((*dest = OPENSSL_memdup(src, src_len)) == NULL) 369 1.1 christos return 0; 370 1.1 christos *dest_len = src_len; 371 1.1 christos } else { 372 1.1 christos *dest = NULL; 373 1.1 christos *dest_len = 0; 374 1.1 christos } 375 1.1 christos return 1; 376 1.1 christos } 377