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)) != NULL) { 246 if (p->data_type != OSSL_PARAM_UTF8_STRING) 247 return 0; 248 mdname = p->data; 249 } 250 } 251 if (ciphername == NULL) { 252 if ((p = OSSL_PARAM_locate_const(params, 253 OSSL_ALG_PARAM_CIPHER)) != NULL) { 254 if (p->data_type != OSSL_PARAM_UTF8_STRING) 255 return 0; 256 ciphername = p->data; 257 } 258 } 259 if (engine == NULL) { 260 if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE)) 261 != NULL) { 262 if (p->data_type != OSSL_PARAM_UTF8_STRING) 263 return 0; 264 engine = p->data; 265 } 266 } 267 } 268 269 if (mdname != NULL) 270 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 271 (char *)mdname, 0); 272 if (ciphername != NULL) 273 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, 274 (char *)ciphername, 0); 275 if (properties != NULL) 276 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, 277 (char *)properties, 0); 278 279 #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) 280 if (engine != NULL) 281 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE, 282 (char *) engine, 0); 283 #endif 284 285 if (key != NULL) 286 *mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 287 (unsigned char *)key, 288 keylen); 289 290 *mp = OSSL_PARAM_construct_end(); 291 292 return EVP_MAC_CTX_set_params(macctx, mac_params); 293 294 } 295 296 int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, 297 const OSSL_PARAM params[], 298 const char *macname, 299 const char *ciphername, 300 const char *mdname, 301 OSSL_LIB_CTX *libctx) 302 { 303 const OSSL_PARAM *p; 304 const char *properties = NULL; 305 306 if (macname == NULL 307 && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) { 308 if (p->data_type != OSSL_PARAM_UTF8_STRING) 309 return 0; 310 macname = p->data; 311 } 312 if ((p = OSSL_PARAM_locate_const(params, 313 OSSL_ALG_PARAM_PROPERTIES)) != NULL) { 314 if (p->data_type != OSSL_PARAM_UTF8_STRING) 315 return 0; 316 properties = p->data; 317 } 318 319 /* If we got a new mac name, we make a new EVP_MAC_CTX */ 320 if (macname != NULL) { 321 EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties); 322 323 EVP_MAC_CTX_free(*macctx); 324 *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac); 325 /* The context holds on to the MAC */ 326 EVP_MAC_free(mac); 327 if (*macctx == NULL) 328 return 0; 329 } 330 331 /* 332 * If there is no MAC yet (and therefore, no MAC context), we ignore 333 * all other parameters. 334 */ 335 if (*macctx == NULL) 336 return 1; 337 338 if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL, 339 properties, NULL, 0)) 340 return 1; 341 342 EVP_MAC_CTX_free(*macctx); 343 *macctx = NULL; 344 return 0; 345 } 346 347 void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, 348 OSSL_ALGORITHM *out) 349 { 350 int i, j; 351 352 if (out[0].algorithm_names == NULL) { 353 for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) { 354 if (in[i].capable == NULL || in[i].capable()) 355 out[j++] = in[i].alg; 356 } 357 out[j++] = in[i].alg; 358 } 359 } 360 361 /* Duplicate a lump of memory safely */ 362 int ossl_prov_memdup(const void *src, size_t src_len, 363 unsigned char **dest, size_t *dest_len) 364 { 365 if (src != NULL) { 366 if ((*dest = OPENSSL_memdup(src, src_len)) == NULL) 367 return 0; 368 *dest_len = src_len; 369 } else { 370 *dest = NULL; 371 *dest_len = 0; 372 } 373 return 1; 374 } 375