xref: /openssl/crypto/ec/ecx_meth.c (revision da1c088f)
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) == 0)
184             return 0;
185     } else {
186         if (ecxkey == NULL) {
187             if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
188                 return 0;
189             return 1;
190         }
191         if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
192             return 0;
193     }
194     if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
195         return 0;
196 
197     if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
198                        indent + 4) == 0)
199         return 0;
200     return 1;
201 }
202 
ecx_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)203 static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
204                           ASN1_PCTX *ctx)
205 {
206     return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
207 }
208 
ecx_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)209 static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
210                          ASN1_PCTX *ctx)
211 {
212     return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
213 }
214 
ecx_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)215 static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
216 {
217     switch (op) {
218 
219     case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
220         ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
221                                        KEY_OP_PUBLIC, NULL, NULL);
222 
223         if (ecx != NULL) {
224             EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
225             return 1;
226         }
227         return 0;
228     }
229     case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
230         if (pkey->pkey.ecx != NULL) {
231             unsigned char **ppt = arg2;
232 
233             *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
234             if (*ppt != NULL)
235                 return KEYLEN(pkey);
236         }
237         return 0;
238 
239     default:
240         return -2;
241 
242     }
243 }
244 
ecd_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)245 static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
246 {
247     switch (op) {
248     case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
249         /* We currently only support Pure EdDSA which takes no digest */
250         *(int *)arg2 = NID_undef;
251         return 2;
252 
253     default:
254         return -2;
255 
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) == 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, 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                                0, 0, 0,
876                                NULL, 0,
877                                edkey->libctx, edkey->propq);
878 }
879 
pkey_ecd_digestverify448(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)880 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
881                                     size_t siglen, const unsigned char *tbs,
882                                     size_t tbslen)
883 {
884     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
885 
886     if (edkey == NULL) {
887         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
888         return 0;
889     }
890 
891     if (siglen != ED448_SIGSIZE)
892         return 0;
893 
894     return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
895                              NULL, 0, 0, edkey->propq);
896 }
897 
pkey_ecd_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)898 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
899 {
900     switch (type) {
901     case EVP_PKEY_CTRL_MD:
902         /* Only NULL allowed as digest */
903         if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
904             return 1;
905         ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
906         return 0;
907 
908     case EVP_PKEY_CTRL_DIGESTINIT:
909         return 1;
910     }
911     return -2;
912 }
913 
914 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
915     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
916     0, 0, 0, 0, 0, 0,
917     pkey_ecx_keygen,
918     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
919     pkey_ecd_ctrl,
920     0,
921     pkey_ecd_digestsign25519,
922     pkey_ecd_digestverify25519
923 };
924 
925 static const EVP_PKEY_METHOD ed448_pkey_meth = {
926     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
927     0, 0, 0, 0, 0, 0,
928     pkey_ecx_keygen,
929     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
930     pkey_ecd_ctrl,
931     0,
932     pkey_ecd_digestsign448,
933     pkey_ecd_digestverify448
934 };
935 
936 #ifdef S390X_EC_ASM
937 # include "s390x_arch.h"
938 
s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)939 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
940 {
941     static const unsigned char generator[] = {
942         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
944         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
945     };
946     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
947                                     ctx->propquery);
948     unsigned char *privkey = NULL, *pubkey;
949 
950     if (key == NULL) {
951         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
952         goto err;
953     }
954 
955     pubkey = key->pubkey;
956 
957     privkey = ossl_ecx_key_allocate_privkey(key);
958     if (privkey == NULL) {
959         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
960         goto err;
961     }
962 
963     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
964         goto err;
965 
966     privkey[0] &= 248;
967     privkey[31] &= 127;
968     privkey[31] |= 64;
969 
970     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
971         goto err;
972 
973     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
974     return 1;
975  err:
976     ossl_ecx_key_free(key);
977     return 0;
978 }
979 
s390x_pkey_ecx_keygen448(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)980 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
981 {
982     static const unsigned char generator[] = {
983         0x05, 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, 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
988     };
989     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
990                                     ctx->propquery);
991     unsigned char *privkey = NULL, *pubkey;
992 
993     if (key == NULL) {
994         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
995         goto err;
996     }
997 
998     pubkey = key->pubkey;
999 
1000     privkey = ossl_ecx_key_allocate_privkey(key);
1001     if (privkey == NULL) {
1002         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1003         goto err;
1004     }
1005 
1006     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1007         goto err;
1008 
1009     privkey[0] &= 252;
1010     privkey[55] |= 128;
1011 
1012     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1013         goto err;
1014 
1015     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1016     return 1;
1017  err:
1018     ossl_ecx_key_free(key);
1019     return 0;
1020 }
1021 
s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)1022 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1023 {
1024     static const unsigned char generator_x[] = {
1025         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1026         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1027         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1028     };
1029     static const unsigned char generator_y[] = {
1030         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1031         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1032         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1033     };
1034     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1035     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1036                                     ctx->propquery);
1037     unsigned char *privkey = NULL, *pubkey;
1038     unsigned int sz;
1039     EVP_MD *md = NULL;
1040     int rv;
1041 
1042     if (key == NULL) {
1043         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1044         goto err;
1045     }
1046 
1047     pubkey = key->pubkey;
1048 
1049     privkey = ossl_ecx_key_allocate_privkey(key);
1050     if (privkey == NULL) {
1051         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1052         goto err;
1053     }
1054 
1055     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1056         goto err;
1057 
1058     md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1059     if (md == NULL)
1060         goto err;
1061 
1062     rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1063     EVP_MD_free(md);
1064     if (!rv)
1065         goto err;
1066 
1067     buff[0] &= 248;
1068     buff[31] &= 63;
1069     buff[31] |= 64;
1070 
1071     if (s390x_ed25519_mul(x_dst, pubkey,
1072                           generator_x, generator_y, buff) != 1)
1073         goto err;
1074 
1075     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1076 
1077     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1078     return 1;
1079  err:
1080     ossl_ecx_key_free(key);
1081     return 0;
1082 }
1083 
s390x_pkey_ecd_keygen448(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)1084 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1085 {
1086     static const unsigned char generator_x[] = {
1087         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1088         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1089         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1090         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1091         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1092     };
1093     static const unsigned char generator_y[] = {
1094         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1095         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1096         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1097         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1098         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1099     };
1100     unsigned char x_dst[57], buff[114];
1101     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1102                                     ctx->propquery);
1103     unsigned char *privkey = NULL, *pubkey;
1104     EVP_MD_CTX *hashctx = NULL;
1105     EVP_MD *md = NULL;
1106     int rv;
1107 
1108     if (key == NULL) {
1109         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1110         goto err;
1111     }
1112 
1113     pubkey = key->pubkey;
1114 
1115     privkey = ossl_ecx_key_allocate_privkey(key);
1116     if (privkey == NULL) {
1117         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1118         goto err;
1119     }
1120 
1121     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1122         goto err;
1123 
1124     hashctx = EVP_MD_CTX_new();
1125     if (hashctx == NULL)
1126         goto err;
1127 
1128     md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1129     if (md == NULL)
1130         goto err;
1131 
1132     rv = EVP_DigestInit_ex(hashctx, md, NULL);
1133     EVP_MD_free(md);
1134     if (rv != 1)
1135         goto err;
1136 
1137     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1138         goto err;
1139     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1140         goto err;
1141 
1142     buff[0] &= -4;
1143     buff[55] |= 0x80;
1144     buff[56] = 0;
1145 
1146     if (s390x_ed448_mul(x_dst, pubkey,
1147                         generator_x, generator_y, buff) != 1)
1148         goto err;
1149 
1150     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1151 
1152     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1153     EVP_MD_CTX_free(hashctx);
1154     return 1;
1155  err:
1156     ossl_ecx_key_free(key);
1157     EVP_MD_CTX_free(hashctx);
1158     return 0;
1159 }
1160 
s390x_pkey_ecx_derive25519(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)1161 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1162                                       size_t *keylen)
1163 {
1164     const unsigned char *privkey, *pubkey;
1165 
1166     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1167         || (key != NULL
1168             && s390x_x25519_mul(key, privkey, pubkey) == 0))
1169         return 0;
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         || (key != NULL
1181             && s390x_x448_mul(key, pubkey, privkey) == 0))
1182         return 0;
1183     *keylen = X448_KEYLEN;
1184     return 1;
1185 }
1186 
s390x_pkey_ecd_digestsign25519(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1187 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1188                                           unsigned char *sig, size_t *siglen,
1189                                           const unsigned char *tbs,
1190                                           size_t tbslen)
1191 {
1192     union {
1193         struct {
1194             unsigned char sig[64];
1195             unsigned char priv[32];
1196         } ed25519;
1197         unsigned long long buff[512];
1198     } param;
1199     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1200     int rc;
1201 
1202     if (edkey == NULL) {
1203         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1204         return 0;
1205     }
1206 
1207     if (sig == NULL) {
1208         *siglen = ED25519_SIGSIZE;
1209         return 1;
1210     }
1211 
1212     if (*siglen < ED25519_SIGSIZE) {
1213         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1214         return 0;
1215     }
1216 
1217     memset(&param, 0, sizeof(param));
1218     memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1219 
1220     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1221     OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1222     if (rc != 0)
1223         return 0;
1224 
1225     s390x_flip_endian32(sig, param.ed25519.sig);
1226     s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1227 
1228     *siglen = ED25519_SIGSIZE;
1229     return 1;
1230 }
1231 
s390x_pkey_ecd_digestsign448(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1232 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1233                                         unsigned char *sig, size_t *siglen,
1234                                         const unsigned char *tbs,
1235                                         size_t tbslen)
1236 {
1237     union {
1238         struct {
1239             unsigned char sig[128];
1240             unsigned char priv[64];
1241         } ed448;
1242         unsigned long long buff[512];
1243     } param;
1244     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1245     int rc;
1246 
1247     if (edkey == NULL) {
1248         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1249         return 0;
1250     }
1251 
1252     if (sig == NULL) {
1253         *siglen = ED448_SIGSIZE;
1254         return 1;
1255     }
1256 
1257     if (*siglen < ED448_SIGSIZE) {
1258         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1259         return 0;
1260     }
1261 
1262     memset(&param, 0, sizeof(param));
1263     memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1264 
1265     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1266     OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1267     if (rc != 0)
1268         return 0;
1269 
1270     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1271     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1272     memcpy(sig, param.ed448.sig, 57);
1273     memcpy(sig + 57, param.ed448.sig + 64, 57);
1274 
1275     *siglen = ED448_SIGSIZE;
1276     return 1;
1277 }
1278 
s390x_pkey_ecd_digestverify25519(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)1279 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1280                                             const unsigned char *sig,
1281                                             size_t siglen,
1282                                             const unsigned char *tbs,
1283                                             size_t tbslen)
1284 {
1285     union {
1286         struct {
1287             unsigned char sig[64];
1288             unsigned char pub[32];
1289         } ed25519;
1290         unsigned long long buff[512];
1291     } param;
1292     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1293 
1294     if (edkey == NULL) {
1295         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1296         return 0;
1297     }
1298 
1299     if (siglen != ED25519_SIGSIZE)
1300         return 0;
1301 
1302     memset(&param, 0, sizeof(param));
1303     s390x_flip_endian32(param.ed25519.sig, sig);
1304     s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1305     s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1306 
1307     return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1308                       &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1309 }
1310 
s390x_pkey_ecd_digestverify448(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)1311 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1312                                           const unsigned char *sig,
1313                                           size_t siglen,
1314                                           const unsigned char *tbs,
1315                                           size_t tbslen)
1316 {
1317     union {
1318         struct {
1319             unsigned char sig[128];
1320             unsigned char pub[64];
1321         } ed448;
1322         unsigned long long buff[512];
1323     } param;
1324     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1325 
1326     if (edkey == NULL) {
1327         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1328         return 0;
1329     }
1330 
1331     if (siglen != ED448_SIGSIZE)
1332         return 0;
1333 
1334     memset(&param, 0, sizeof(param));
1335     memcpy(param.ed448.sig, sig, 57);
1336     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1337     memcpy(param.ed448.sig + 64, sig + 57, 57);
1338     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1339     memcpy(param.ed448.pub, edkey->pubkey, 57);
1340     s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1341 
1342     return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1343                       &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1344 }
1345 
1346 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1347     EVP_PKEY_X25519,
1348     0, 0, 0, 0, 0, 0, 0,
1349     s390x_pkey_ecx_keygen25519,
1350     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1351     s390x_pkey_ecx_derive25519,
1352     pkey_ecx_ctrl,
1353     0
1354 };
1355 
1356 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1357     EVP_PKEY_X448,
1358     0, 0, 0, 0, 0, 0, 0,
1359     s390x_pkey_ecx_keygen448,
1360     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1361     s390x_pkey_ecx_derive448,
1362     pkey_ecx_ctrl,
1363     0
1364 };
1365 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1366     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1367     0, 0, 0, 0, 0, 0,
1368     s390x_pkey_ecd_keygen25519,
1369     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1370     pkey_ecd_ctrl,
1371     0,
1372     s390x_pkey_ecd_digestsign25519,
1373     s390x_pkey_ecd_digestverify25519
1374 };
1375 
1376 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1377     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1378     0, 0, 0, 0, 0, 0,
1379     s390x_pkey_ecd_keygen448,
1380     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1381     pkey_ecd_ctrl,
1382     0,
1383     s390x_pkey_ecd_digestsign448,
1384     s390x_pkey_ecd_digestverify448
1385 };
1386 #endif
1387 
ossl_ecx25519_pkey_method(void)1388 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1389 {
1390 #ifdef S390X_EC_ASM
1391     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1392         return &ecx25519_s390x_pkey_meth;
1393 #endif
1394     return &ecx25519_pkey_meth;
1395 }
1396 
ossl_ecx448_pkey_method(void)1397 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1398 {
1399 #ifdef S390X_EC_ASM
1400     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1401         return &ecx448_s390x_pkey_meth;
1402 #endif
1403     return &ecx448_pkey_meth;
1404 }
1405 
ossl_ed25519_pkey_method(void)1406 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1407 {
1408 #ifdef S390X_EC_ASM
1409     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1410         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1411         && OPENSSL_s390xcap_P.kdsa[0]
1412             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1413         return &ed25519_s390x_pkey_meth;
1414 #endif
1415     return &ed25519_pkey_meth;
1416 }
1417 
ossl_ed448_pkey_method(void)1418 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1419 {
1420 #ifdef S390X_EC_ASM
1421     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1422         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1423         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1424         return &ed448_s390x_pkey_meth;
1425 #endif
1426     return &ed448_pkey_meth;
1427 }
1428