]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ecx_meth.c
Implement EVP_PKEY_dup() function
[thirdparty/openssl.git] / crypto / ec / ecx_meth.c
CommitLineData
756b198d 1/*
8020d79b 2 * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
756b198d 3 *
a7f182b7 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
756b198d
DSH
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
579422c8
P
10/*
11 * ECDSA low level APIs are deprecated for public use, but still ok for
12 * internal use.
13 */
14#include "internal/deprecated.h"
15
756b198d 16#include <stdio.h>
756b198d
DSH
17#include <openssl/x509.h>
18#include <openssl/ec.h>
6f7d2135 19#include <openssl/core_names.h>
8c631cfa 20#include <openssl/param_build.h>
c08138e5 21#include <openssl/rand.h>
8c631cfa
TM
22#include "internal/cryptlib.h"
23#include "internal/provider.h"
25f2138b
DMSP
24#include "crypto/asn1.h"
25#include "crypto/evp.h"
4de88fe6 26#include "crypto/ecx.h"
706457b7
DMSP
27#include "ec_local.h"
28#include "curve448/curve448_local.h"
0abae163 29#include "ecx_backend.h"
756b198d 30
756b198d
DSH
31static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
32{
13735cfe 33 const ECX_KEY *ecxkey = pkey->pkey.ecx;
756b198d
DSH
34 unsigned char *penc;
35
13735cfe 36 if (ecxkey == NULL) {
9311d0c4 37 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
756b198d
DSH
38 return 0;
39 }
40
13735cfe 41 penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
756b198d 42 if (penc == NULL) {
9311d0c4 43 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
756b198d
DSH
44 return 0;
45 }
46
8ecade8b 47 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
13735cfe 48 V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
756b198d 49 OPENSSL_free(penc);
9311d0c4 50 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
756b198d
DSH
51 return 0;
52 }
53 return 1;
54}
55
7674e923 56static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
756b198d
DSH
57{
58 const unsigned char *p;
59 int pklen;
60 X509_ALGOR *palg;
cf333799
RL
61 ECX_KEY *ecx;
62 int ret = 0;
756b198d
DSH
63
64 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
65 return 0;
cf333799
RL
66 ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
67 KEY_OP_PUBLIC, NULL, NULL);
68 if (ecx != NULL) {
69 ret = 1;
70 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
71 }
72 return ret;
756b198d
DSH
73}
74
75static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
76{
13735cfe
MC
77 const ECX_KEY *akey = a->pkey.ecx;
78 const ECX_KEY *bkey = b->pkey.ecx;
756b198d
DSH
79
80 if (akey == NULL || bkey == NULL)
81 return -2;
13735cfe
MC
82
83 return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
756b198d
DSH
84}
85
d8652be0 86static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
b4250010 87 OSSL_LIB_CTX *libctx, const char *propq)
756b198d 88{
cf333799
RL
89 int ret = 0;
90 ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
756b198d 91
cf333799
RL
92 if (ecx != NULL) {
93 ret = 1;
94 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
756b198d
DSH
95 }
96
cf333799 97 return ret;
756b198d
DSH
98}
99
100static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
101{
13735cfe 102 const ECX_KEY *ecxkey = pkey->pkey.ecx;
756b198d
DSH
103 ASN1_OCTET_STRING oct;
104 unsigned char *penc = NULL;
105 int penclen;
106
13735cfe 107 if (ecxkey == NULL || ecxkey->privkey == NULL) {
9311d0c4 108 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
756b198d
DSH
109 return 0;
110 }
111
13735cfe
MC
112 oct.data = ecxkey->privkey;
113 oct.length = KEYLEN(pkey);
756b198d
DSH
114 oct.flags = 0;
115
116 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
117 if (penclen < 0) {
9311d0c4 118 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
756b198d
DSH
119 return 0;
120 }
121
8ecade8b 122 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
756b198d
DSH
123 V_ASN1_UNDEF, NULL, penc, penclen)) {
124 OPENSSL_clear_free(penc, penclen);
9311d0c4 125 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
756b198d
DSH
126 return 0;
127 }
128
129 return 1;
130}
131
132static int ecx_size(const EVP_PKEY *pkey)
133{
13735cfe 134 return KEYLEN(pkey);
756b198d
DSH
135}
136
137static int ecx_bits(const EVP_PKEY *pkey)
138{
13735cfe
MC
139 if (IS25519(pkey->ameth->pkey_id)) {
140 return X25519_BITS;
141 } else if(ISX448(pkey->ameth->pkey_id)) {
142 return X448_BITS;
143 } else {
144 return ED448_BITS;
145 }
756b198d
DSH
146}
147
148static int ecx_security_bits(const EVP_PKEY *pkey)
149{
13735cfe
MC
150 if (IS25519(pkey->ameth->pkey_id)) {
151 return X25519_SECURITY_BITS;
152 } else {
153 return X448_SECURITY_BITS;
154 }
756b198d
DSH
155}
156
157static void ecx_free(EVP_PKEY *pkey)
158{
32ab57cb 159 ossl_ecx_key_free(pkey->pkey.ecx);
756b198d
DSH
160}
161
162/* "parameters" are always equal */
163static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
164{
165 return 1;
166}
167
168static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
169 ASN1_PCTX *ctx, ecx_key_op_t op)
170{
13735cfe 171 const ECX_KEY *ecxkey = pkey->pkey.ecx;
8ecade8b
DSH
172 const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
173
13735cfe
MC
174 if (op == KEY_OP_PRIVATE) {
175 if (ecxkey == NULL || ecxkey->privkey == NULL) {
756b198d
DSH
176 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
177 return 0;
178 return 1;
179 }
8ecade8b 180 if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
756b198d
DSH
181 return 0;
182 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
183 return 0;
13735cfe
MC
184 if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
185 indent + 4) == 0)
756b198d
DSH
186 return 0;
187 } else {
13735cfe 188 if (ecxkey == NULL) {
756b198d
DSH
189 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
190 return 0;
191 return 1;
192 }
8ecade8b 193 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
756b198d
DSH
194 return 0;
195 }
196 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
197 return 0;
13735cfe
MC
198
199 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
200 indent + 4) == 0)
756b198d
DSH
201 return 0;
202 return 1;
203}
204
205static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
206 ASN1_PCTX *ctx)
207{
13735cfe 208 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
756b198d
DSH
209}
210
211static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
212 ASN1_PCTX *ctx)
213{
13735cfe 214 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
756b198d
DSH
215}
216
217static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
218{
5d6aaf8a
DSH
219 switch (op) {
220
cf333799
RL
221 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
222 ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
223 KEY_OP_PUBLIC, NULL, NULL);
5d6aaf8a 224
cf333799
RL
225 if (ecx != NULL) {
226 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
227 return 1;
228 }
229 return 0;
230 }
5d6aaf8a 231 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
13735cfe 232 if (pkey->pkey.ecx != NULL) {
5d6aaf8a 233 unsigned char **ppt = arg2;
13735cfe
MC
234
235 *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
5d6aaf8a 236 if (*ppt != NULL)
13735cfe 237 return KEYLEN(pkey);
5d6aaf8a
DSH
238 }
239 return 0;
240
aabbc24e
MC
241 default:
242 return -2;
243
244 }
245}
246
247static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
248{
249 switch (op) {
5d6aaf8a 250 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
aabbc24e
MC
251 /* We currently only support Pure EdDSA which takes no digest */
252 *(int *)arg2 = NID_undef;
5d6aaf8a
DSH
253 return 2;
254
255 default:
256 return -2;
257
258 }
756b198d
DSH
259}
260
cc8b15c7
MC
261static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
262 size_t len)
263{
8c631cfa 264 OSSL_LIB_CTX *libctx = NULL;
cf333799 265 ECX_KEY *ecx = NULL;
8c631cfa
TM
266
267 if (pkey->keymgmt != NULL)
268 libctx = ossl_provider_libctx(EVP_KEYMGMT_provider(pkey->keymgmt));
269
cf333799
RL
270 ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
271 KEY_OP_PRIVATE, libctx, NULL);
272
273 if (ecx != NULL) {
274 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
275 return 1;
276 }
277 return 0;
cc8b15c7
MC
278}
279
280static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
281{
8c631cfa 282 OSSL_LIB_CTX *libctx = NULL;
cf333799 283 ECX_KEY *ecx = NULL;
8c631cfa
TM
284
285 if (pkey->keymgmt != NULL)
286 libctx = ossl_provider_libctx(EVP_KEYMGMT_provider(pkey->keymgmt));
287
cf333799
RL
288 ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
289 KEY_OP_PUBLIC, libctx, NULL);
290
291 if (ecx != NULL) {
292 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
293 return 1;
294 }
295 return 0;
cc8b15c7
MC
296}
297
0d124b0a
MC
298static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
299 size_t *len)
300{
301 const ECX_KEY *key = pkey->pkey.ecx;
302
303 if (priv == NULL) {
304 *len = KEYLENID(pkey->ameth->pkey_id);
305 return 1;
306 }
307
308 if (key == NULL
309 || key->privkey == NULL
310 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
311 return 0;
312
313 *len = KEYLENID(pkey->ameth->pkey_id);
314 memcpy(priv, key->privkey, *len);
315
316 return 1;
317}
318
319static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
320 size_t *len)
321{
322 const ECX_KEY *key = pkey->pkey.ecx;
323
324 if (pub == NULL) {
325 *len = KEYLENID(pkey->ameth->pkey_id);
326 return 1;
327 }
328
329 if (key == NULL
330 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
331 return 0;
332
333 *len = KEYLENID(pkey->ameth->pkey_id);
334 memcpy(pub, key->pubkey, *len);
335
336 return 1;
337}
338
6f7d2135
MC
339static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
340{
341 /*
342 * We provide no mechanism to "update" an ECX key once it has been set,
343 * therefore we do not have to maintain a dirty count.
344 */
345 return 1;
346}
347
348static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
b4250010 349 EVP_KEYMGMT *to_keymgmt, OSSL_LIB_CTX *libctx,
76e23fc5 350 const char *propq)
6f7d2135
MC
351{
352 const ECX_KEY *key = from->pkey.ecx;
6d4e6009 353 OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
6f7d2135 354 OSSL_PARAM *params = NULL;
0996cff9 355 int selection = 0;
6f7d2135
MC
356 int rv = 0;
357
6d4e6009
P
358 if (tmpl == NULL)
359 return 0;
6f7d2135
MC
360
361 /* A key must at least have a public part */
6d4e6009 362 if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
6f7d2135
MC
363 key->pubkey, key->keylen))
364 goto err;
0996cff9 365 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
6f7d2135
MC
366
367 if (key->privkey != NULL) {
6d4e6009 368 if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
6f7d2135
MC
369 OSSL_PKEY_PARAM_PRIV_KEY,
370 key->privkey, key->keylen))
371 goto err;
0996cff9 372 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
6f7d2135
MC
373 }
374
6d4e6009 375 params = OSSL_PARAM_BLD_to_param(tmpl);
6f7d2135
MC
376
377 /* We export, the provider imports */
0996cff9 378 rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
6f7d2135
MC
379
380 err:
6d4e6009
P
381 OSSL_PARAM_BLD_free(tmpl);
382 OSSL_PARAM_BLD_free_params(params);
6f7d2135
MC
383 return rv;
384}
385
629c72db 386static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
0abae163
RL
387 int keytype)
388{
629c72db
MC
389 EVP_PKEY_CTX *pctx = vpctx;
390 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
32ab57cb
SL
391 ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
392 pctx->propquery);
0abae163
RL
393
394 if (ecx == NULL) {
395 ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
396 return 0;
397 }
398
32ab57cb 399 if (!ossl_ecx_key_fromdata(ecx, params, 1)
0abae163 400 || !EVP_PKEY_assign(pkey, keytype, ecx)) {
32ab57cb 401 ossl_ecx_key_free(ecx);
0abae163
RL
402 return 0;
403 }
404 return 1;
405}
406
2145ba5e
TM
407static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
408{
409 ECX_KEY *ecx = from->pkey.ecx;
410 int ret;
411
412 /* We can do just up-ref as ECX keys are immutable */
413 if (ecx != NULL && !ossl_ecx_key_up_ref(ecx))
414 return 0;
415
416 ret = EVP_PKEY_assign(to, from->type, ecx);
417 if (!ret)
418 ossl_ecx_key_free(ecx);
419 return ret;
420}
421
629c72db 422static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 423{
629c72db 424 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
0abae163
RL
425}
426
adf7e6d1 427const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
d2916a5b
DSH
428 EVP_PKEY_X25519,
429 EVP_PKEY_X25519,
756b198d
DSH
430 0,
431 "X25519",
432 "OpenSSL X25519 algorithm",
433
434 ecx_pub_decode,
435 ecx_pub_encode,
436 ecx_pub_cmp,
437 ecx_pub_print,
438
f13fdeb3 439 NULL,
756b198d
DSH
440 ecx_priv_encode,
441 ecx_priv_print,
442
443 ecx_size,
444 ecx_bits,
445 ecx_security_bits,
446
447 0, 0, 0, 0,
448 ecx_cmp_parameters,
449 0, 0,
450
451 ecx_free,
452 ecx_ctrl,
453 NULL,
cc8b15c7
MC
454 NULL,
455
456 NULL,
457 NULL,
458 NULL,
459
460 NULL,
461 NULL,
462 NULL,
463
464 ecx_set_priv_key,
465 ecx_set_pub_key,
0d124b0a
MC
466 ecx_get_priv_key,
467 ecx_get_pub_key,
6f7d2135 468 ecx_pkey_dirty_cnt,
0abae163 469 ecx_pkey_export_to,
f13fdeb3 470 x25519_import_from,
2145ba5e 471 ecx_pkey_copy,
f13fdeb3 472
d8652be0 473 ecx_priv_decode_ex
756b198d
DSH
474};
475
629c72db 476static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 477{
629c72db 478 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
0abae163
RL
479}
480
adf7e6d1 481const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
13735cfe
MC
482 EVP_PKEY_X448,
483 EVP_PKEY_X448,
484 0,
485 "X448",
486 "OpenSSL X448 algorithm",
487
488 ecx_pub_decode,
489 ecx_pub_encode,
490 ecx_pub_cmp,
491 ecx_pub_print,
492
f13fdeb3 493 NULL,
13735cfe
MC
494 ecx_priv_encode,
495 ecx_priv_print,
496
497 ecx_size,
498 ecx_bits,
499 ecx_security_bits,
500
501 0, 0, 0, 0,
502 ecx_cmp_parameters,
503 0, 0,
504
505 ecx_free,
506 ecx_ctrl,
507 NULL,
cc8b15c7
MC
508 NULL,
509
510 NULL,
511 NULL,
512 NULL,
513
514 NULL,
515 NULL,
516 NULL,
517
518 ecx_set_priv_key,
519 ecx_set_pub_key,
0d124b0a
MC
520 ecx_get_priv_key,
521 ecx_get_pub_key,
6f7d2135 522 ecx_pkey_dirty_cnt,
0abae163 523 ecx_pkey_export_to,
f13fdeb3 524 x448_import_from,
2145ba5e 525 ecx_pkey_copy,
f13fdeb3 526
d8652be0 527 ecx_priv_decode_ex
13735cfe
MC
528};
529
530static int ecd_size25519(const EVP_PKEY *pkey)
8ecade8b
DSH
531{
532 return ED25519_SIGSIZE;
533}
534
13735cfe
MC
535static int ecd_size448(const EVP_PKEY *pkey)
536{
537 return ED448_SIGSIZE;
538}
539
ded346fa
DDO
540static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
541 const void *asn, const X509_ALGOR *sigalg,
542 const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
9f98fbad
DSH
543{
544 const ASN1_OBJECT *obj;
545 int ptype;
13735cfe 546 int nid;
9f98fbad 547
13735cfe 548 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
9f98fbad 549 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
13735cfe
MC
550 nid = OBJ_obj2nid(obj);
551 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
9311d0c4 552 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
9f98fbad
DSH
553 return 0;
554 }
555
556 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
557 return 0;
558
559 return 2;
560}
561
ded346fa
DDO
562static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
563 const void *asn,
13735cfe
MC
564 X509_ALGOR *alg1, X509_ALGOR *alg2,
565 ASN1_BIT_STRING *str)
9f98fbad
DSH
566{
567 /* Set algorithms identifiers */
568 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
569 if (alg2)
570 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
c2969ff6 571 /* Algorithm identifiers set: carry on as normal */
9f98fbad
DSH
572 return 3;
573}
574
13735cfe
MC
575static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
576 const ASN1_STRING *sig)
684c41c8
DSH
577{
578 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
579 X509_SIG_INFO_TLS);
580 return 1;
581}
582
ded346fa
DDO
583static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
584 const void *asn,
13735cfe
MC
585 X509_ALGOR *alg1, X509_ALGOR *alg2,
586 ASN1_BIT_STRING *str)
587{
588 /* Set algorithm identifier */
589 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
590 if (alg2 != NULL)
591 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
592 /* Algorithm identifier set: carry on as normal */
593 return 3;
594}
595
596static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
597 const ASN1_STRING *sig)
598{
599 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
600 X509_SIG_INFO_TLS);
601 return 1;
602}
603
629c72db 604static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 605{
629c72db 606 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
0abae163 607}
13735cfe 608
adf7e6d1 609const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
d2916a5b
DSH
610 EVP_PKEY_ED25519,
611 EVP_PKEY_ED25519,
8ecade8b
DSH
612 0,
613 "ED25519",
614 "OpenSSL ED25519 algorithm",
615
616 ecx_pub_decode,
617 ecx_pub_encode,
618 ecx_pub_cmp,
619 ecx_pub_print,
620
f13fdeb3 621 NULL,
8ecade8b
DSH
622 ecx_priv_encode,
623 ecx_priv_print,
624
13735cfe
MC
625 ecd_size25519,
626 ecx_bits,
627 ecx_security_bits,
628
629 0, 0, 0, 0,
630 ecx_cmp_parameters,
631 0, 0,
632
633 ecx_free,
aabbc24e 634 ecd_ctrl,
13735cfe
MC
635 NULL,
636 NULL,
637 ecd_item_verify,
638 ecd_item_sign25519,
cc8b15c7
MC
639 ecd_sig_info_set25519,
640
641 NULL,
642 NULL,
643 NULL,
644
645 ecx_set_priv_key,
646 ecx_set_pub_key,
0d124b0a
MC
647 ecx_get_priv_key,
648 ecx_get_pub_key,
3965480c 649 ecx_pkey_dirty_cnt,
0abae163 650 ecx_pkey_export_to,
f13fdeb3 651 ed25519_import_from,
2145ba5e 652 ecx_pkey_copy,
f13fdeb3 653
d8652be0 654 ecx_priv_decode_ex
13735cfe
MC
655};
656
629c72db 657static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 658{
629c72db 659 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
0abae163
RL
660}
661
adf7e6d1 662const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
13735cfe
MC
663 EVP_PKEY_ED448,
664 EVP_PKEY_ED448,
665 0,
666 "ED448",
667 "OpenSSL ED448 algorithm",
668
669 ecx_pub_decode,
670 ecx_pub_encode,
671 ecx_pub_cmp,
672 ecx_pub_print,
673
f13fdeb3 674 NULL,
13735cfe
MC
675 ecx_priv_encode,
676 ecx_priv_print,
677
678 ecd_size448,
8ecade8b
DSH
679 ecx_bits,
680 ecx_security_bits,
681
682 0, 0, 0, 0,
683 ecx_cmp_parameters,
684 0, 0,
685
686 ecx_free,
aabbc24e 687 ecd_ctrl,
8ecade8b 688 NULL,
9f98fbad
DSH
689 NULL,
690 ecd_item_verify,
13735cfe 691 ecd_item_sign448,
cc8b15c7
MC
692 ecd_sig_info_set448,
693
694 NULL,
695 NULL,
696 NULL,
697
698 ecx_set_priv_key,
699 ecx_set_pub_key,
0d124b0a
MC
700 ecx_get_priv_key,
701 ecx_get_pub_key,
3965480c 702 ecx_pkey_dirty_cnt,
0abae163 703 ecx_pkey_export_to,
f13fdeb3 704 ed448_import_from,
2145ba5e 705 ecx_pkey_copy,
f13fdeb3 706
d8652be0 707 ecx_priv_decode_ex
8ecade8b
DSH
708};
709
756b198d
DSH
710static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
711{
cf333799
RL
712 ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
713 KEY_OP_PUBLIC, NULL, NULL);
714
715 if (ecx != NULL) {
716 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
717 return 1;
718 }
719 return 0;
756b198d
DSH
720}
721
13735cfe
MC
722static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
723 size_t *keylen,
724 const unsigned char **privkey,
725 const unsigned char **pubkey)
756b198d 726{
13735cfe 727 const ECX_KEY *ecxkey, *peerkey;
756b198d
DSH
728
729 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
9311d0c4 730 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
756b198d
DSH
731 return 0;
732 }
13735cfe 733 ecxkey = ctx->pkey->pkey.ecx;
19ad1e9d 734 peerkey = EVP_PKEY_get0(ctx->peerkey);
13735cfe 735 if (ecxkey == NULL || ecxkey->privkey == NULL) {
9311d0c4 736 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
756b198d
DSH
737 return 0;
738 }
739 if (peerkey == NULL) {
9311d0c4 740 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
756b198d
DSH
741 return 0;
742 }
13735cfe
MC
743 *privkey = ecxkey->privkey;
744 *pubkey = peerkey->pubkey;
745
746 return 1;
747}
748
749static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
750 size_t *keylen)
751{
752 const unsigned char *privkey, *pubkey;
753
754 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
755 || (key != NULL
054d43ff 756 && ossl_x25519(key, privkey, pubkey) == 0))
13735cfe 757 return 0;
756b198d 758 *keylen = X25519_KEYLEN;
13735cfe
MC
759 return 1;
760}
761
762static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
763 size_t *keylen)
764{
765 const unsigned char *privkey, *pubkey;
766
767 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
768 || (key != NULL
054d43ff 769 && ossl_x448(key, privkey, pubkey) == 0))
756b198d 770 return 0;
13735cfe 771 *keylen = X448_KEYLEN;
756b198d
DSH
772 return 1;
773}
774
775static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
776{
777 /* Only need to handle peer key for derivation */
778 if (type == EVP_PKEY_CTRL_PEER_KEY)
779 return 1;
780 return -2;
781}
782
19bd1fa1 783static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
d2916a5b 784 EVP_PKEY_X25519,
756b198d
DSH
785 0, 0, 0, 0, 0, 0, 0,
786 pkey_ecx_keygen,
787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13735cfe 788 pkey_ecx_derive25519,
756b198d
DSH
789 pkey_ecx_ctrl,
790 0
791};
42a3008a 792
19bd1fa1 793static const EVP_PKEY_METHOD ecx448_pkey_meth = {
13735cfe
MC
794 EVP_PKEY_X448,
795 0, 0, 0, 0, 0, 0, 0,
796 pkey_ecx_keygen,
797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
798 pkey_ecx_derive448,
799 pkey_ecx_ctrl,
800 0
801};
802
07824f30
MC
803static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
804 size_t *siglen, const unsigned char *tbs,
805 size_t tbslen)
42a3008a 806{
07824f30 807 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
42a3008a
DSH
808
809 if (sig == NULL) {
810 *siglen = ED25519_SIGSIZE;
811 return 1;
812 }
813 if (*siglen < ED25519_SIGSIZE) {
9311d0c4 814 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
42a3008a
DSH
815 return 0;
816 }
817
054d43ff
SL
818 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
819 NULL) == 0)
42a3008a
DSH
820 return 0;
821 *siglen = ED25519_SIGSIZE;
822 return 1;
823}
824
07824f30
MC
825static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
826 size_t *siglen, const unsigned char *tbs,
827 size_t tbslen)
13735cfe 828{
07824f30 829 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
13735cfe
MC
830
831 if (sig == NULL) {
832 *siglen = ED448_SIGSIZE;
833 return 1;
834 }
835 if (*siglen < ED448_SIGSIZE) {
9311d0c4 836 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
13735cfe
MC
837 return 0;
838 }
839
054d43ff
SL
840 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
841 edkey->privkey, NULL, 0, edkey->propq) == 0)
13735cfe
MC
842 return 0;
843 *siglen = ED448_SIGSIZE;
844 return 1;
845}
846
07824f30
MC
847static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
848 size_t siglen, const unsigned char *tbs,
849 size_t tbslen)
42a3008a 850{
07824f30 851 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
42a3008a
DSH
852
853 if (siglen != ED25519_SIGSIZE)
854 return 0;
855
054d43ff
SL
856 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
857 edkey->libctx, edkey->propq);
42a3008a
DSH
858}
859
07824f30
MC
860static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
861 size_t siglen, const unsigned char *tbs,
862 size_t tbslen)
13735cfe 863{
07824f30 864 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
13735cfe
MC
865
866 if (siglen != ED448_SIGSIZE)
867 return 0;
868
054d43ff
SL
869 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
870 NULL, 0, edkey->propq);
13735cfe
MC
871}
872
42a3008a
DSH
873static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
874{
875 switch (type) {
876 case EVP_PKEY_CTRL_MD:
877 /* Only NULL allowed as digest */
f3021aca 878 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
42a3008a 879 return 1;
9311d0c4 880 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
42a3008a
DSH
881 return 0;
882
883 case EVP_PKEY_CTRL_DIGESTINIT:
884 return 1;
885 }
886 return -2;
887}
888
19bd1fa1 889static const EVP_PKEY_METHOD ed25519_pkey_meth = {
d2916a5b 890 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
42a3008a
DSH
891 0, 0, 0, 0, 0, 0,
892 pkey_ecx_keygen,
07824f30 893 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42a3008a
DSH
894 pkey_ecd_ctrl,
895 0,
13735cfe
MC
896 pkey_ecd_digestsign25519,
897 pkey_ecd_digestverify25519
898};
899
19bd1fa1 900static const EVP_PKEY_METHOD ed448_pkey_meth = {
13735cfe
MC
901 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
902 0, 0, 0, 0, 0, 0,
903 pkey_ecx_keygen,
07824f30 904 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13735cfe
MC
905 pkey_ecd_ctrl,
906 0,
907 pkey_ecd_digestsign448,
908 pkey_ecd_digestverify448
42a3008a 909};
19bd1fa1
PS
910
911#ifdef S390X_EC_ASM
912# include "s390x_arch.h"
19bd1fa1
PS
913
914static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
915{
916 static const unsigned char generator[] = {
917 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
920 };
32ab57cb
SL
921 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
922 ctx->propquery);
19bd1fa1
PS
923 unsigned char *privkey = NULL, *pubkey;
924
19bd1fa1 925 if (key == NULL) {
9311d0c4 926 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
927 goto err;
928 }
929
930 pubkey = key->pubkey;
931
32ab57cb 932 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 933 if (privkey == NULL) {
9311d0c4 934 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
935 goto err;
936 }
937
8dbef010 938 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN) <= 0)
19bd1fa1
PS
939 goto err;
940
941 privkey[0] &= 248;
942 privkey[31] &= 127;
943 privkey[31] |= 64;
944
945 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
946 goto err;
947
948 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
949 return 1;
950 err:
32ab57cb 951 ossl_ecx_key_free(key);
19bd1fa1
PS
952 return 0;
953}
954
955static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
956{
957 static const unsigned char generator[] = {
958 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
963 };
32ab57cb
SL
964 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
965 ctx->propquery);
19bd1fa1
PS
966 unsigned char *privkey = NULL, *pubkey;
967
19bd1fa1 968 if (key == NULL) {
9311d0c4 969 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
970 goto err;
971 }
972
973 pubkey = key->pubkey;
974
32ab57cb 975 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 976 if (privkey == NULL) {
9311d0c4 977 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
978 goto err;
979 }
980
8dbef010 981 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN) <= 0)
19bd1fa1
PS
982 goto err;
983
984 privkey[0] &= 252;
985 privkey[55] |= 128;
986
987 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
988 goto err;
989
990 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
991 return 1;
992 err:
32ab57cb 993 ossl_ecx_key_free(key);
19bd1fa1
PS
994 return 0;
995}
996
997static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
998{
999 static const unsigned char generator_x[] = {
1000 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1001 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1002 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1003 };
1004 static const unsigned char generator_y[] = {
1005 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1006 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1007 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1008 };
1009 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
32ab57cb
SL
1010 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1011 ctx->propquery);
19bd1fa1 1012 unsigned char *privkey = NULL, *pubkey;
85d843c8 1013 unsigned int sz;
e72dbd8e
SL
1014 EVP_MD *md = NULL;
1015 int rv;
19bd1fa1 1016
19bd1fa1 1017 if (key == NULL) {
9311d0c4 1018 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1019 goto err;
1020 }
1021
1022 pubkey = key->pubkey;
1023
32ab57cb 1024 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 1025 if (privkey == NULL) {
9311d0c4 1026 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1027 goto err;
1028 }
1029
8dbef010 1030 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN) <= 0)
19bd1fa1
PS
1031 goto err;
1032
e72dbd8e
SL
1033 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1034 if (md == NULL)
1035 goto err;
1036
1037 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1038 EVP_MD_free(md);
1039 if (!rv)
85d843c8
P
1040 goto err;
1041
19bd1fa1
PS
1042 buff[0] &= 248;
1043 buff[31] &= 63;
1044 buff[31] |= 64;
1045
1046 if (s390x_ed25519_mul(x_dst, pubkey,
1047 generator_x, generator_y, buff) != 1)
1048 goto err;
1049
1050 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1051
1052 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1053 return 1;
1054 err:
32ab57cb 1055 ossl_ecx_key_free(key);
19bd1fa1
PS
1056 return 0;
1057}
1058
1059static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1060{
1061 static const unsigned char generator_x[] = {
1062 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1063 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1064 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1065 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1066 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1067 };
1068 static const unsigned char generator_y[] = {
1069 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1070 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1071 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1072 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1073 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1074 };
1075 unsigned char x_dst[57], buff[114];
32ab57cb
SL
1076 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1077 ctx->propquery);
19bd1fa1
PS
1078 unsigned char *privkey = NULL, *pubkey;
1079 EVP_MD_CTX *hashctx = NULL;
e72dbd8e
SL
1080 EVP_MD *md = NULL;
1081 int rv;
19bd1fa1 1082
19bd1fa1 1083 if (key == NULL) {
9311d0c4 1084 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1085 goto err;
1086 }
1087
1088 pubkey = key->pubkey;
1089
32ab57cb 1090 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 1091 if (privkey == NULL) {
9311d0c4 1092 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1093 goto err;
1094 }
1095
8dbef010 1096 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN) <= 0)
19bd1fa1
PS
1097 goto err;
1098
1099 hashctx = EVP_MD_CTX_new();
1100 if (hashctx == NULL)
1101 goto err;
e72dbd8e
SL
1102
1103 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1104 if (md == NULL)
1105 goto err;
1106
1107 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1108 EVP_MD_free(md);
1109 if (rv != 1)
19bd1fa1 1110 goto err;
e72dbd8e 1111
19bd1fa1
PS
1112 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1113 goto err;
1114 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1115 goto err;
1116
1117 buff[0] &= -4;
1118 buff[55] |= 0x80;
1119 buff[56] = 0;
1120
1121 if (s390x_ed448_mul(x_dst, pubkey,
1122 generator_x, generator_y, buff) != 1)
1123 goto err;
1124
1125 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1126
1127 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1128 EVP_MD_CTX_free(hashctx);
1129 return 1;
1130 err:
32ab57cb 1131 ossl_ecx_key_free(key);
19bd1fa1
PS
1132 EVP_MD_CTX_free(hashctx);
1133 return 0;
1134}
1135
1136static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1137 size_t *keylen)
1138{
1139 const unsigned char *privkey, *pubkey;
1140
1141 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1142 return 0;
1143
1144 if (key != NULL)
1145 return s390x_x25519_mul(key, pubkey, privkey);
1146
1147 *keylen = X25519_KEYLEN;
1148 return 1;
1149}
1150
1151static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1152 size_t *keylen)
1153{
1154 const unsigned char *privkey, *pubkey;
1155
1156 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1157 return 0;
1158
1159 if (key != NULL)
1160 return s390x_x448_mul(key, pubkey, privkey);
1161
1162 *keylen = X448_KEYLEN;
1163 return 1;
1164}
1165
1166static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1167 unsigned char *sig, size_t *siglen,
1168 const unsigned char *tbs,
1169 size_t tbslen)
1170{
1171 union {
1172 struct {
1173 unsigned char sig[64];
1174 unsigned char priv[32];
1175 } ed25519;
1176 unsigned long long buff[512];
1177 } param;
1178 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1179 int rc;
1180
1181 if (sig == NULL) {
1182 *siglen = ED25519_SIGSIZE;
1183 return 1;
1184 }
1185
1186 if (*siglen < ED25519_SIGSIZE) {
9311d0c4 1187 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
19bd1fa1
PS
1188 return 0;
1189 }
1190
1191 memset(&param, 0, sizeof(param));
1192 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1193
1194 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1195 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1196 if (rc != 0)
1197 return 0;
1198
1199 s390x_flip_endian32(sig, param.ed25519.sig);
1200 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1201
1202 *siglen = ED25519_SIGSIZE;
1203 return 1;
1204}
1205
1206static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1207 unsigned char *sig, size_t *siglen,
1208 const unsigned char *tbs,
1209 size_t tbslen)
1210{
1211 union {
1212 struct {
1213 unsigned char sig[128];
1214 unsigned char priv[64];
1215 } ed448;
1216 unsigned long long buff[512];
1217 } param;
1218 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1219 int rc;
1220
1221 if (sig == NULL) {
1222 *siglen = ED448_SIGSIZE;
1223 return 1;
1224 }
1225
1226 if (*siglen < ED448_SIGSIZE) {
9311d0c4 1227 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
19bd1fa1
PS
1228 return 0;
1229 }
1230
1231 memset(&param, 0, sizeof(param));
1232 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1233
1234 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1235 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1236 if (rc != 0)
1237 return 0;
1238
1239 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1240 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1241 memcpy(sig, param.ed448.sig, 57);
1242 memcpy(sig + 57, param.ed448.sig + 64, 57);
1243
1244 *siglen = ED448_SIGSIZE;
1245 return 1;
1246}
1247
1248static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1249 const unsigned char *sig,
1250 size_t siglen,
1251 const unsigned char *tbs,
1252 size_t tbslen)
1253{
1254 union {
1255 struct {
1256 unsigned char sig[64];
1257 unsigned char pub[32];
1258 } ed25519;
1259 unsigned long long buff[512];
1260 } param;
1261 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1262
1263 if (siglen != ED25519_SIGSIZE)
1264 return 0;
1265
1266 memset(&param, 0, sizeof(param));
1267 s390x_flip_endian32(param.ed25519.sig, sig);
1268 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1269 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1270
1271 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1272 &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1273}
1274
1275static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1276 const unsigned char *sig,
1277 size_t siglen,
1278 const unsigned char *tbs,
1279 size_t tbslen)
1280{
1281 union {
1282 struct {
1283 unsigned char sig[128];
1284 unsigned char pub[64];
1285 } ed448;
1286 unsigned long long buff[512];
1287 } param;
1288 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1289
1290 if (siglen != ED448_SIGSIZE)
1291 return 0;
1292
1293 memset(&param, 0, sizeof(param));
1294 memcpy(param.ed448.sig, sig, 57);
1295 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1296 memcpy(param.ed448.sig + 64, sig + 57, 57);
1297 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1298 memcpy(param.ed448.pub, edkey->pubkey, 57);
1299 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1300
1301 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1302 &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1303}
1304
1305static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1306 EVP_PKEY_X25519,
1307 0, 0, 0, 0, 0, 0, 0,
1308 s390x_pkey_ecx_keygen25519,
1309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1310 s390x_pkey_ecx_derive25519,
1311 pkey_ecx_ctrl,
1312 0
1313};
1314
1315static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1316 EVP_PKEY_X448,
1317 0, 0, 0, 0, 0, 0, 0,
1318 s390x_pkey_ecx_keygen448,
1319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1320 s390x_pkey_ecx_derive448,
1321 pkey_ecx_ctrl,
1322 0
1323};
1324static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1325 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1326 0, 0, 0, 0, 0, 0,
1327 s390x_pkey_ecd_keygen25519,
1328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1329 pkey_ecd_ctrl,
1330 0,
1331 s390x_pkey_ecd_digestsign25519,
1332 s390x_pkey_ecd_digestverify25519
1333};
1334
1335static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1336 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1337 0, 0, 0, 0, 0, 0,
1338 s390x_pkey_ecd_keygen448,
1339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1340 pkey_ecd_ctrl,
1341 0,
1342 s390x_pkey_ecd_digestsign448,
1343 s390x_pkey_ecd_digestverify448
1344};
1345#endif
1346
32ab57cb 1347const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
19bd1fa1
PS
1348{
1349#ifdef S390X_EC_ASM
1350 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1351 return &ecx25519_s390x_pkey_meth;
1352#endif
1353 return &ecx25519_pkey_meth;
1354}
1355
32ab57cb 1356const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
19bd1fa1
PS
1357{
1358#ifdef S390X_EC_ASM
1359 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1360 return &ecx448_s390x_pkey_meth;
1361#endif
1362 return &ecx448_pkey_meth;
1363}
1364
32ab57cb 1365const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
19bd1fa1
PS
1366{
1367#ifdef S390X_EC_ASM
1368 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1369 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1370 && OPENSSL_s390xcap_P.kdsa[0]
1371 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1372 return &ed25519_s390x_pkey_meth;
1373#endif
1374 return &ed25519_pkey_meth;
1375}
1376
32ab57cb 1377const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
19bd1fa1
PS
1378{
1379#ifdef S390X_EC_ASM
1380 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1381 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1382 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1383 return &ed448_s390x_pkey_meth;
1384#endif
1385 return &ed448_pkey_meth;
1386}