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