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