]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ecx_meth.c
fix some code with obvious wrong coding style
[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;
1287dabd 141 } else if (ISX448(pkey->ameth->pkey_id)) {
13735cfe
MC
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)
ed576acd 268 libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
8c631cfa 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)
ed576acd 286 libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
8c631cfa 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,
bed7437b
RL
349 OSSL_FUNC_keymgmt_import_fn *importer,
350 OSSL_LIB_CTX *libctx, 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 */
bed7437b 378 rv = importer(to_keydata, selection, params);
6f7d2135
MC
379
380 err:
6d4e6009 381 OSSL_PARAM_BLD_free(tmpl);
3f883c7c 382 OSSL_PARAM_free(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{
4a9fe33c 409 ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
2145ba5e
TM
410 int ret;
411
4a9fe33c 412 if (ecx != NULL) {
b4f447c0 413 dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
4a9fe33c
TM
414 if (dupkey == NULL)
415 return 0;
416 }
2145ba5e 417
4a9fe33c 418 ret = EVP_PKEY_assign(to, from->type, dupkey);
2145ba5e 419 if (!ret)
4a9fe33c 420 ossl_ecx_key_free(dupkey);
2145ba5e
TM
421 return ret;
422}
423
629c72db 424static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 425{
629c72db 426 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
0abae163
RL
427}
428
adf7e6d1 429const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
d2916a5b
DSH
430 EVP_PKEY_X25519,
431 EVP_PKEY_X25519,
756b198d
DSH
432 0,
433 "X25519",
434 "OpenSSL X25519 algorithm",
435
436 ecx_pub_decode,
437 ecx_pub_encode,
438 ecx_pub_cmp,
439 ecx_pub_print,
440
f13fdeb3 441 NULL,
756b198d
DSH
442 ecx_priv_encode,
443 ecx_priv_print,
444
445 ecx_size,
446 ecx_bits,
447 ecx_security_bits,
448
449 0, 0, 0, 0,
450 ecx_cmp_parameters,
451 0, 0,
452
453 ecx_free,
454 ecx_ctrl,
455 NULL,
cc8b15c7
MC
456 NULL,
457
458 NULL,
459 NULL,
460 NULL,
461
462 NULL,
463 NULL,
464 NULL,
465
466 ecx_set_priv_key,
467 ecx_set_pub_key,
0d124b0a
MC
468 ecx_get_priv_key,
469 ecx_get_pub_key,
6f7d2135 470 ecx_pkey_dirty_cnt,
0abae163 471 ecx_pkey_export_to,
f13fdeb3 472 x25519_import_from,
2145ba5e 473 ecx_pkey_copy,
f13fdeb3 474
d8652be0 475 ecx_priv_decode_ex
756b198d
DSH
476};
477
629c72db 478static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 479{
629c72db 480 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
0abae163
RL
481}
482
adf7e6d1 483const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
13735cfe
MC
484 EVP_PKEY_X448,
485 EVP_PKEY_X448,
486 0,
487 "X448",
488 "OpenSSL X448 algorithm",
489
490 ecx_pub_decode,
491 ecx_pub_encode,
492 ecx_pub_cmp,
493 ecx_pub_print,
494
f13fdeb3 495 NULL,
13735cfe
MC
496 ecx_priv_encode,
497 ecx_priv_print,
498
499 ecx_size,
500 ecx_bits,
501 ecx_security_bits,
502
503 0, 0, 0, 0,
504 ecx_cmp_parameters,
505 0, 0,
506
507 ecx_free,
508 ecx_ctrl,
509 NULL,
cc8b15c7
MC
510 NULL,
511
512 NULL,
513 NULL,
514 NULL,
515
516 NULL,
517 NULL,
518 NULL,
519
520 ecx_set_priv_key,
521 ecx_set_pub_key,
0d124b0a
MC
522 ecx_get_priv_key,
523 ecx_get_pub_key,
6f7d2135 524 ecx_pkey_dirty_cnt,
0abae163 525 ecx_pkey_export_to,
f13fdeb3 526 x448_import_from,
2145ba5e 527 ecx_pkey_copy,
f13fdeb3 528
d8652be0 529 ecx_priv_decode_ex
13735cfe
MC
530};
531
532static int ecd_size25519(const EVP_PKEY *pkey)
8ecade8b
DSH
533{
534 return ED25519_SIGSIZE;
535}
536
13735cfe
MC
537static int ecd_size448(const EVP_PKEY *pkey)
538{
539 return ED448_SIGSIZE;
540}
541
ded346fa
DDO
542static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
543 const void *asn, const X509_ALGOR *sigalg,
544 const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
9f98fbad
DSH
545{
546 const ASN1_OBJECT *obj;
547 int ptype;
13735cfe 548 int nid;
9f98fbad 549
13735cfe 550 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
9f98fbad 551 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
13735cfe
MC
552 nid = OBJ_obj2nid(obj);
553 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
9311d0c4 554 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
9f98fbad
DSH
555 return 0;
556 }
557
558 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
559 return 0;
560
561 return 2;
562}
563
ded346fa
DDO
564static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
565 const void *asn,
13735cfe
MC
566 X509_ALGOR *alg1, X509_ALGOR *alg2,
567 ASN1_BIT_STRING *str)
9f98fbad
DSH
568{
569 /* Set algorithms identifiers */
570 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
571 if (alg2)
572 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
c2969ff6 573 /* Algorithm identifiers set: carry on as normal */
9f98fbad
DSH
574 return 3;
575}
576
13735cfe
MC
577static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
578 const ASN1_STRING *sig)
684c41c8
DSH
579{
580 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
581 X509_SIG_INFO_TLS);
582 return 1;
583}
584
ded346fa
DDO
585static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
586 const void *asn,
13735cfe
MC
587 X509_ALGOR *alg1, X509_ALGOR *alg2,
588 ASN1_BIT_STRING *str)
589{
590 /* Set algorithm identifier */
591 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
592 if (alg2 != NULL)
593 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
594 /* Algorithm identifier set: carry on as normal */
595 return 3;
596}
597
598static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
599 const ASN1_STRING *sig)
600{
601 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
602 X509_SIG_INFO_TLS);
603 return 1;
604}
605
629c72db 606static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 607{
629c72db 608 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
0abae163 609}
13735cfe 610
adf7e6d1 611const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
d2916a5b
DSH
612 EVP_PKEY_ED25519,
613 EVP_PKEY_ED25519,
8ecade8b
DSH
614 0,
615 "ED25519",
616 "OpenSSL ED25519 algorithm",
617
618 ecx_pub_decode,
619 ecx_pub_encode,
620 ecx_pub_cmp,
621 ecx_pub_print,
622
f13fdeb3 623 NULL,
8ecade8b
DSH
624 ecx_priv_encode,
625 ecx_priv_print,
626
13735cfe
MC
627 ecd_size25519,
628 ecx_bits,
629 ecx_security_bits,
630
631 0, 0, 0, 0,
632 ecx_cmp_parameters,
633 0, 0,
634
635 ecx_free,
aabbc24e 636 ecd_ctrl,
13735cfe
MC
637 NULL,
638 NULL,
639 ecd_item_verify,
640 ecd_item_sign25519,
cc8b15c7
MC
641 ecd_sig_info_set25519,
642
643 NULL,
644 NULL,
645 NULL,
646
647 ecx_set_priv_key,
648 ecx_set_pub_key,
0d124b0a
MC
649 ecx_get_priv_key,
650 ecx_get_pub_key,
3965480c 651 ecx_pkey_dirty_cnt,
0abae163 652 ecx_pkey_export_to,
f13fdeb3 653 ed25519_import_from,
2145ba5e 654 ecx_pkey_copy,
f13fdeb3 655
d8652be0 656 ecx_priv_decode_ex
13735cfe
MC
657};
658
629c72db 659static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
0abae163 660{
629c72db 661 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
0abae163
RL
662}
663
adf7e6d1 664const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
13735cfe
MC
665 EVP_PKEY_ED448,
666 EVP_PKEY_ED448,
667 0,
668 "ED448",
669 "OpenSSL ED448 algorithm",
670
671 ecx_pub_decode,
672 ecx_pub_encode,
673 ecx_pub_cmp,
674 ecx_pub_print,
675
f13fdeb3 676 NULL,
13735cfe
MC
677 ecx_priv_encode,
678 ecx_priv_print,
679
680 ecd_size448,
8ecade8b
DSH
681 ecx_bits,
682 ecx_security_bits,
683
684 0, 0, 0, 0,
685 ecx_cmp_parameters,
686 0, 0,
687
688 ecx_free,
aabbc24e 689 ecd_ctrl,
8ecade8b 690 NULL,
9f98fbad
DSH
691 NULL,
692 ecd_item_verify,
13735cfe 693 ecd_item_sign448,
cc8b15c7
MC
694 ecd_sig_info_set448,
695
696 NULL,
697 NULL,
698 NULL,
699
700 ecx_set_priv_key,
701 ecx_set_pub_key,
0d124b0a
MC
702 ecx_get_priv_key,
703 ecx_get_pub_key,
3965480c 704 ecx_pkey_dirty_cnt,
0abae163 705 ecx_pkey_export_to,
f13fdeb3 706 ed448_import_from,
2145ba5e 707 ecx_pkey_copy,
f13fdeb3 708
d8652be0 709 ecx_priv_decode_ex
8ecade8b
DSH
710};
711
756b198d
DSH
712static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
713{
cf333799
RL
714 ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
715 KEY_OP_PUBLIC, NULL, NULL);
716
717 if (ecx != NULL) {
718 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
719 return 1;
720 }
721 return 0;
756b198d
DSH
722}
723
13735cfe
MC
724static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
725 size_t *keylen,
726 const unsigned char **privkey,
727 const unsigned char **pubkey)
756b198d 728{
13735cfe 729 const ECX_KEY *ecxkey, *peerkey;
756b198d
DSH
730
731 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
9311d0c4 732 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
756b198d
DSH
733 return 0;
734 }
5dc6489b
MC
735 ecxkey = evp_pkey_get_legacy(ctx->pkey);
736 peerkey = evp_pkey_get_legacy(ctx->peerkey);
13735cfe 737 if (ecxkey == NULL || ecxkey->privkey == NULL) {
9311d0c4 738 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
756b198d
DSH
739 return 0;
740 }
741 if (peerkey == NULL) {
9311d0c4 742 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
756b198d
DSH
743 return 0;
744 }
13735cfe
MC
745 *privkey = ecxkey->privkey;
746 *pubkey = peerkey->pubkey;
747
748 return 1;
749}
750
751static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
752 size_t *keylen)
753{
754 const unsigned char *privkey, *pubkey;
755
756 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
757 || (key != NULL
054d43ff 758 && ossl_x25519(key, privkey, pubkey) == 0))
13735cfe 759 return 0;
756b198d 760 *keylen = X25519_KEYLEN;
13735cfe
MC
761 return 1;
762}
763
764static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
765 size_t *keylen)
766{
767 const unsigned char *privkey, *pubkey;
768
769 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
770 || (key != NULL
054d43ff 771 && ossl_x448(key, privkey, pubkey) == 0))
756b198d 772 return 0;
13735cfe 773 *keylen = X448_KEYLEN;
756b198d
DSH
774 return 1;
775}
776
777static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
778{
779 /* Only need to handle peer key for derivation */
780 if (type == EVP_PKEY_CTRL_PEER_KEY)
781 return 1;
782 return -2;
783}
784
19bd1fa1 785static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
d2916a5b 786 EVP_PKEY_X25519,
756b198d
DSH
787 0, 0, 0, 0, 0, 0, 0,
788 pkey_ecx_keygen,
789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13735cfe 790 pkey_ecx_derive25519,
756b198d
DSH
791 pkey_ecx_ctrl,
792 0
793};
42a3008a 794
19bd1fa1 795static const EVP_PKEY_METHOD ecx448_pkey_meth = {
13735cfe
MC
796 EVP_PKEY_X448,
797 0, 0, 0, 0, 0, 0, 0,
798 pkey_ecx_keygen,
799 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
800 pkey_ecx_derive448,
801 pkey_ecx_ctrl,
802 0
803};
804
07824f30
MC
805static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
806 size_t *siglen, const unsigned char *tbs,
807 size_t tbslen)
42a3008a 808{
5dc6489b 809 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
42a3008a
DSH
810
811 if (sig == NULL) {
812 *siglen = ED25519_SIGSIZE;
813 return 1;
814 }
815 if (*siglen < ED25519_SIGSIZE) {
9311d0c4 816 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
42a3008a
DSH
817 return 0;
818 }
819
054d43ff
SL
820 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
821 NULL) == 0)
42a3008a
DSH
822 return 0;
823 *siglen = ED25519_SIGSIZE;
824 return 1;
825}
826
07824f30
MC
827static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
828 size_t *siglen, const unsigned char *tbs,
829 size_t tbslen)
13735cfe 830{
5dc6489b 831 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
13735cfe
MC
832
833 if (sig == NULL) {
834 *siglen = ED448_SIGSIZE;
835 return 1;
836 }
837 if (*siglen < ED448_SIGSIZE) {
9311d0c4 838 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
13735cfe
MC
839 return 0;
840 }
841
054d43ff
SL
842 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
843 edkey->privkey, NULL, 0, edkey->propq) == 0)
13735cfe
MC
844 return 0;
845 *siglen = ED448_SIGSIZE;
846 return 1;
847}
848
07824f30
MC
849static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
850 size_t siglen, const unsigned char *tbs,
851 size_t tbslen)
42a3008a 852{
5dc6489b 853 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
42a3008a
DSH
854
855 if (siglen != ED25519_SIGSIZE)
856 return 0;
857
054d43ff
SL
858 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
859 edkey->libctx, edkey->propq);
42a3008a
DSH
860}
861
07824f30
MC
862static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
863 size_t siglen, const unsigned char *tbs,
864 size_t tbslen)
13735cfe 865{
5dc6489b 866 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
13735cfe
MC
867
868 if (siglen != ED448_SIGSIZE)
869 return 0;
870
054d43ff
SL
871 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
872 NULL, 0, edkey->propq);
13735cfe
MC
873}
874
42a3008a
DSH
875static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
876{
877 switch (type) {
878 case EVP_PKEY_CTRL_MD:
879 /* Only NULL allowed as digest */
f3021aca 880 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
42a3008a 881 return 1;
9311d0c4 882 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
42a3008a
DSH
883 return 0;
884
885 case EVP_PKEY_CTRL_DIGESTINIT:
886 return 1;
887 }
888 return -2;
889}
890
19bd1fa1 891static const EVP_PKEY_METHOD ed25519_pkey_meth = {
d2916a5b 892 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
42a3008a
DSH
893 0, 0, 0, 0, 0, 0,
894 pkey_ecx_keygen,
07824f30 895 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42a3008a
DSH
896 pkey_ecd_ctrl,
897 0,
13735cfe
MC
898 pkey_ecd_digestsign25519,
899 pkey_ecd_digestverify25519
900};
901
19bd1fa1 902static const EVP_PKEY_METHOD ed448_pkey_meth = {
13735cfe
MC
903 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
904 0, 0, 0, 0, 0, 0,
905 pkey_ecx_keygen,
07824f30 906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13735cfe
MC
907 pkey_ecd_ctrl,
908 0,
909 pkey_ecd_digestsign448,
910 pkey_ecd_digestverify448
42a3008a 911};
19bd1fa1
PS
912
913#ifdef S390X_EC_ASM
914# include "s390x_arch.h"
19bd1fa1
PS
915
916static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
917{
918 static const unsigned char generator[] = {
919 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
922 };
32ab57cb
SL
923 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
924 ctx->propquery);
19bd1fa1
PS
925 unsigned char *privkey = NULL, *pubkey;
926
19bd1fa1 927 if (key == NULL) {
9311d0c4 928 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
929 goto err;
930 }
931
932 pubkey = key->pubkey;
933
32ab57cb 934 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 935 if (privkey == NULL) {
9311d0c4 936 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
937 goto err;
938 }
939
5cbd2ea3 940 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
19bd1fa1
PS
941 goto err;
942
943 privkey[0] &= 248;
944 privkey[31] &= 127;
945 privkey[31] |= 64;
946
947 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
948 goto err;
949
950 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
951 return 1;
952 err:
32ab57cb 953 ossl_ecx_key_free(key);
19bd1fa1
PS
954 return 0;
955}
956
957static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
958{
959 static const unsigned char generator[] = {
960 0x05, 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, 0x00, 0x00, 0x00, 0x00,
963 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
965 };
32ab57cb
SL
966 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
967 ctx->propquery);
19bd1fa1
PS
968 unsigned char *privkey = NULL, *pubkey;
969
19bd1fa1 970 if (key == NULL) {
9311d0c4 971 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
972 goto err;
973 }
974
975 pubkey = key->pubkey;
976
32ab57cb 977 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 978 if (privkey == NULL) {
9311d0c4 979 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
980 goto err;
981 }
982
5cbd2ea3 983 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
19bd1fa1
PS
984 goto err;
985
986 privkey[0] &= 252;
987 privkey[55] |= 128;
988
989 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
990 goto err;
991
992 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
993 return 1;
994 err:
32ab57cb 995 ossl_ecx_key_free(key);
19bd1fa1
PS
996 return 0;
997}
998
999static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1000{
1001 static const unsigned char generator_x[] = {
1002 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1003 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1004 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1005 };
1006 static const unsigned char generator_y[] = {
1007 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1008 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1009 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1010 };
1011 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
32ab57cb
SL
1012 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1013 ctx->propquery);
19bd1fa1 1014 unsigned char *privkey = NULL, *pubkey;
85d843c8 1015 unsigned int sz;
e72dbd8e
SL
1016 EVP_MD *md = NULL;
1017 int rv;
19bd1fa1 1018
19bd1fa1 1019 if (key == NULL) {
9311d0c4 1020 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1021 goto err;
1022 }
1023
1024 pubkey = key->pubkey;
1025
32ab57cb 1026 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 1027 if (privkey == NULL) {
9311d0c4 1028 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1029 goto err;
1030 }
1031
5cbd2ea3 1032 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
19bd1fa1
PS
1033 goto err;
1034
e72dbd8e
SL
1035 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1036 if (md == NULL)
1037 goto err;
1038
1039 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1040 EVP_MD_free(md);
1041 if (!rv)
85d843c8
P
1042 goto err;
1043
19bd1fa1
PS
1044 buff[0] &= 248;
1045 buff[31] &= 63;
1046 buff[31] |= 64;
1047
1048 if (s390x_ed25519_mul(x_dst, pubkey,
1049 generator_x, generator_y, buff) != 1)
1050 goto err;
1051
1052 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1053
1054 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1055 return 1;
1056 err:
32ab57cb 1057 ossl_ecx_key_free(key);
19bd1fa1
PS
1058 return 0;
1059}
1060
1061static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1062{
1063 static const unsigned char generator_x[] = {
1064 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1065 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1066 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1067 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1068 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1069 };
1070 static const unsigned char generator_y[] = {
1071 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1072 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1073 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1074 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1075 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1076 };
1077 unsigned char x_dst[57], buff[114];
32ab57cb
SL
1078 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1079 ctx->propquery);
19bd1fa1
PS
1080 unsigned char *privkey = NULL, *pubkey;
1081 EVP_MD_CTX *hashctx = NULL;
e72dbd8e
SL
1082 EVP_MD *md = NULL;
1083 int rv;
19bd1fa1 1084
19bd1fa1 1085 if (key == NULL) {
9311d0c4 1086 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1087 goto err;
1088 }
1089
1090 pubkey = key->pubkey;
1091
32ab57cb 1092 privkey = ossl_ecx_key_allocate_privkey(key);
19bd1fa1 1093 if (privkey == NULL) {
9311d0c4 1094 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
19bd1fa1
PS
1095 goto err;
1096 }
1097
5cbd2ea3 1098 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
19bd1fa1
PS
1099 goto err;
1100
1101 hashctx = EVP_MD_CTX_new();
1102 if (hashctx == NULL)
1103 goto err;
e72dbd8e
SL
1104
1105 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1106 if (md == NULL)
1107 goto err;
1108
1109 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1110 EVP_MD_free(md);
1111 if (rv != 1)
19bd1fa1 1112 goto err;
e72dbd8e 1113
19bd1fa1
PS
1114 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1115 goto err;
1116 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1117 goto err;
1118
1119 buff[0] &= -4;
1120 buff[55] |= 0x80;
1121 buff[56] = 0;
1122
1123 if (s390x_ed448_mul(x_dst, pubkey,
1124 generator_x, generator_y, buff) != 1)
1125 goto err;
1126
1127 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1128
1129 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1130 EVP_MD_CTX_free(hashctx);
1131 return 1;
1132 err:
32ab57cb 1133 ossl_ecx_key_free(key);
19bd1fa1
PS
1134 EVP_MD_CTX_free(hashctx);
1135 return 0;
1136}
1137
1138static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1139 size_t *keylen)
1140{
1141 const unsigned char *privkey, *pubkey;
1142
1143 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1144 return 0;
1145
1146 if (key != NULL)
1147 return s390x_x25519_mul(key, pubkey, privkey);
1148
1149 *keylen = X25519_KEYLEN;
1150 return 1;
1151}
1152
1153static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1154 size_t *keylen)
1155{
1156 const unsigned char *privkey, *pubkey;
1157
1158 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1159 return 0;
1160
1161 if (key != NULL)
1162 return s390x_x448_mul(key, pubkey, privkey);
1163
1164 *keylen = X448_KEYLEN;
1165 return 1;
1166}
1167
1168static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1169 unsigned char *sig, size_t *siglen,
1170 const unsigned char *tbs,
1171 size_t tbslen)
1172{
1173 union {
1174 struct {
1175 unsigned char sig[64];
1176 unsigned char priv[32];
1177 } ed25519;
1178 unsigned long long buff[512];
1179 } param;
5dc6489b 1180 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
19bd1fa1
PS
1181 int rc;
1182
1183 if (sig == NULL) {
1184 *siglen = ED25519_SIGSIZE;
1185 return 1;
1186 }
1187
1188 if (*siglen < ED25519_SIGSIZE) {
9311d0c4 1189 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
19bd1fa1
PS
1190 return 0;
1191 }
1192
1193 memset(&param, 0, sizeof(param));
1194 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1195
1196 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1197 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1198 if (rc != 0)
1199 return 0;
1200
1201 s390x_flip_endian32(sig, param.ed25519.sig);
1202 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1203
1204 *siglen = ED25519_SIGSIZE;
1205 return 1;
1206}
1207
1208static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1209 unsigned char *sig, size_t *siglen,
1210 const unsigned char *tbs,
1211 size_t tbslen)
1212{
1213 union {
1214 struct {
1215 unsigned char sig[128];
1216 unsigned char priv[64];
1217 } ed448;
1218 unsigned long long buff[512];
1219 } param;
5dc6489b 1220 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
19bd1fa1
PS
1221 int rc;
1222
1223 if (sig == NULL) {
1224 *siglen = ED448_SIGSIZE;
1225 return 1;
1226 }
1227
1228 if (*siglen < ED448_SIGSIZE) {
9311d0c4 1229 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
19bd1fa1
PS
1230 return 0;
1231 }
1232
1233 memset(&param, 0, sizeof(param));
1234 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1235
1236 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1237 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1238 if (rc != 0)
1239 return 0;
1240
1241 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1242 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1243 memcpy(sig, param.ed448.sig, 57);
1244 memcpy(sig + 57, param.ed448.sig + 64, 57);
1245
1246 *siglen = ED448_SIGSIZE;
1247 return 1;
1248}
1249
1250static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1251 const unsigned char *sig,
1252 size_t siglen,
1253 const unsigned char *tbs,
1254 size_t tbslen)
1255{
1256 union {
1257 struct {
1258 unsigned char sig[64];
1259 unsigned char pub[32];
1260 } ed25519;
1261 unsigned long long buff[512];
1262 } param;
5dc6489b 1263 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
19bd1fa1
PS
1264
1265 if (siglen != ED25519_SIGSIZE)
1266 return 0;
1267
1268 memset(&param, 0, sizeof(param));
1269 s390x_flip_endian32(param.ed25519.sig, sig);
1270 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1271 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1272
1273 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1274 &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1275}
1276
1277static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1278 const unsigned char *sig,
1279 size_t siglen,
1280 const unsigned char *tbs,
1281 size_t tbslen)
1282{
1283 union {
1284 struct {
1285 unsigned char sig[128];
1286 unsigned char pub[64];
1287 } ed448;
1288 unsigned long long buff[512];
1289 } param;
5dc6489b 1290 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
19bd1fa1
PS
1291
1292 if (siglen != ED448_SIGSIZE)
1293 return 0;
1294
1295 memset(&param, 0, sizeof(param));
1296 memcpy(param.ed448.sig, sig, 57);
1297 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1298 memcpy(param.ed448.sig + 64, sig + 57, 57);
1299 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1300 memcpy(param.ed448.pub, edkey->pubkey, 57);
1301 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1302
1303 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1304 &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1305}
1306
1307static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1308 EVP_PKEY_X25519,
1309 0, 0, 0, 0, 0, 0, 0,
1310 s390x_pkey_ecx_keygen25519,
1311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1312 s390x_pkey_ecx_derive25519,
1313 pkey_ecx_ctrl,
1314 0
1315};
1316
1317static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1318 EVP_PKEY_X448,
1319 0, 0, 0, 0, 0, 0, 0,
1320 s390x_pkey_ecx_keygen448,
1321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1322 s390x_pkey_ecx_derive448,
1323 pkey_ecx_ctrl,
1324 0
1325};
1326static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1327 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1328 0, 0, 0, 0, 0, 0,
1329 s390x_pkey_ecd_keygen25519,
1330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1331 pkey_ecd_ctrl,
1332 0,
1333 s390x_pkey_ecd_digestsign25519,
1334 s390x_pkey_ecd_digestverify25519
1335};
1336
1337static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1338 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1339 0, 0, 0, 0, 0, 0,
1340 s390x_pkey_ecd_keygen448,
1341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1342 pkey_ecd_ctrl,
1343 0,
1344 s390x_pkey_ecd_digestsign448,
1345 s390x_pkey_ecd_digestverify448
1346};
1347#endif
1348
32ab57cb 1349const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
19bd1fa1
PS
1350{
1351#ifdef S390X_EC_ASM
1352 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1353 return &ecx25519_s390x_pkey_meth;
1354#endif
1355 return &ecx25519_pkey_meth;
1356}
1357
32ab57cb 1358const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
19bd1fa1
PS
1359{
1360#ifdef S390X_EC_ASM
1361 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1362 return &ecx448_s390x_pkey_meth;
1363#endif
1364 return &ecx448_pkey_meth;
1365}
1366
32ab57cb 1367const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
19bd1fa1
PS
1368{
1369#ifdef S390X_EC_ASM
1370 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1371 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1372 && OPENSSL_s390xcap_P.kdsa[0]
1373 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1374 return &ed25519_s390x_pkey_meth;
1375#endif
1376 return &ed25519_pkey_meth;
1377}
1378
32ab57cb 1379const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
19bd1fa1
PS
1380{
1381#ifdef S390X_EC_ASM
1382 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1383 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1384 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1385 return &ed448_s390x_pkey_meth;
1386#endif
1387 return &ed448_pkey_meth;
1388}