1 /* 2 * Copyright 2019-2021 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/provider_util.h" 22 #include "internal/nelem.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 (params == NULL) 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 (params == NULL) 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 const EVP_MD *ossl_prov_digest_md(const PROV_DIGEST *pd) 215 { 216 return pd->md; 217 } 218 219 ENGINE *ossl_prov_digest_engine(const PROV_DIGEST *pd) 220 { 221 return pd->engine; 222 } 223 224 int ossl_prov_set_macctx(EVP_MAC_CTX *macctx, 225 const OSSL_PARAM params[], 226 const char *ciphername, 227 const char *mdname, 228 const char *engine, 229 const char *properties, 230 const unsigned char *key, 231 size_t keylen) 232 { 233 const OSSL_PARAM *p; 234 OSSL_PARAM mac_params[6], *mp = mac_params; 235 236 if (params != NULL) { 237 if (mdname == NULL) { 238 if ((p = OSSL_PARAM_locate_const(params, 239 OSSL_ALG_PARAM_DIGEST)) != NULL) { 240 if (p->data_type != OSSL_PARAM_UTF8_STRING) 241 return 0; 242 mdname = p->data; 243 } 244 } 245 if (ciphername == NULL) { 246 if ((p = OSSL_PARAM_locate_const(params, 247 OSSL_ALG_PARAM_CIPHER)) != NULL) { 248 if (p->data_type != OSSL_PARAM_UTF8_STRING) 249 return 0; 250 ciphername = p->data; 251 } 252 } 253 if (engine == NULL) { 254 if ((p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_ENGINE)) 255 != NULL) { 256 if (p->data_type != OSSL_PARAM_UTF8_STRING) 257 return 0; 258 engine = p->data; 259 } 260 } 261 } 262 263 if (mdname != NULL) 264 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, 265 (char *)mdname, 0); 266 if (ciphername != NULL) 267 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, 268 (char *)ciphername, 0); 269 if (properties != NULL) 270 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_PROPERTIES, 271 (char *)properties, 0); 272 273 #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) 274 if (engine != NULL) 275 *mp++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_ENGINE, 276 (char *) engine, 0); 277 #endif 278 279 if (key != NULL) 280 *mp++ = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY, 281 (unsigned char *)key, 282 keylen); 283 284 *mp = OSSL_PARAM_construct_end(); 285 286 return EVP_MAC_CTX_set_params(macctx, mac_params); 287 288 } 289 290 int ossl_prov_macctx_load_from_params(EVP_MAC_CTX **macctx, 291 const OSSL_PARAM params[], 292 const char *macname, 293 const char *ciphername, 294 const char *mdname, 295 OSSL_LIB_CTX *libctx) 296 { 297 const OSSL_PARAM *p; 298 const char *properties = NULL; 299 300 if (macname == NULL 301 && (p = OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_MAC)) != NULL) { 302 if (p->data_type != OSSL_PARAM_UTF8_STRING) 303 return 0; 304 macname = p->data; 305 } 306 if ((p = OSSL_PARAM_locate_const(params, 307 OSSL_ALG_PARAM_PROPERTIES)) != NULL) { 308 if (p->data_type != OSSL_PARAM_UTF8_STRING) 309 return 0; 310 properties = p->data; 311 } 312 313 /* If we got a new mac name, we make a new EVP_MAC_CTX */ 314 if (macname != NULL) { 315 EVP_MAC *mac = EVP_MAC_fetch(libctx, macname, properties); 316 317 EVP_MAC_CTX_free(*macctx); 318 *macctx = mac == NULL ? NULL : EVP_MAC_CTX_new(mac); 319 /* The context holds on to the MAC */ 320 EVP_MAC_free(mac); 321 if (*macctx == NULL) 322 return 0; 323 } 324 325 /* 326 * If there is no MAC yet (and therefore, no MAC context), we ignore 327 * all other parameters. 328 */ 329 if (*macctx == NULL) 330 return 1; 331 332 if (ossl_prov_set_macctx(*macctx, params, ciphername, mdname, NULL, 333 properties, NULL, 0)) 334 return 1; 335 336 EVP_MAC_CTX_free(*macctx); 337 *macctx = NULL; 338 return 0; 339 } 340 341 void ossl_prov_cache_exported_algorithms(const OSSL_ALGORITHM_CAPABLE *in, 342 OSSL_ALGORITHM *out) 343 { 344 int i, j; 345 346 if (out[0].algorithm_names == NULL) { 347 for (i = j = 0; in[i].alg.algorithm_names != NULL; ++i) { 348 if (in[i].capable == NULL || in[i].capable()) 349 out[j++] = in[i].alg; 350 } 351 out[j++] = in[i].alg; 352 } 353 } 354