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