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