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