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