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