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