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