1 /*
2 * Copyright 2006-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
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
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
16 #include <stdio.h>
17 #include <openssl/x509.h>
18 #include <openssl/ec.h>
19 #include <openssl/core_names.h>
20 #include <openssl/param_build.h>
21 #include <openssl/rand.h>
22 #include "internal/cryptlib.h"
23 #include "internal/provider.h"
24 #include "crypto/asn1.h"
25 #include "crypto/evp.h"
26 #include "crypto/ecx.h"
27 #include "ec_local.h"
28 #include "curve448/curve448_local.h"
29 #include "ecx_backend.h"
30
ecx_pub_encode(X509_PUBKEY * pk,const EVP_PKEY * pkey)31 static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
32 {
33 const ECX_KEY *ecxkey = pkey->pkey.ecx;
34 unsigned char *penc;
35
36 if (ecxkey == NULL) {
37 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
38 return 0;
39 }
40
41 penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
42 if (penc == NULL) {
43 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
44 return 0;
45 }
46
47 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
48 V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
49 OPENSSL_free(penc);
50 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
51 return 0;
52 }
53 return 1;
54 }
55
ecx_pub_decode(EVP_PKEY * pkey,const X509_PUBKEY * pubkey)56 static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
57 {
58 const unsigned char *p;
59 int pklen;
60 X509_ALGOR *palg;
61 ECX_KEY *ecx;
62 int ret = 0;
63
64 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
65 return 0;
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;
73 }
74
ecx_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)75 static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
76 {
77 const ECX_KEY *akey = a->pkey.ecx;
78 const ECX_KEY *bkey = b->pkey.ecx;
79
80 if (akey == NULL || bkey == NULL)
81 return -2;
82
83 return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
84 }
85
ecx_priv_decode_ex(EVP_PKEY * pkey,const PKCS8_PRIV_KEY_INFO * p8,OSSL_LIB_CTX * libctx,const char * propq)86 static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
87 OSSL_LIB_CTX *libctx, const char *propq)
88 {
89 int ret = 0;
90 ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
91
92 if (ecx != NULL) {
93 ret = 1;
94 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
95 }
96
97 return ret;
98 }
99
ecx_priv_encode(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pkey)100 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
101 {
102 const ECX_KEY *ecxkey = pkey->pkey.ecx;
103 ASN1_OCTET_STRING oct;
104 unsigned char *penc = NULL;
105 int penclen;
106
107 if (ecxkey == NULL || ecxkey->privkey == NULL) {
108 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
109 return 0;
110 }
111
112 oct.data = ecxkey->privkey;
113 oct.length = KEYLEN(pkey);
114 oct.flags = 0;
115
116 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
117 if (penclen < 0) {
118 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
119 return 0;
120 }
121
122 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
123 V_ASN1_UNDEF, NULL, penc, penclen)) {
124 OPENSSL_clear_free(penc, penclen);
125 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
126 return 0;
127 }
128
129 return 1;
130 }
131
ecx_size(const EVP_PKEY * pkey)132 static int ecx_size(const EVP_PKEY *pkey)
133 {
134 return KEYLEN(pkey);
135 }
136
ecx_bits(const EVP_PKEY * pkey)137 static int ecx_bits(const EVP_PKEY *pkey)
138 {
139 if (IS25519(pkey->ameth->pkey_id)) {
140 return X25519_BITS;
141 } else if (ISX448(pkey->ameth->pkey_id)) {
142 return X448_BITS;
143 } else {
144 return ED448_BITS;
145 }
146 }
147
ecx_security_bits(const EVP_PKEY * pkey)148 static int ecx_security_bits(const EVP_PKEY *pkey)
149 {
150 if (IS25519(pkey->ameth->pkey_id)) {
151 return X25519_SECURITY_BITS;
152 } else {
153 return X448_SECURITY_BITS;
154 }
155 }
156
ecx_free(EVP_PKEY * pkey)157 static void ecx_free(EVP_PKEY *pkey)
158 {
159 ossl_ecx_key_free(pkey->pkey.ecx);
160 }
161
162 /* "parameters" are always equal */
ecx_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)163 static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
164 {
165 return 1;
166 }
167
ecx_key_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx,ecx_key_op_t op)168 static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
169 ASN1_PCTX *ctx, ecx_key_op_t op)
170 {
171 const ECX_KEY *ecxkey = pkey->pkey.ecx;
172 const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
173
174 if (op == KEY_OP_PRIVATE) {
175 if (ecxkey == NULL || ecxkey->privkey == NULL) {
176 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
177 return 0;
178 return 1;
179 }
180 if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
181 return 0;
182 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
183 return 0;
184 if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
185 indent + 4) == 0)
186 return 0;
187 } else {
188 if (ecxkey == NULL) {
189 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
190 return 0;
191 return 1;
192 }
193 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
194 return 0;
195 }
196 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
197 return 0;
198
199 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
200 indent + 4) == 0)
201 return 0;
202 return 1;
203 }
204
ecx_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)205 static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
206 ASN1_PCTX *ctx)
207 {
208 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
209 }
210
ecx_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)211 static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
212 ASN1_PCTX *ctx)
213 {
214 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
215 }
216
ecx_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)217 static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
218 {
219 switch (op) {
220
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);
224
225 if (ecx != NULL) {
226 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
227 return 1;
228 }
229 return 0;
230 }
231 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
232 if (pkey->pkey.ecx != NULL) {
233 unsigned char **ppt = arg2;
234
235 *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
236 if (*ppt != NULL)
237 return KEYLEN(pkey);
238 }
239 return 0;
240
241 default:
242 return -2;
243
244 }
245 }
246
ecd_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)247 static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
248 {
249 switch (op) {
250 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
251 /* We currently only support Pure EdDSA which takes no digest */
252 *(int *)arg2 = NID_undef;
253 return 2;
254
255 default:
256 return -2;
257
258 }
259 }
260
ecx_set_priv_key(EVP_PKEY * pkey,const unsigned char * priv,size_t len)261 static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
262 size_t len)
263 {
264 OSSL_LIB_CTX *libctx = NULL;
265 ECX_KEY *ecx = NULL;
266
267 if (pkey->keymgmt != NULL)
268 libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
269
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;
278 }
279
ecx_set_pub_key(EVP_PKEY * pkey,const unsigned char * pub,size_t len)280 static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
281 {
282 OSSL_LIB_CTX *libctx = NULL;
283 ECX_KEY *ecx = NULL;
284
285 if (pkey->keymgmt != NULL)
286 libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
287
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;
296 }
297
ecx_get_priv_key(const EVP_PKEY * pkey,unsigned char * priv,size_t * len)298 static 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
ecx_get_pub_key(const EVP_PKEY * pkey,unsigned char * pub,size_t * len)319 static 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
ecx_pkey_dirty_cnt(const EVP_PKEY * pkey)339 static 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
ecx_pkey_export_to(const EVP_PKEY * from,void * to_keydata,OSSL_FUNC_keymgmt_import_fn * importer,OSSL_LIB_CTX * libctx,const char * propq)348 static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
349 OSSL_FUNC_keymgmt_import_fn *importer,
350 OSSL_LIB_CTX *libctx, const char *propq)
351 {
352 const ECX_KEY *key = from->pkey.ecx;
353 OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
354 OSSL_PARAM *params = NULL;
355 int selection = 0;
356 int rv = 0;
357
358 if (tmpl == NULL)
359 return 0;
360
361 /* A key must at least have a public part */
362 if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
363 key->pubkey, key->keylen))
364 goto err;
365 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
366
367 if (key->privkey != NULL) {
368 if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
369 OSSL_PKEY_PARAM_PRIV_KEY,
370 key->privkey, key->keylen))
371 goto err;
372 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
373 }
374
375 params = OSSL_PARAM_BLD_to_param(tmpl);
376
377 /* We export, the provider imports */
378 rv = importer(to_keydata, selection, params);
379
380 err:
381 OSSL_PARAM_BLD_free(tmpl);
382 OSSL_PARAM_free(params);
383 return rv;
384 }
385
ecx_generic_import_from(const OSSL_PARAM params[],void * vpctx,int keytype)386 static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
387 int keytype)
388 {
389 EVP_PKEY_CTX *pctx = vpctx;
390 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
391 ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
392 pctx->propquery);
393
394 if (ecx == NULL) {
395 ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
396 return 0;
397 }
398
399 if (!ossl_ecx_key_fromdata(ecx, params, 1)
400 || !EVP_PKEY_assign(pkey, keytype, ecx)) {
401 ossl_ecx_key_free(ecx);
402 return 0;
403 }
404 return 1;
405 }
406
ecx_pkey_copy(EVP_PKEY * to,EVP_PKEY * from)407 static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
408 {
409 ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
410 int ret;
411
412 if (ecx != NULL) {
413 dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
414 if (dupkey == NULL)
415 return 0;
416 }
417
418 ret = EVP_PKEY_assign(to, from->type, dupkey);
419 if (!ret)
420 ossl_ecx_key_free(dupkey);
421 return ret;
422 }
423
x25519_import_from(const OSSL_PARAM params[],void * vpctx)424 static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
425 {
426 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
427 }
428
429 const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
430 EVP_PKEY_X25519,
431 EVP_PKEY_X25519,
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
441 NULL,
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,
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,
468 ecx_get_priv_key,
469 ecx_get_pub_key,
470 ecx_pkey_dirty_cnt,
471 ecx_pkey_export_to,
472 x25519_import_from,
473 ecx_pkey_copy,
474
475 ecx_priv_decode_ex
476 };
477
x448_import_from(const OSSL_PARAM params[],void * vpctx)478 static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
479 {
480 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
481 }
482
483 const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
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
495 NULL,
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,
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,
522 ecx_get_priv_key,
523 ecx_get_pub_key,
524 ecx_pkey_dirty_cnt,
525 ecx_pkey_export_to,
526 x448_import_from,
527 ecx_pkey_copy,
528
529 ecx_priv_decode_ex
530 };
531
ecd_size25519(const EVP_PKEY * pkey)532 static int ecd_size25519(const EVP_PKEY *pkey)
533 {
534 return ED25519_SIGSIZE;
535 }
536
ecd_size448(const EVP_PKEY * pkey)537 static int ecd_size448(const EVP_PKEY *pkey)
538 {
539 return ED448_SIGSIZE;
540 }
541
ecd_item_verify(EVP_MD_CTX * ctx,const ASN1_ITEM * it,const void * asn,const X509_ALGOR * sigalg,const ASN1_BIT_STRING * str,EVP_PKEY * pkey)542 static 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)
545 {
546 const ASN1_OBJECT *obj;
547 int ptype;
548 int nid;
549
550 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
551 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
552 nid = OBJ_obj2nid(obj);
553 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
554 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
555 return 0;
556 }
557
558 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
559 return 0;
560
561 return 2;
562 }
563
ecd_item_sign(X509_ALGOR * alg1,X509_ALGOR * alg2,int nid)564 static 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
ecd_item_sign25519(EVP_MD_CTX * ctx,const ASN1_ITEM * it,const void * asn,X509_ALGOR * alg1,X509_ALGOR * alg2,ASN1_BIT_STRING * str)575 static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
576 const void *asn,
577 X509_ALGOR *alg1, X509_ALGOR *alg2,
578 ASN1_BIT_STRING *str)
579 {
580 return ecd_item_sign(alg1, alg2, NID_ED25519);
581 }
582
ecd_sig_info_set25519(X509_SIG_INFO * siginf,const X509_ALGOR * alg,const ASN1_STRING * sig)583 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
584 const ASN1_STRING *sig)
585 {
586 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
587 X509_SIG_INFO_TLS);
588 return 1;
589 }
590
ecd_item_sign448(EVP_MD_CTX * ctx,const ASN1_ITEM * it,const void * asn,X509_ALGOR * alg1,X509_ALGOR * alg2,ASN1_BIT_STRING * str)591 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
592 const void *asn,
593 X509_ALGOR *alg1, X509_ALGOR *alg2,
594 ASN1_BIT_STRING *str)
595 {
596 return ecd_item_sign(alg1, alg2, NID_ED448);
597 }
598
ecd_sig_info_set448(X509_SIG_INFO * siginf,const X509_ALGOR * alg,const ASN1_STRING * sig)599 static 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
ed25519_import_from(const OSSL_PARAM params[],void * vpctx)607 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
608 {
609 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
610 }
611
612 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
613 EVP_PKEY_ED25519,
614 EVP_PKEY_ED25519,
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
624 NULL,
625 ecx_priv_encode,
626 ecx_priv_print,
627
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,
637 ecd_ctrl,
638 NULL,
639 NULL,
640 ecd_item_verify,
641 ecd_item_sign25519,
642 ecd_sig_info_set25519,
643
644 NULL,
645 NULL,
646 NULL,
647
648 ecx_set_priv_key,
649 ecx_set_pub_key,
650 ecx_get_priv_key,
651 ecx_get_pub_key,
652 ecx_pkey_dirty_cnt,
653 ecx_pkey_export_to,
654 ed25519_import_from,
655 ecx_pkey_copy,
656
657 ecx_priv_decode_ex
658 };
659
ed448_import_from(const OSSL_PARAM params[],void * vpctx)660 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
661 {
662 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
663 }
664
665 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
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
677 NULL,
678 ecx_priv_encode,
679 ecx_priv_print,
680
681 ecd_size448,
682 ecx_bits,
683 ecx_security_bits,
684
685 0, 0, 0, 0,
686 ecx_cmp_parameters,
687 0, 0,
688
689 ecx_free,
690 ecd_ctrl,
691 NULL,
692 NULL,
693 ecd_item_verify,
694 ecd_item_sign448,
695 ecd_sig_info_set448,
696
697 NULL,
698 NULL,
699 NULL,
700
701 ecx_set_priv_key,
702 ecx_set_pub_key,
703 ecx_get_priv_key,
704 ecx_get_pub_key,
705 ecx_pkey_dirty_cnt,
706 ecx_pkey_export_to,
707 ed448_import_from,
708 ecx_pkey_copy,
709
710 ecx_priv_decode_ex
711 };
712
pkey_ecx_keygen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)713 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
714 {
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;
723 }
724
validate_ecx_derive(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen,const unsigned char ** privkey,const unsigned char ** pubkey)725 static 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)
729 {
730 const ECX_KEY *ecxkey, *peerkey;
731
732 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
733 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
734 return 0;
735 }
736 ecxkey = evp_pkey_get_legacy(ctx->pkey);
737 peerkey = evp_pkey_get_legacy(ctx->peerkey);
738 if (ecxkey == NULL || ecxkey->privkey == NULL) {
739 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
740 return 0;
741 }
742 if (peerkey == NULL) {
743 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
744 return 0;
745 }
746 *privkey = ecxkey->privkey;
747 *pubkey = peerkey->pubkey;
748
749 return 1;
750 }
751
pkey_ecx_derive25519(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)752 static 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
759 && ossl_x25519(key, privkey, pubkey) == 0))
760 return 0;
761 *keylen = X25519_KEYLEN;
762 return 1;
763 }
764
pkey_ecx_derive448(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)765 static 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
772 && ossl_x448(key, privkey, pubkey) == 0))
773 return 0;
774 *keylen = X448_KEYLEN;
775 return 1;
776 }
777
pkey_ecx_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)778 static 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
786 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
787 EVP_PKEY_X25519,
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,
791 pkey_ecx_derive25519,
792 pkey_ecx_ctrl,
793 0
794 };
795
796 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
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
pkey_ecd_digestsign25519(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)806 static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
807 size_t *siglen, const unsigned char *tbs,
808 size_t tbslen)
809 {
810 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
811
812 if (edkey == NULL) {
813 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
814 return 0;
815 }
816
817 if (sig == NULL) {
818 *siglen = ED25519_SIGSIZE;
819 return 1;
820 }
821 if (*siglen < ED25519_SIGSIZE) {
822 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
823 return 0;
824 }
825
826 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
827 NULL) == 0)
828 return 0;
829 *siglen = ED25519_SIGSIZE;
830 return 1;
831 }
832
pkey_ecd_digestsign448(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)833 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
834 size_t *siglen, const unsigned char *tbs,
835 size_t tbslen)
836 {
837 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
838
839 if (edkey == NULL) {
840 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
841 return 0;
842 }
843
844 if (sig == NULL) {
845 *siglen = ED448_SIGSIZE;
846 return 1;
847 }
848 if (*siglen < ED448_SIGSIZE) {
849 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
850 return 0;
851 }
852
853 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
854 edkey->privkey, NULL, 0, edkey->propq) == 0)
855 return 0;
856 *siglen = ED448_SIGSIZE;
857 return 1;
858 }
859
pkey_ecd_digestverify25519(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)860 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
861 size_t siglen, const unsigned char *tbs,
862 size_t tbslen)
863 {
864 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
865
866 if (edkey == NULL) {
867 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
868 return 0;
869 }
870
871 if (siglen != ED25519_SIGSIZE)
872 return 0;
873
874 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
875 edkey->libctx, edkey->propq);
876 }
877
pkey_ecd_digestverify448(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)878 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
879 size_t siglen, const unsigned char *tbs,
880 size_t tbslen)
881 {
882 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
883
884 if (edkey == NULL) {
885 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
886 return 0;
887 }
888
889 if (siglen != ED448_SIGSIZE)
890 return 0;
891
892 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
893 NULL, 0, edkey->propq);
894 }
895
pkey_ecd_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)896 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
897 {
898 switch (type) {
899 case EVP_PKEY_CTRL_MD:
900 /* Only NULL allowed as digest */
901 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
902 return 1;
903 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
904 return 0;
905
906 case EVP_PKEY_CTRL_DIGESTINIT:
907 return 1;
908 }
909 return -2;
910 }
911
912 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
913 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
914 0, 0, 0, 0, 0, 0,
915 pkey_ecx_keygen,
916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
917 pkey_ecd_ctrl,
918 0,
919 pkey_ecd_digestsign25519,
920 pkey_ecd_digestverify25519
921 };
922
923 static const EVP_PKEY_METHOD ed448_pkey_meth = {
924 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
925 0, 0, 0, 0, 0, 0,
926 pkey_ecx_keygen,
927 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
928 pkey_ecd_ctrl,
929 0,
930 pkey_ecd_digestsign448,
931 pkey_ecd_digestverify448
932 };
933
934 #ifdef S390X_EC_ASM
935 # include "s390x_arch.h"
936
s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)937 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
938 {
939 static const unsigned char generator[] = {
940 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
943 };
944 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
945 ctx->propquery);
946 unsigned char *privkey = NULL, *pubkey;
947
948 if (key == NULL) {
949 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
950 goto err;
951 }
952
953 pubkey = key->pubkey;
954
955 privkey = ossl_ecx_key_allocate_privkey(key);
956 if (privkey == NULL) {
957 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
958 goto err;
959 }
960
961 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
962 goto err;
963
964 privkey[0] &= 248;
965 privkey[31] &= 127;
966 privkey[31] |= 64;
967
968 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
969 goto err;
970
971 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
972 return 1;
973 err:
974 ossl_ecx_key_free(key);
975 return 0;
976 }
977
s390x_pkey_ecx_keygen448(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)978 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
979 {
980 static const unsigned char generator[] = {
981 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
986 };
987 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
988 ctx->propquery);
989 unsigned char *privkey = NULL, *pubkey;
990
991 if (key == NULL) {
992 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
993 goto err;
994 }
995
996 pubkey = key->pubkey;
997
998 privkey = ossl_ecx_key_allocate_privkey(key);
999 if (privkey == NULL) {
1000 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1001 goto err;
1002 }
1003
1004 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1005 goto err;
1006
1007 privkey[0] &= 252;
1008 privkey[55] |= 128;
1009
1010 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1011 goto err;
1012
1013 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1014 return 1;
1015 err:
1016 ossl_ecx_key_free(key);
1017 return 0;
1018 }
1019
s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)1020 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1021 {
1022 static const unsigned char generator_x[] = {
1023 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1024 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1025 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1026 };
1027 static const unsigned char generator_y[] = {
1028 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1029 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1030 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1031 };
1032 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1033 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1034 ctx->propquery);
1035 unsigned char *privkey = NULL, *pubkey;
1036 unsigned int sz;
1037 EVP_MD *md = NULL;
1038 int rv;
1039
1040 if (key == NULL) {
1041 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1042 goto err;
1043 }
1044
1045 pubkey = key->pubkey;
1046
1047 privkey = ossl_ecx_key_allocate_privkey(key);
1048 if (privkey == NULL) {
1049 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1050 goto err;
1051 }
1052
1053 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1054 goto err;
1055
1056 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1057 if (md == NULL)
1058 goto err;
1059
1060 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1061 EVP_MD_free(md);
1062 if (!rv)
1063 goto err;
1064
1065 buff[0] &= 248;
1066 buff[31] &= 63;
1067 buff[31] |= 64;
1068
1069 if (s390x_ed25519_mul(x_dst, pubkey,
1070 generator_x, generator_y, buff) != 1)
1071 goto err;
1072
1073 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1074
1075 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1076 return 1;
1077 err:
1078 ossl_ecx_key_free(key);
1079 return 0;
1080 }
1081
s390x_pkey_ecd_keygen448(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)1082 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1083 {
1084 static const unsigned char generator_x[] = {
1085 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1086 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1087 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1088 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1089 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1090 };
1091 static const unsigned char generator_y[] = {
1092 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1093 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1094 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1095 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1096 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1097 };
1098 unsigned char x_dst[57], buff[114];
1099 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1100 ctx->propquery);
1101 unsigned char *privkey = NULL, *pubkey;
1102 EVP_MD_CTX *hashctx = NULL;
1103 EVP_MD *md = NULL;
1104 int rv;
1105
1106 if (key == NULL) {
1107 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1108 goto err;
1109 }
1110
1111 pubkey = key->pubkey;
1112
1113 privkey = ossl_ecx_key_allocate_privkey(key);
1114 if (privkey == NULL) {
1115 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1116 goto err;
1117 }
1118
1119 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1120 goto err;
1121
1122 hashctx = EVP_MD_CTX_new();
1123 if (hashctx == NULL)
1124 goto err;
1125
1126 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1127 if (md == NULL)
1128 goto err;
1129
1130 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1131 EVP_MD_free(md);
1132 if (rv != 1)
1133 goto err;
1134
1135 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1136 goto err;
1137 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1138 goto err;
1139
1140 buff[0] &= -4;
1141 buff[55] |= 0x80;
1142 buff[56] = 0;
1143
1144 if (s390x_ed448_mul(x_dst, pubkey,
1145 generator_x, generator_y, buff) != 1)
1146 goto err;
1147
1148 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1149
1150 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1151 EVP_MD_CTX_free(hashctx);
1152 return 1;
1153 err:
1154 ossl_ecx_key_free(key);
1155 EVP_MD_CTX_free(hashctx);
1156 return 0;
1157 }
1158
s390x_pkey_ecx_derive25519(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)1159 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1160 size_t *keylen)
1161 {
1162 const unsigned char *privkey, *pubkey;
1163
1164 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1165 return 0;
1166
1167 if (key != NULL)
1168 return s390x_x25519_mul(key, pubkey, privkey);
1169
1170 *keylen = X25519_KEYLEN;
1171 return 1;
1172 }
1173
s390x_pkey_ecx_derive448(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)1174 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1175 size_t *keylen)
1176 {
1177 const unsigned char *privkey, *pubkey;
1178
1179 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1180 return 0;
1181
1182 if (key != NULL)
1183 return s390x_x448_mul(key, pubkey, privkey);
1184
1185 *keylen = X448_KEYLEN;
1186 return 1;
1187 }
1188
s390x_pkey_ecd_digestsign25519(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1189 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1190 unsigned char *sig, size_t *siglen,
1191 const unsigned char *tbs,
1192 size_t tbslen)
1193 {
1194 union {
1195 struct {
1196 unsigned char sig[64];
1197 unsigned char priv[32];
1198 } ed25519;
1199 unsigned long long buff[512];
1200 } param;
1201 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1202 int rc;
1203
1204 if (edkey == NULL) {
1205 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1206 return 0;
1207 }
1208
1209 if (sig == NULL) {
1210 *siglen = ED25519_SIGSIZE;
1211 return 1;
1212 }
1213
1214 if (*siglen < ED25519_SIGSIZE) {
1215 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1216 return 0;
1217 }
1218
1219 memset(¶m, 0, sizeof(param));
1220 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1221
1222 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);
1223 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1224 if (rc != 0)
1225 return 0;
1226
1227 s390x_flip_endian32(sig, param.ed25519.sig);
1228 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1229
1230 *siglen = ED25519_SIGSIZE;
1231 return 1;
1232 }
1233
s390x_pkey_ecd_digestsign448(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1234 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1235 unsigned char *sig, size_t *siglen,
1236 const unsigned char *tbs,
1237 size_t tbslen)
1238 {
1239 union {
1240 struct {
1241 unsigned char sig[128];
1242 unsigned char priv[64];
1243 } ed448;
1244 unsigned long long buff[512];
1245 } param;
1246 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1247 int rc;
1248
1249 if (edkey == NULL) {
1250 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1251 return 0;
1252 }
1253
1254 if (sig == NULL) {
1255 *siglen = ED448_SIGSIZE;
1256 return 1;
1257 }
1258
1259 if (*siglen < ED448_SIGSIZE) {
1260 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1261 return 0;
1262 }
1263
1264 memset(¶m, 0, sizeof(param));
1265 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1266
1267 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);
1268 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1269 if (rc != 0)
1270 return 0;
1271
1272 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1273 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1274 memcpy(sig, param.ed448.sig, 57);
1275 memcpy(sig + 57, param.ed448.sig + 64, 57);
1276
1277 *siglen = ED448_SIGSIZE;
1278 return 1;
1279 }
1280
s390x_pkey_ecd_digestverify25519(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)1281 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1282 const unsigned char *sig,
1283 size_t siglen,
1284 const unsigned char *tbs,
1285 size_t tbslen)
1286 {
1287 union {
1288 struct {
1289 unsigned char sig[64];
1290 unsigned char pub[32];
1291 } ed25519;
1292 unsigned long long buff[512];
1293 } param;
1294 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1295
1296 if (edkey == NULL) {
1297 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1298 return 0;
1299 }
1300
1301 if (siglen != ED25519_SIGSIZE)
1302 return 0;
1303
1304 memset(¶m, 0, sizeof(param));
1305 s390x_flip_endian32(param.ed25519.sig, sig);
1306 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1307 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1308
1309 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1310 ¶m.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1311 }
1312
s390x_pkey_ecd_digestverify448(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)1313 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1314 const unsigned char *sig,
1315 size_t siglen,
1316 const unsigned char *tbs,
1317 size_t tbslen)
1318 {
1319 union {
1320 struct {
1321 unsigned char sig[128];
1322 unsigned char pub[64];
1323 } ed448;
1324 unsigned long long buff[512];
1325 } param;
1326 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1327
1328 if (edkey == NULL) {
1329 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1330 return 0;
1331 }
1332
1333 if (siglen != ED448_SIGSIZE)
1334 return 0;
1335
1336 memset(¶m, 0, sizeof(param));
1337 memcpy(param.ed448.sig, sig, 57);
1338 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1339 memcpy(param.ed448.sig + 64, sig + 57, 57);
1340 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1341 memcpy(param.ed448.pub, edkey->pubkey, 57);
1342 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1343
1344 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1345 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;
1346 }
1347
1348 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1349 EVP_PKEY_X25519,
1350 0, 0, 0, 0, 0, 0, 0,
1351 s390x_pkey_ecx_keygen25519,
1352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1353 s390x_pkey_ecx_derive25519,
1354 pkey_ecx_ctrl,
1355 0
1356 };
1357
1358 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1359 EVP_PKEY_X448,
1360 0, 0, 0, 0, 0, 0, 0,
1361 s390x_pkey_ecx_keygen448,
1362 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1363 s390x_pkey_ecx_derive448,
1364 pkey_ecx_ctrl,
1365 0
1366 };
1367 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1368 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1369 0, 0, 0, 0, 0, 0,
1370 s390x_pkey_ecd_keygen25519,
1371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1372 pkey_ecd_ctrl,
1373 0,
1374 s390x_pkey_ecd_digestsign25519,
1375 s390x_pkey_ecd_digestverify25519
1376 };
1377
1378 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1379 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1380 0, 0, 0, 0, 0, 0,
1381 s390x_pkey_ecd_keygen448,
1382 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1383 pkey_ecd_ctrl,
1384 0,
1385 s390x_pkey_ecd_digestsign448,
1386 s390x_pkey_ecd_digestverify448
1387 };
1388 #endif
1389
ossl_ecx25519_pkey_method(void)1390 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1391 {
1392 #ifdef S390X_EC_ASM
1393 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1394 return &ecx25519_s390x_pkey_meth;
1395 #endif
1396 return &ecx25519_pkey_meth;
1397 }
1398
ossl_ecx448_pkey_method(void)1399 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1400 {
1401 #ifdef S390X_EC_ASM
1402 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1403 return &ecx448_s390x_pkey_meth;
1404 #endif
1405 return &ecx448_pkey_meth;
1406 }
1407
ossl_ed25519_pkey_method(void)1408 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1409 {
1410 #ifdef S390X_EC_ASM
1411 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1412 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1413 && OPENSSL_s390xcap_P.kdsa[0]
1414 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1415 return &ed25519_s390x_pkey_meth;
1416 #endif
1417 return &ed25519_pkey_meth;
1418 }
1419
ossl_ed448_pkey_method(void)1420 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1421 {
1422 #ifdef S390X_EC_ASM
1423 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1424 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1425 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1426 return &ed448_s390x_pkey_meth;
1427 #endif
1428 return &ed448_pkey_meth;
1429 }
1430