1 /* 2 * Copyright 2020-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 #include <assert.h> 11 #include <string.h> 12 #include <openssl/core_dispatch.h> 13 #include <openssl/core_names.h> 14 #include <openssl/params.h> 15 #include <openssl/err.h> 16 #include <openssl/proverr.h> 17 #include <openssl/evp.h> 18 #include <openssl/rand.h> 19 #include <openssl/self_test.h> 20 #include "internal/fips.h" 21 #include "internal/param_build_set.h" 22 #include <openssl/param_build.h> 23 #include "crypto/ecx.h" 24 #include "prov/implementations.h" 25 #include "prov/providercommon.h" 26 #include "prov/provider_ctx.h" 27 #include "prov/ecx.h" 28 #include "prov/securitycheck.h" 29 #ifdef S390X_EC_ASM 30 # include "s390x_arch.h" 31 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */ 32 #endif 33 34 static OSSL_FUNC_keymgmt_new_fn x25519_new_key; 35 static OSSL_FUNC_keymgmt_new_fn x448_new_key; 36 static OSSL_FUNC_keymgmt_new_fn ed25519_new_key; 37 static OSSL_FUNC_keymgmt_new_fn ed448_new_key; 38 static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init; 39 static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init; 40 static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init; 41 static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init; 42 static OSSL_FUNC_keymgmt_gen_fn x25519_gen; 43 static OSSL_FUNC_keymgmt_gen_fn x448_gen; 44 static OSSL_FUNC_keymgmt_gen_fn ed25519_gen; 45 static OSSL_FUNC_keymgmt_gen_fn ed448_gen; 46 static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup; 47 static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params; 48 static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params; 49 static OSSL_FUNC_keymgmt_load_fn ecx_load; 50 static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params; 51 static OSSL_FUNC_keymgmt_get_params_fn x448_get_params; 52 static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params; 53 static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params; 54 static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params; 55 static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params; 56 static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params; 57 static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params; 58 static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params; 59 static OSSL_FUNC_keymgmt_set_params_fn x448_set_params; 60 static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params; 61 static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params; 62 static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params; 63 static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params; 64 static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params; 65 static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params; 66 static OSSL_FUNC_keymgmt_has_fn ecx_has; 67 static OSSL_FUNC_keymgmt_match_fn ecx_match; 68 static OSSL_FUNC_keymgmt_validate_fn x25519_validate; 69 static OSSL_FUNC_keymgmt_validate_fn x448_validate; 70 static OSSL_FUNC_keymgmt_validate_fn ed25519_validate; 71 static OSSL_FUNC_keymgmt_validate_fn ed448_validate; 72 static OSSL_FUNC_keymgmt_import_fn ecx_import; 73 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types; 74 static OSSL_FUNC_keymgmt_export_fn ecx_export; 75 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types; 76 static OSSL_FUNC_keymgmt_dup_fn ecx_dup; 77 78 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR) 79 80 struct ecx_gen_ctx { 81 OSSL_LIB_CTX *libctx; 82 char *propq; 83 ECX_KEY_TYPE type; 84 int selection; 85 unsigned char *dhkem_ikm; 86 size_t dhkem_ikmlen; 87 }; 88 89 #ifdef S390X_EC_ASM 90 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx); 91 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx); 92 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx); 93 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx); 94 #endif 95 96 #ifdef FIPS_MODULE 97 static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test); 98 #endif /* FIPS_MODULE */ 99 100 static ossl_inline int ecx_key_type_is_ed(ECX_KEY_TYPE type) 101 { 102 return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448; 103 } 104 105 static void *x25519_new_key(void *provctx) 106 { 107 if (!ossl_prov_is_running()) 108 return 0; 109 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0, 110 NULL); 111 } 112 113 static void *x448_new_key(void *provctx) 114 { 115 if (!ossl_prov_is_running()) 116 return 0; 117 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0, 118 NULL); 119 } 120 121 static void *ed25519_new_key(void *provctx) 122 { 123 if (!ossl_prov_is_running()) 124 return 0; 125 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0, 126 NULL); 127 } 128 129 static void *ed448_new_key(void *provctx) 130 { 131 if (!ossl_prov_is_running()) 132 return 0; 133 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0, 134 NULL); 135 } 136 137 static int ecx_has(const void *keydata, int selection) 138 { 139 const ECX_KEY *key = keydata; 140 int ok = 0; 141 142 if (ossl_prov_is_running() && key != NULL) { 143 /* 144 * ECX keys always have all the parameters they need (i.e. none). 145 * Therefore we always return with 1, if asked about parameters. 146 */ 147 ok = 1; 148 149 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) 150 ok = ok && key->haspubkey; 151 152 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 153 ok = ok && key->privkey != NULL; 154 } 155 return ok; 156 } 157 158 static int ecx_match(const void *keydata1, const void *keydata2, int selection) 159 { 160 const ECX_KEY *key1 = keydata1; 161 const ECX_KEY *key2 = keydata2; 162 int ok = 1; 163 164 if (!ossl_prov_is_running()) 165 return 0; 166 167 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) 168 ok = ok && key1->type == key2->type; 169 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 170 int key_checked = 0; 171 172 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { 173 const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL; 174 const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL; 175 size_t pal = key1->keylen; 176 size_t pbl = key2->keylen; 177 178 if (pa != NULL && pb != NULL) { 179 ok = ok 180 && key1->type == key2->type 181 && pal == pbl 182 && CRYPTO_memcmp(pa, pb, pal) == 0; 183 key_checked = 1; 184 } 185 } 186 if (!key_checked 187 && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { 188 const unsigned char *pa = key1->privkey; 189 const unsigned char *pb = key2->privkey; 190 size_t pal = key1->keylen; 191 size_t pbl = key2->keylen; 192 193 if (pa != NULL && pb != NULL) { 194 ok = ok 195 && key1->type == key2->type 196 && pal == pbl 197 && CRYPTO_memcmp(pa, pb, pal) == 0; 198 key_checked = 1; 199 } 200 } 201 ok = ok && key_checked; 202 } 203 return ok; 204 } 205 206 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[]) 207 { 208 ECX_KEY *key = keydata; 209 int ok = 1; 210 int include_private; 211 212 if (!ossl_prov_is_running() || key == NULL) 213 return 0; 214 215 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 216 return 0; 217 218 include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0; 219 ok = ok && ossl_ecx_key_fromdata(key, params, include_private); 220 221 return ok; 222 } 223 224 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl, 225 OSSL_PARAM params[], int include_private) 226 { 227 if (key == NULL) 228 return 0; 229 230 if (!ossl_param_build_set_octet_string(tmpl, params, 231 OSSL_PKEY_PARAM_PUB_KEY, 232 key->pubkey, key->keylen)) 233 return 0; 234 235 if (include_private 236 && key->privkey != NULL 237 && !ossl_param_build_set_octet_string(tmpl, params, 238 OSSL_PKEY_PARAM_PRIV_KEY, 239 key->privkey, key->keylen)) 240 return 0; 241 242 return 1; 243 } 244 245 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb, 246 void *cbarg) 247 { 248 ECX_KEY *key = keydata; 249 OSSL_PARAM_BLD *tmpl; 250 OSSL_PARAM *params = NULL; 251 int ret = 0; 252 253 if (!ossl_prov_is_running() || key == NULL) 254 return 0; 255 256 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 257 return 0; 258 259 tmpl = OSSL_PARAM_BLD_new(); 260 if (tmpl == NULL) 261 return 0; 262 263 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { 264 int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0); 265 266 if (!key_to_params(key, tmpl, NULL, include_private)) 267 goto err; 268 } 269 270 params = OSSL_PARAM_BLD_to_param(tmpl); 271 if (params == NULL) 272 goto err; 273 274 ret = param_cb(params, cbarg); 275 OSSL_PARAM_free(params); 276 err: 277 OSSL_PARAM_BLD_free(tmpl); 278 return ret; 279 } 280 281 #define ECX_KEY_TYPES() \ 282 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \ 283 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0) 284 285 static const OSSL_PARAM ecx_key_types[] = { 286 ECX_KEY_TYPES(), 287 OSSL_PARAM_END 288 }; 289 static const OSSL_PARAM *ecx_imexport_types(int selection) 290 { 291 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) 292 return ecx_key_types; 293 return NULL; 294 } 295 296 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits, 297 int size) 298 { 299 ECX_KEY *ecx = key; 300 OSSL_PARAM *p; 301 302 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL 303 && !OSSL_PARAM_set_int(p, bits)) 304 return 0; 305 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL 306 && !OSSL_PARAM_set_int(p, secbits)) 307 return 0; 308 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL 309 && !OSSL_PARAM_set_int(p, size)) 310 return 0; 311 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL 312 && (ecx->type == ECX_KEY_TYPE_X25519 313 || ecx->type == ECX_KEY_TYPE_X448)) { 314 if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen)) 315 return 0; 316 } 317 #ifdef FIPS_MODULE 318 { 319 /* X25519 and X448 are not approved */ 320 int approved = 0; 321 322 p = OSSL_PARAM_locate(params, OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR); 323 if (p != NULL && !OSSL_PARAM_set_int(p, approved)) 324 return 0; 325 } 326 #endif 327 328 return key_to_params(ecx, NULL, params, 1); 329 } 330 331 static int ed_get_params(void *key, OSSL_PARAM params[]) 332 { 333 OSSL_PARAM *p; 334 335 if ((p = OSSL_PARAM_locate(params, 336 OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL 337 && !OSSL_PARAM_set_utf8_string(p, "")) 338 return 0; 339 return 1; 340 } 341 342 static int x25519_get_params(void *key, OSSL_PARAM params[]) 343 { 344 return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS, 345 X25519_KEYLEN); 346 } 347 348 static int x448_get_params(void *key, OSSL_PARAM params[]) 349 { 350 return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS, 351 X448_KEYLEN); 352 } 353 354 static int ed25519_get_params(void *key, OSSL_PARAM params[]) 355 { 356 return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS, 357 ED25519_SIGSIZE) 358 && ed_get_params(key, params); 359 } 360 361 static int ed448_get_params(void *key, OSSL_PARAM params[]) 362 { 363 return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS, 364 ED448_SIGSIZE) 365 && ed_get_params(key, params); 366 } 367 368 static const OSSL_PARAM ecx_gettable_params[] = { 369 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), 370 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), 371 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), 372 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), 373 ECX_KEY_TYPES(), 374 OSSL_FIPS_IND_GETTABLE_CTX_PARAM() 375 OSSL_PARAM_END 376 }; 377 378 static const OSSL_PARAM ed_gettable_params[] = { 379 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), 380 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), 381 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL), 382 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0), 383 ECX_KEY_TYPES(), 384 OSSL_PARAM_END 385 }; 386 387 static const OSSL_PARAM *x25519_gettable_params(void *provctx) 388 { 389 return ecx_gettable_params; 390 } 391 392 static const OSSL_PARAM *x448_gettable_params(void *provctx) 393 { 394 return ecx_gettable_params; 395 } 396 397 static const OSSL_PARAM *ed25519_gettable_params(void *provctx) 398 { 399 return ed_gettable_params; 400 } 401 402 static const OSSL_PARAM *ed448_gettable_params(void *provctx) 403 { 404 return ed_gettable_params; 405 } 406 407 static int set_property_query(ECX_KEY *ecxkey, const char *propq) 408 { 409 OPENSSL_free(ecxkey->propq); 410 ecxkey->propq = NULL; 411 if (propq != NULL) { 412 ecxkey->propq = OPENSSL_strdup(propq); 413 if (ecxkey->propq == NULL) 414 return 0; 415 } 416 return 1; 417 } 418 419 static int ecx_set_params(void *key, const OSSL_PARAM params[]) 420 { 421 ECX_KEY *ecxkey = key; 422 const OSSL_PARAM *p; 423 424 if (ossl_param_is_empty(params)) 425 return 1; 426 427 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); 428 if (p != NULL) { 429 void *buf = ecxkey->pubkey; 430 431 if (p->data_size != ecxkey->keylen 432 || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey), 433 NULL)) 434 return 0; 435 OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen); 436 ecxkey->privkey = NULL; 437 ecxkey->haspubkey = 1; 438 } 439 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES); 440 if (p != NULL) { 441 if (p->data_type != OSSL_PARAM_UTF8_STRING 442 || !set_property_query(ecxkey, p->data)) 443 return 0; 444 } 445 446 return 1; 447 } 448 449 static int x25519_set_params(void *key, const OSSL_PARAM params[]) 450 { 451 return ecx_set_params(key, params); 452 } 453 454 static int x448_set_params(void *key, const OSSL_PARAM params[]) 455 { 456 return ecx_set_params(key, params); 457 } 458 459 static int ed25519_set_params(void *key, const OSSL_PARAM params[]) 460 { 461 return 1; 462 } 463 464 static int ed448_set_params(void *key, const OSSL_PARAM params[]) 465 { 466 return 1; 467 } 468 469 static const OSSL_PARAM ecx_settable_params[] = { 470 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), 471 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0), 472 OSSL_PARAM_END 473 }; 474 475 static const OSSL_PARAM ed_settable_params[] = { 476 OSSL_PARAM_END 477 }; 478 479 static const OSSL_PARAM *x25519_settable_params(void *provctx) 480 { 481 return ecx_settable_params; 482 } 483 484 static const OSSL_PARAM *x448_settable_params(void *provctx) 485 { 486 return ecx_settable_params; 487 } 488 489 static const OSSL_PARAM *ed25519_settable_params(void *provctx) 490 { 491 return ed_settable_params; 492 } 493 494 static const OSSL_PARAM *ed448_settable_params(void *provctx) 495 { 496 return ed_settable_params; 497 } 498 499 static void *ecx_gen_init(void *provctx, int selection, 500 const OSSL_PARAM params[], ECX_KEY_TYPE type, 501 const char *algdesc) 502 { 503 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx); 504 struct ecx_gen_ctx *gctx = NULL; 505 506 if (!ossl_prov_is_running()) 507 return NULL; 508 509 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) { 510 gctx->libctx = libctx; 511 gctx->type = type; 512 gctx->selection = selection; 513 #ifdef FIPS_MODULE 514 /* X25519/X448 are not FIPS approved, (ED25519/ED448 are approved) */ 515 if (algdesc != NULL 516 && !ossl_FIPS_IND_callback(libctx, algdesc, "KeyGen Init")) { 517 OPENSSL_free(gctx); 518 return NULL; 519 } 520 #endif 521 } else { 522 return NULL; 523 } 524 if (!ecx_gen_set_params(gctx, params)) { 525 ecx_gen_cleanup(gctx); 526 gctx = NULL; 527 } 528 return gctx; 529 } 530 531 static void *x25519_gen_init(void *provctx, int selection, 532 const OSSL_PARAM params[]) 533 { 534 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519"); 535 } 536 537 static void *x448_gen_init(void *provctx, int selection, 538 const OSSL_PARAM params[]) 539 { 540 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448"); 541 } 542 543 static void *ed25519_gen_init(void *provctx, int selection, 544 const OSSL_PARAM params[]) 545 { 546 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519, NULL); 547 } 548 549 static void *ed448_gen_init(void *provctx, int selection, 550 const OSSL_PARAM params[]) 551 { 552 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448, NULL); 553 } 554 555 static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[]) 556 { 557 struct ecx_gen_ctx *gctx = genctx; 558 const OSSL_PARAM *p; 559 560 if (gctx == NULL) 561 return 0; 562 563 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); 564 if (p != NULL) { 565 const char *groupname = NULL; 566 567 /* 568 * We optionally allow setting a group name - but each algorithm only 569 * support one such name, so all we do is verify that it is the one we 570 * expected. 571 */ 572 switch (gctx->type) { 573 case ECX_KEY_TYPE_X25519: 574 groupname = "x25519"; 575 break; 576 case ECX_KEY_TYPE_X448: 577 groupname = "x448"; 578 break; 579 default: 580 /* We only support this for key exchange at the moment */ 581 break; 582 } 583 if (p->data_type != OSSL_PARAM_UTF8_STRING 584 || groupname == NULL 585 || OPENSSL_strcasecmp(p->data, groupname) != 0) { 586 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); 587 return 0; 588 } 589 } 590 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES); 591 if (p != NULL) { 592 if (p->data_type != OSSL_PARAM_UTF8_STRING) 593 return 0; 594 OPENSSL_free(gctx->propq); 595 gctx->propq = OPENSSL_strdup(p->data); 596 if (gctx->propq == NULL) 597 return 0; 598 } 599 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM); 600 if (p != NULL) { 601 if (p->data_size != 0 && p->data != NULL) { 602 OPENSSL_free(gctx->dhkem_ikm); 603 gctx->dhkem_ikm = NULL; 604 if (!OSSL_PARAM_get_octet_string(p, (void **)&gctx->dhkem_ikm, 0, 605 &gctx->dhkem_ikmlen)) 606 return 0; 607 } 608 } 609 610 return 1; 611 } 612 613 static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx, 614 ossl_unused void *provctx) 615 { 616 static OSSL_PARAM settable[] = { 617 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), 618 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0), 619 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0), 620 OSSL_PARAM_END 621 }; 622 return settable; 623 } 624 625 #ifdef FIPS_MODULE 626 /* 627 * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1 628 * Perform a pairwise test for EDDSA by signing and verifying signature. 629 * 630 * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST 631 * instance. 632 */ 633 static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test) 634 { 635 int ret = 0; 636 OSSL_SELF_TEST *st = NULL; 637 OSSL_CALLBACK *cb = NULL; 638 void *cbarg = NULL; 639 640 unsigned char msg[16] = {0}; 641 size_t msg_len = sizeof(msg); 642 unsigned char sig[ED448_SIGSIZE] = {0}; 643 644 int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0; 645 int operation_result = 0; 646 647 /* 648 * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st` 649 * is NULL. 650 */ 651 if (self_test) { 652 OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg); 653 654 st = OSSL_SELF_TEST_new(cb, cbarg); 655 if (st == NULL) 656 return 0; 657 } 658 659 OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT, 660 OSSL_SELF_TEST_DESC_PCT_EDDSA); 661 662 if (is_ed25519) 663 operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey, 664 ecx->privkey, 0, 0, 0, NULL, 0, 665 ecx->libctx, ecx->propq); 666 else 667 operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len, 668 ecx->pubkey, ecx->privkey, NULL, 0, 669 0, ecx->propq); 670 if (operation_result != 1) 671 goto err; 672 673 OSSL_SELF_TEST_oncorrupt_byte(st, sig); 674 675 if (is_ed25519) 676 operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey, 677 0, 0, 0, NULL, 0, ecx->libctx, 678 ecx->propq); 679 else 680 operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig, 681 ecx->pubkey, NULL, 0, 0, ecx->propq); 682 if (operation_result != 1) 683 goto err; 684 685 ret = 1; 686 err: 687 OSSL_SELF_TEST_onend(st, ret); 688 OSSL_SELF_TEST_free(st); 689 return ret; 690 } 691 #endif 692 693 static void *ecx_gen(struct ecx_gen_ctx *gctx) 694 { 695 ECX_KEY *key; 696 unsigned char *privkey; 697 698 if (gctx == NULL) 699 return NULL; 700 if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0, 701 gctx->propq)) == NULL) { 702 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 703 return NULL; 704 } 705 706 /* If we're doing parameter generation then we just return a blank key */ 707 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 708 return key; 709 710 if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) { 711 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 712 goto err; 713 } 714 #ifndef FIPS_MODULE 715 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) { 716 if (ecx_key_type_is_ed(gctx->type)) 717 goto err; 718 if (!ossl_ecx_dhkem_derive_private(key, privkey, 719 gctx->dhkem_ikm, gctx->dhkem_ikmlen)) 720 goto err; 721 } else 722 #endif 723 { 724 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0) 725 goto err; 726 } 727 728 switch (gctx->type) { 729 case ECX_KEY_TYPE_X25519: 730 privkey[0] &= 248; 731 privkey[X25519_KEYLEN - 1] &= 127; 732 privkey[X25519_KEYLEN - 1] |= 64; 733 ossl_x25519_public_from_private(key->pubkey, privkey); 734 break; 735 case ECX_KEY_TYPE_X448: 736 privkey[0] &= 252; 737 privkey[X448_KEYLEN - 1] |= 128; 738 ossl_x448_public_from_private(key->pubkey, privkey); 739 break; 740 case ECX_KEY_TYPE_ED25519: 741 if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey, 742 gctx->propq)) 743 goto err; 744 break; 745 case ECX_KEY_TYPE_ED448: 746 if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey, 747 gctx->propq)) 748 goto err; 749 break; 750 } 751 key->haspubkey = 1; 752 return key; 753 err: 754 ossl_ecx_key_free(key); 755 return NULL; 756 } 757 758 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) 759 { 760 struct ecx_gen_ctx *gctx = genctx; 761 762 if (!ossl_prov_is_running()) 763 return 0; 764 765 #ifdef S390X_EC_ASM 766 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)) 767 return s390x_ecx_keygen25519(gctx); 768 #endif 769 return ecx_gen(gctx); 770 } 771 772 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) 773 { 774 struct ecx_gen_ctx *gctx = genctx; 775 776 if (!ossl_prov_is_running()) 777 return 0; 778 779 #ifdef S390X_EC_ASM 780 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)) 781 return s390x_ecx_keygen448(gctx); 782 #endif 783 return ecx_gen(gctx); 784 } 785 786 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) 787 { 788 ECX_KEY *key = NULL; 789 struct ecx_gen_ctx *gctx = genctx; 790 791 if (!ossl_prov_is_running()) 792 return 0; 793 794 #ifdef S390X_EC_ASM 795 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519) 796 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519) 797 && OPENSSL_s390xcap_P.kdsa[0] 798 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) { 799 key = s390x_ecd_keygen25519(gctx); 800 } else 801 #endif 802 { 803 key = ecx_gen(gctx); 804 } 805 806 #ifdef FIPS_MODULE 807 /* Exit if keygen failed OR we are doing parameter generation (blank key) */ 808 if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)) 809 return key; 810 if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) { 811 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); 812 ossl_ecx_key_free(key); 813 return NULL; 814 } 815 #endif 816 817 return key; 818 } 819 820 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) 821 { 822 ECX_KEY *key = NULL; 823 struct ecx_gen_ctx *gctx = genctx; 824 825 if (!ossl_prov_is_running()) 826 return 0; 827 828 #ifdef S390X_EC_ASM 829 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448) 830 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448) 831 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) { 832 key = s390x_ecd_keygen448(gctx); 833 } else 834 #endif 835 { 836 key = ecx_gen(gctx); 837 } 838 839 #ifdef FIPS_MODULE 840 /* Exit if keygen failed OR we are doing parameter generation (blank key) */ 841 if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)) 842 return key; 843 if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) { 844 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); 845 ossl_ecx_key_free(key); 846 return NULL; 847 } 848 #endif 849 850 return key; 851 } 852 853 static void ecx_gen_cleanup(void *genctx) 854 { 855 struct ecx_gen_ctx *gctx = genctx; 856 857 if (gctx == NULL) 858 return; 859 860 OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen); 861 OPENSSL_free(gctx->propq); 862 OPENSSL_free(gctx); 863 } 864 865 void *ecx_load(const void *reference, size_t reference_sz) 866 { 867 ECX_KEY *key = NULL; 868 869 if (ossl_prov_is_running() && reference_sz == sizeof(key)) { 870 /* The contents of the reference is the address to our object */ 871 key = *(ECX_KEY **)reference; 872 /* We grabbed, so we detach it */ 873 *(ECX_KEY **)reference = NULL; 874 return key; 875 } 876 return NULL; 877 } 878 879 static void *ecx_dup(const void *keydata_from, int selection) 880 { 881 if (ossl_prov_is_running()) 882 return ossl_ecx_key_dup(keydata_from, selection); 883 return NULL; 884 } 885 886 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type) 887 { 888 uint8_t pub[64]; 889 890 switch (type) { 891 case ECX_KEY_TYPE_X25519: 892 ossl_x25519_public_from_private(pub, ecx->privkey); 893 break; 894 case ECX_KEY_TYPE_X448: 895 ossl_x448_public_from_private(pub, ecx->privkey); 896 break; 897 default: 898 return 0; 899 } 900 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0; 901 } 902 903 #ifdef FIPS_MODULE 904 /* 905 * FIPS ACVP testing requires the ability to check if the public key is valid 906 * This is not required normally since the ED signature verify does the test 907 * internally. 908 */ 909 static int ecd_key_pub_check(const ECX_KEY *ecx, int type) 910 { 911 switch (type) { 912 case ECX_KEY_TYPE_ED25519: 913 return ossl_ed25519_pubkey_verify(ecx->pubkey, ecx->keylen); 914 case ECX_KEY_TYPE_ED448: 915 return ossl_ed448_pubkey_verify(ecx->pubkey, ecx->keylen); 916 default: 917 return 1; 918 } 919 } 920 #endif 921 922 #ifdef FIPS_MODULE 923 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type) 924 { 925 return ecd_fips140_pairwise_test(ecx, type, 0); 926 } 927 #else 928 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type) 929 { 930 uint8_t pub[64]; 931 932 switch (type) { 933 case ECX_KEY_TYPE_ED25519: 934 if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey, 935 ecx->propq)) 936 return 0; 937 break; 938 case ECX_KEY_TYPE_ED448: 939 if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey, 940 ecx->propq)) 941 return 0; 942 break; 943 default: 944 return 0; 945 } 946 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0; 947 } 948 #endif 949 950 static int ecx_validate(const void *keydata, int selection, int type, 951 size_t keylen) 952 { 953 const ECX_KEY *ecx = keydata; 954 int ok = keylen == ecx->keylen; 955 956 if (!ossl_prov_is_running()) 957 return 0; 958 959 if ((selection & ECX_POSSIBLE_SELECTIONS) == 0) 960 return 1; /* nothing to validate */ 961 962 if (!ok) { 963 ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH); 964 return 0; 965 } 966 967 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { 968 ok = ok && ecx->haspubkey; 969 #ifdef FIPS_MODULE 970 ok = ok && ecd_key_pub_check(ecx, type); 971 #endif 972 } 973 974 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) 975 ok = ok && ecx->privkey != NULL; 976 977 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR) 978 return ok; 979 980 if (ecx_key_type_is_ed(type)) 981 ok = ok && ecd_key_pairwise_check(ecx, type); 982 else 983 ok = ok && ecx_key_pairwise_check(ecx, type); 984 985 return ok; 986 } 987 988 static int x25519_validate(const void *keydata, int selection, int checktype) 989 { 990 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN); 991 } 992 993 static int x448_validate(const void *keydata, int selection, int checktype) 994 { 995 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN); 996 } 997 998 static int ed25519_validate(const void *keydata, int selection, int checktype) 999 { 1000 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN); 1001 } 1002 1003 static int ed448_validate(const void *keydata, int selection, int checktype) 1004 { 1005 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN); 1006 } 1007 1008 #define MAKE_KEYMGMT_FUNCTIONS(alg) \ 1009 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \ 1010 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \ 1011 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \ 1012 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \ 1013 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \ 1014 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \ 1015 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \ 1016 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \ 1017 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \ 1018 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \ 1019 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \ 1020 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ 1021 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \ 1022 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \ 1023 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \ 1024 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \ 1025 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \ 1026 (void (*)(void))ecx_gen_settable_params }, \ 1027 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \ 1028 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \ 1029 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \ 1030 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \ 1031 OSSL_DISPATCH_END \ 1032 }; 1033 1034 MAKE_KEYMGMT_FUNCTIONS(x25519) 1035 MAKE_KEYMGMT_FUNCTIONS(x448) 1036 MAKE_KEYMGMT_FUNCTIONS(ed25519) 1037 MAKE_KEYMGMT_FUNCTIONS(ed448) 1038 1039 #ifdef S390X_EC_ASM 1040 # include "s390x_arch.h" 1041 1042 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx) 1043 { 1044 static const unsigned char generator[] = { 1045 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1047 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1048 }; 1049 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1, 1050 gctx->propq); 1051 unsigned char *privkey = NULL, *pubkey; 1052 1053 if (key == NULL) { 1054 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1055 goto err; 1056 } 1057 1058 /* If we're doing parameter generation then we just return a blank key */ 1059 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 1060 return key; 1061 1062 pubkey = key->pubkey; 1063 1064 privkey = ossl_ecx_key_allocate_privkey(key); 1065 if (privkey == NULL) { 1066 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1067 goto err; 1068 } 1069 1070 #ifndef FIPS_MODULE 1071 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) { 1072 if (gctx->type != ECX_KEY_TYPE_X25519) 1073 goto err; 1074 if (!ossl_ecx_dhkem_derive_private(key, privkey, 1075 gctx->dhkem_ikm, gctx->dhkem_ikmlen)) 1076 goto err; 1077 } else 1078 #endif 1079 { 1080 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0) 1081 goto err; 1082 } 1083 1084 privkey[0] &= 248; 1085 privkey[31] &= 127; 1086 privkey[31] |= 64; 1087 1088 if (s390x_x25519_mul(pubkey, generator, privkey) != 1) 1089 goto err; 1090 key->haspubkey = 1; 1091 return key; 1092 err: 1093 ossl_ecx_key_free(key); 1094 return NULL; 1095 } 1096 1097 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx) 1098 { 1099 static const unsigned char generator[] = { 1100 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 1105 }; 1106 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1, 1107 gctx->propq); 1108 unsigned char *privkey = NULL, *pubkey; 1109 1110 if (key == NULL) { 1111 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1112 goto err; 1113 } 1114 1115 /* If we're doing parameter generation then we just return a blank key */ 1116 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 1117 return key; 1118 1119 pubkey = key->pubkey; 1120 1121 privkey = ossl_ecx_key_allocate_privkey(key); 1122 if (privkey == NULL) { 1123 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1124 goto err; 1125 } 1126 1127 #ifndef FIPS_MODULE 1128 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) { 1129 if (gctx->type != ECX_KEY_TYPE_X448) 1130 goto err; 1131 if (!ossl_ecx_dhkem_derive_private(key, privkey, 1132 gctx->dhkem_ikm, gctx->dhkem_ikmlen)) 1133 goto err; 1134 } else 1135 #endif 1136 { 1137 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0) 1138 goto err; 1139 } 1140 1141 privkey[0] &= 252; 1142 privkey[55] |= 128; 1143 1144 if (s390x_x448_mul(pubkey, generator, privkey) != 1) 1145 goto err; 1146 key->haspubkey = 1; 1147 return key; 1148 err: 1149 ossl_ecx_key_free(key); 1150 return NULL; 1151 } 1152 1153 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx) 1154 { 1155 static const unsigned char generator_x[] = { 1156 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, 1157 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 1158 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 1159 }; 1160 static const unsigned char generator_y[] = { 1161 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 1162 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 1163 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 1164 }; 1165 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH]; 1166 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1, 1167 gctx->propq); 1168 unsigned char *privkey = NULL, *pubkey; 1169 unsigned int sz; 1170 EVP_MD *sha = NULL; 1171 int j; 1172 1173 if (key == NULL) { 1174 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1175 goto err; 1176 } 1177 1178 /* If we're doing parameter generation then we just return a blank key */ 1179 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 1180 return key; 1181 1182 pubkey = key->pubkey; 1183 1184 privkey = ossl_ecx_key_allocate_privkey(key); 1185 if (privkey == NULL) { 1186 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1187 goto err; 1188 } 1189 1190 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0) 1191 goto err; 1192 1193 sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq); 1194 if (sha == NULL) 1195 goto err; 1196 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL); 1197 EVP_MD_free(sha); 1198 if (!j) 1199 goto err; 1200 1201 buff[0] &= 248; 1202 buff[31] &= 63; 1203 buff[31] |= 64; 1204 1205 if (s390x_ed25519_mul(x_dst, pubkey, 1206 generator_x, generator_y, buff) != 1) 1207 goto err; 1208 1209 pubkey[31] |= ((x_dst[0] & 0x01) << 7); 1210 key->haspubkey = 1; 1211 return key; 1212 err: 1213 ossl_ecx_key_free(key); 1214 return NULL; 1215 } 1216 1217 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx) 1218 { 1219 static const unsigned char generator_x[] = { 1220 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b, 1221 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12, 1222 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47, 1223 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22, 1224 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00 1225 }; 1226 static const unsigned char generator_y[] = { 1227 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e, 1228 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a, 1229 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c, 1230 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88, 1231 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00 1232 }; 1233 unsigned char x_dst[57], buff[114]; 1234 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1, 1235 gctx->propq); 1236 unsigned char *privkey = NULL, *pubkey; 1237 EVP_MD_CTX *hashctx = NULL; 1238 EVP_MD *shake = NULL; 1239 1240 if (key == NULL) { 1241 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1242 goto err; 1243 } 1244 1245 /* If we're doing parameter generation then we just return a blank key */ 1246 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) 1247 return key; 1248 1249 pubkey = key->pubkey; 1250 1251 privkey = ossl_ecx_key_allocate_privkey(key); 1252 if (privkey == NULL) { 1253 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB); 1254 goto err; 1255 } 1256 1257 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq); 1258 if (shake == NULL) 1259 goto err; 1260 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0) 1261 goto err; 1262 1263 hashctx = EVP_MD_CTX_new(); 1264 if (hashctx == NULL) 1265 goto err; 1266 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1) 1267 goto err; 1268 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1) 1269 goto err; 1270 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1) 1271 goto err; 1272 1273 buff[0] &= -4; 1274 buff[55] |= 0x80; 1275 buff[56] = 0; 1276 1277 if (s390x_ed448_mul(x_dst, pubkey, 1278 generator_x, generator_y, buff) != 1) 1279 goto err; 1280 1281 pubkey[56] |= ((x_dst[0] & 0x01) << 7); 1282 EVP_MD_CTX_free(hashctx); 1283 EVP_MD_free(shake); 1284 key->haspubkey = 1; 1285 return key; 1286 err: 1287 ossl_ecx_key_free(key); 1288 EVP_MD_CTX_free(hashctx); 1289 EVP_MD_free(shake); 1290 return NULL; 1291 } 1292 #endif 1293