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