1 /* 2 * Copyright 2006-2022 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 #include <stdio.h> 11 #include <stdlib.h> 12 #include <openssl/core.h> 13 #include <openssl/core_names.h> 14 #include "internal/cryptlib.h" 15 #include "internal/core.h" 16 #include <openssl/objects.h> 17 #include <openssl/evp.h> 18 #include "crypto/bn.h" 19 #ifndef FIPS_MODULE 20 # include "crypto/asn1.h" 21 #endif 22 #include "crypto/evp.h" 23 #include "evp_local.h" 24 25 static int gen_init(EVP_PKEY_CTX *ctx, int operation) 26 { 27 int ret = 0; 28 29 if (ctx == NULL) 30 goto not_supported; 31 32 evp_pkey_ctx_free_old_ops(ctx); 33 ctx->operation = operation; 34 35 if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL) 36 goto legacy; 37 38 switch (operation) { 39 case EVP_PKEY_OP_PARAMGEN: 40 ctx->op.keymgmt.genctx = 41 evp_keymgmt_gen_init(ctx->keymgmt, 42 OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, NULL); 43 break; 44 case EVP_PKEY_OP_KEYGEN: 45 ctx->op.keymgmt.genctx = 46 evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR, 47 NULL); 48 break; 49 } 50 51 if (ctx->op.keymgmt.genctx == NULL) 52 ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); 53 else 54 ret = 1; 55 goto end; 56 57 legacy: 58 #ifdef FIPS_MODULE 59 goto not_supported; 60 #else 61 if (ctx->pmeth == NULL 62 || (operation == EVP_PKEY_OP_PARAMGEN 63 && ctx->pmeth->paramgen == NULL) 64 || (operation == EVP_PKEY_OP_KEYGEN 65 && ctx->pmeth->keygen == NULL)) 66 goto not_supported; 67 68 ret = 1; 69 switch (operation) { 70 case EVP_PKEY_OP_PARAMGEN: 71 if (ctx->pmeth->paramgen_init != NULL) 72 ret = ctx->pmeth->paramgen_init(ctx); 73 break; 74 case EVP_PKEY_OP_KEYGEN: 75 if (ctx->pmeth->keygen_init != NULL) 76 ret = ctx->pmeth->keygen_init(ctx); 77 break; 78 } 79 #endif 80 81 end: 82 if (ret <= 0 && ctx != NULL) { 83 evp_pkey_ctx_free_old_ops(ctx); 84 ctx->operation = EVP_PKEY_OP_UNDEFINED; 85 } 86 return ret; 87 88 not_supported: 89 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 90 ret = -2; 91 goto end; 92 } 93 94 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) 95 { 96 return gen_init(ctx, EVP_PKEY_OP_PARAMGEN); 97 } 98 99 int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) 100 { 101 return gen_init(ctx, EVP_PKEY_OP_KEYGEN); 102 } 103 104 static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg) 105 { 106 EVP_PKEY_CTX *ctx = arg; 107 const OSSL_PARAM *param = NULL; 108 int p = -1, n = -1; 109 110 if (ctx->pkey_gencb == NULL) 111 return 1; /* No callback? That's fine */ 112 113 if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL)) 114 == NULL 115 || !OSSL_PARAM_get_int(param, &p)) 116 return 0; 117 if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION)) 118 == NULL 119 || !OSSL_PARAM_get_int(param, &n)) 120 return 0; 121 122 ctx->keygen_info[0] = p; 123 ctx->keygen_info[1] = n; 124 125 return ctx->pkey_gencb(ctx); 126 } 127 128 int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) 129 { 130 int ret = 0; 131 EVP_PKEY *allocated_pkey = NULL; 132 /* Legacy compatible keygen callback info, only used with provider impls */ 133 int gentmp[2]; 134 135 if (ppkey == NULL) 136 return -1; 137 138 if (ctx == NULL) 139 goto not_supported; 140 141 if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0) 142 goto not_initialized; 143 144 if (*ppkey == NULL) 145 *ppkey = allocated_pkey = EVP_PKEY_new(); 146 147 if (*ppkey == NULL) { 148 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 149 return -1; 150 } 151 152 if (ctx->op.keymgmt.genctx == NULL) 153 goto legacy; 154 155 /* 156 * Asssigning gentmp to ctx->keygen_info is something our legacy 157 * implementations do. Because the provider implementations aren't 158 * allowed to reach into our EVP_PKEY_CTX, we need to provide similar 159 * space for backward compatibility. It's ok that we attach a local 160 * variable, as it should only be useful in the calls down from here. 161 * This is cleared as soon as it isn't useful any more, i.e. directly 162 * after the evp_keymgmt_util_gen() call. 163 */ 164 ctx->keygen_info = gentmp; 165 ctx->keygen_info_count = 2; 166 167 ret = 1; 168 if (ctx->pkey != NULL) { 169 EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt; 170 void *keydata = 171 evp_pkey_export_to_provider(ctx->pkey, ctx->libctx, 172 &tmp_keymgmt, ctx->propquery); 173 174 if (tmp_keymgmt == NULL) 175 goto not_supported; 176 /* 177 * It's ok if keydata is NULL here. The backend is expected to deal 178 * with that as it sees fit. 179 */ 180 ret = evp_keymgmt_gen_set_template(ctx->keymgmt, 181 ctx->op.keymgmt.genctx, keydata); 182 } 183 184 /* 185 * the returned value from evp_keymgmt_util_gen() is cached in *ppkey, 186 * so we do not need to save it, just check it. 187 */ 188 ret = ret 189 && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx, 190 ossl_callback_to_pkey_gencb, ctx) 191 != NULL); 192 193 ctx->keygen_info = NULL; 194 195 #ifndef FIPS_MODULE 196 /* In case |*ppkey| was originally a legacy key */ 197 if (ret) 198 evp_pkey_free_legacy(*ppkey); 199 #endif 200 201 /* 202 * Because we still have legacy keys 203 */ 204 (*ppkey)->type = ctx->legacy_keytype; 205 206 goto end; 207 208 legacy: 209 #ifdef FIPS_MODULE 210 goto not_supported; 211 #else 212 /* 213 * If we get here then we're using legacy paramgen/keygen. In that case 214 * the pkey in ctx (if there is one) had better not be provided (because the 215 * legacy methods may not know how to handle it). However we can only get 216 * here if ctx->op.keymgmt.genctx == NULL, but that should never be the case 217 * if ctx->pkey is provided because we don't allow this when we initialise 218 * the ctx. 219 */ 220 if (ctx->pkey != NULL && !ossl_assert(!evp_pkey_is_provided(ctx->pkey))) 221 goto not_accessible; 222 223 switch (ctx->operation) { 224 case EVP_PKEY_OP_PARAMGEN: 225 ret = ctx->pmeth->paramgen(ctx, *ppkey); 226 break; 227 case EVP_PKEY_OP_KEYGEN: 228 ret = ctx->pmeth->keygen(ctx, *ppkey); 229 break; 230 default: 231 goto not_supported; 232 } 233 #endif 234 235 end: 236 if (ret <= 0) { 237 if (allocated_pkey != NULL) 238 *ppkey = NULL; 239 EVP_PKEY_free(allocated_pkey); 240 } 241 return ret; 242 243 not_supported: 244 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 245 ret = -2; 246 goto end; 247 not_initialized: 248 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 249 ret = -1; 250 goto end; 251 #ifndef FIPS_MODULE 252 not_accessible: 253 ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS); 254 ret = -1; 255 goto end; 256 #endif 257 } 258 259 int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) 260 { 261 if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { 262 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 263 return -1; 264 } 265 return EVP_PKEY_generate(ctx, ppkey); 266 } 267 268 int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) 269 { 270 if (ctx->operation != EVP_PKEY_OP_KEYGEN) { 271 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED); 272 return -1; 273 } 274 return EVP_PKEY_generate(ctx, ppkey); 275 } 276 277 void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb) 278 { 279 ctx->pkey_gencb = cb; 280 } 281 282 EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx) 283 { 284 return ctx->pkey_gencb; 285 } 286 287 /* 288 * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style 289 * callbacks. 290 */ 291 292 static int trans_cb(int a, int b, BN_GENCB *gcb) 293 { 294 EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb); 295 ctx->keygen_info[0] = a; 296 ctx->keygen_info[1] = b; 297 return ctx->pkey_gencb(ctx); 298 } 299 300 void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx) 301 { 302 BN_GENCB_set(cb, trans_cb, ctx); 303 } 304 305 int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx) 306 { 307 if (idx == -1) 308 return ctx->keygen_info_count; 309 if (idx < 0 || idx > ctx->keygen_info_count) 310 return 0; 311 return ctx->keygen_info[idx]; 312 } 313 314 #ifndef FIPS_MODULE 315 316 EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, 317 const unsigned char *key, int keylen) 318 { 319 EVP_PKEY_CTX *mac_ctx = NULL; 320 EVP_PKEY *mac_key = NULL; 321 mac_ctx = EVP_PKEY_CTX_new_id(type, e); 322 if (!mac_ctx) 323 return NULL; 324 if (EVP_PKEY_keygen_init(mac_ctx) <= 0) 325 goto merr; 326 if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0) 327 goto merr; 328 if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0) 329 goto merr; 330 merr: 331 EVP_PKEY_CTX_free(mac_ctx); 332 return mac_key; 333 } 334 335 #endif /* FIPS_MODULE */ 336 337 /*- All methods below can also be used in FIPS_MODULE */ 338 339 static int fromdata_init(EVP_PKEY_CTX *ctx, int operation) 340 { 341 if (ctx == NULL || ctx->keytype == NULL) 342 goto not_supported; 343 344 evp_pkey_ctx_free_old_ops(ctx); 345 if (ctx->keymgmt == NULL) 346 goto not_supported; 347 348 ctx->operation = operation; 349 return 1; 350 351 not_supported: 352 if (ctx != NULL) 353 ctx->operation = EVP_PKEY_OP_UNDEFINED; 354 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 355 return -2; 356 } 357 358 int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx) 359 { 360 return fromdata_init(ctx, EVP_PKEY_OP_FROMDATA); 361 } 362 363 int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection, 364 OSSL_PARAM params[]) 365 { 366 void *keydata = NULL; 367 EVP_PKEY *allocated_pkey = NULL; 368 369 if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_FROMDATA) == 0) { 370 ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); 371 return -2; 372 } 373 374 if (ppkey == NULL) 375 return -1; 376 377 if (*ppkey == NULL) 378 allocated_pkey = *ppkey = EVP_PKEY_new(); 379 380 if (*ppkey == NULL) { 381 ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE); 382 return -1; 383 } 384 385 keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection, params); 386 if (keydata == NULL) { 387 if (allocated_pkey != NULL) { 388 *ppkey = NULL; 389 EVP_PKEY_free(allocated_pkey); 390 } 391 return 0; 392 } 393 /* keydata is cached in *ppkey, so we need not bother with it further */ 394 return 1; 395 } 396 397 const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection) 398 { 399 /* We call fromdata_init to get ctx->keymgmt populated */ 400 if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED) == 1) 401 return evp_keymgmt_import_types(ctx->keymgmt, selection); 402 return NULL; 403 } 404 405 static OSSL_CALLBACK ossl_pkey_todata_cb; 406 407 static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg) 408 { 409 OSSL_PARAM **ret = arg; 410 411 *ret = OSSL_PARAM_dup(params); 412 return 1; 413 } 414 415 int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params) 416 { 417 if (params == NULL) 418 return 0; 419 return EVP_PKEY_export(pkey, selection, ossl_pkey_todata_cb, params); 420 } 421 422 #ifndef FIPS_MODULE 423 struct fake_import_data_st { 424 OSSL_CALLBACK *export_cb; 425 void *export_cbarg; 426 }; 427 428 static OSSL_FUNC_keymgmt_import_fn pkey_fake_import; 429 static int pkey_fake_import(void *fake_keydata, int ignored_selection, 430 const OSSL_PARAM params[]) 431 { 432 struct fake_import_data_st *data = fake_keydata; 433 434 return data->export_cb(params, data->export_cbarg); 435 } 436 #endif 437 438 int EVP_PKEY_export(const EVP_PKEY *pkey, int selection, 439 OSSL_CALLBACK *export_cb, void *export_cbarg) 440 { 441 if (pkey == NULL) { 442 ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER); 443 return 0; 444 } 445 #ifndef FIPS_MODULE 446 if (evp_pkey_is_legacy(pkey)) { 447 struct fake_import_data_st data; 448 449 data.export_cb = export_cb; 450 data.export_cbarg = export_cbarg; 451 452 /* 453 * We don't need to care about libctx or propq here, as we're only 454 * interested in the resulting OSSL_PARAM array. 455 */ 456 return pkey->ameth->export_to(pkey, &data, pkey_fake_import, 457 NULL, NULL); 458 } 459 #endif 460 return evp_keymgmt_util_export(pkey, selection, export_cb, export_cbarg); 461 } 462