xref: /freebsd/crypto/openssl/providers/implementations/signature/eddsa_sig.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1b077aed3SPierre Pronchery /*
20d0c8621SEnji Cooper  * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
10b077aed3SPierre Pronchery #include <openssl/crypto.h>
11b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
12b077aed3SPierre Pronchery #include <openssl/core_names.h>
13b077aed3SPierre Pronchery #include <openssl/err.h>
14b077aed3SPierre Pronchery #include <openssl/params.h>
15b077aed3SPierre Pronchery #include <openssl/evp.h>
16b077aed3SPierre Pronchery #include <openssl/proverr.h>
17b077aed3SPierre Pronchery #include "internal/nelem.h"
18b077aed3SPierre Pronchery #include "internal/sizes.h"
19b077aed3SPierre Pronchery #include "prov/providercommon.h"
20b077aed3SPierre Pronchery #include "prov/implementations.h"
21*e7be843bSPierre Pronchery #include "prov/securitycheck.h"
22b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
23b077aed3SPierre Pronchery #include "prov/der_ecx.h"
24b077aed3SPierre Pronchery #include "crypto/ecx.h"
25b077aed3SPierre Pronchery 
26b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
27b077aed3SPierre Pronchery # include "s390x_arch.h"
28b077aed3SPierre Pronchery 
29b077aed3SPierre Pronchery # define S390X_CAN_SIGN(edtype)                                                \
30b077aed3SPierre Pronchery ((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype))    \
31b077aed3SPierre Pronchery && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype))      \
32b077aed3SPierre Pronchery && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
33b077aed3SPierre Pronchery 
34b077aed3SPierre Pronchery static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
35b077aed3SPierre Pronchery                                     const unsigned char *tbs, size_t tbslen);
36b077aed3SPierre Pronchery static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
37b077aed3SPierre Pronchery                                   const unsigned char *tbs, size_t tbslen);
38b077aed3SPierre Pronchery static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
39b077aed3SPierre Pronchery                                       const unsigned char *sig,
40b077aed3SPierre Pronchery                                       const unsigned char *tbs, size_t tbslen);
41b077aed3SPierre Pronchery static int s390x_ed448_digestverify(const ECX_KEY *edkey,
42b077aed3SPierre Pronchery                                     const unsigned char *sig,
43b077aed3SPierre Pronchery                                     const unsigned char *tbs, size_t tbslen);
44b077aed3SPierre Pronchery 
45b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
46b077aed3SPierre Pronchery 
47*e7be843bSPierre Pronchery enum ID_EdDSA_INSTANCE {
48*e7be843bSPierre Pronchery     ID_NOT_SET = 0,
49*e7be843bSPierre Pronchery     ID_Ed25519,
50*e7be843bSPierre Pronchery     ID_Ed25519ctx,
51*e7be843bSPierre Pronchery     ID_Ed25519ph,
52*e7be843bSPierre Pronchery     ID_Ed448,
53*e7be843bSPierre Pronchery     ID_Ed448ph
54*e7be843bSPierre Pronchery };
55*e7be843bSPierre Pronchery 
56*e7be843bSPierre Pronchery #define SN_Ed25519    "Ed25519"
57*e7be843bSPierre Pronchery #define SN_Ed25519ph  "Ed25519ph"
58*e7be843bSPierre Pronchery #define SN_Ed25519ctx "Ed25519ctx"
59*e7be843bSPierre Pronchery #define SN_Ed448      "Ed448"
60*e7be843bSPierre Pronchery #define SN_Ed448ph    "Ed448ph"
61*e7be843bSPierre Pronchery 
62*e7be843bSPierre Pronchery #define EDDSA_MAX_CONTEXT_STRING_LEN 255
63*e7be843bSPierre Pronchery #define EDDSA_PREHASH_OUTPUT_LEN 64
64*e7be843bSPierre Pronchery 
65b077aed3SPierre Pronchery static OSSL_FUNC_signature_newctx_fn eddsa_newctx;
66*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_init_fn ed25519_signverify_message_init;
67*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_init_fn ed25519ph_signverify_message_init;
68*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_init_fn ed25519ctx_signverify_message_init;
69*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_init_fn ed448_signverify_message_init;
70*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_init_fn ed448ph_signverify_message_init;
71*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_fn ed25519_sign;
72*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_fn ed448_sign;
73*e7be843bSPierre Pronchery static OSSL_FUNC_signature_verify_fn ed25519_verify;
74*e7be843bSPierre Pronchery static OSSL_FUNC_signature_verify_fn ed448_verify;
75*e7be843bSPierre Pronchery static OSSL_FUNC_signature_digest_sign_init_fn ed25519_digest_signverify_init;
76*e7be843bSPierre Pronchery static OSSL_FUNC_signature_digest_sign_init_fn ed448_digest_signverify_init;
77b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
78b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
79b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
80b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
81b077aed3SPierre Pronchery static OSSL_FUNC_signature_freectx_fn eddsa_freectx;
82b077aed3SPierre Pronchery static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
83*e7be843bSPierre Pronchery static OSSL_FUNC_signature_query_key_types_fn ed25519_sigalg_query_key_types;
84*e7be843bSPierre Pronchery static OSSL_FUNC_signature_query_key_types_fn ed448_sigalg_query_key_types;
85b077aed3SPierre Pronchery static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
86b077aed3SPierre Pronchery static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
87*e7be843bSPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn eddsa_set_ctx_params;
88*e7be843bSPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn eddsa_settable_ctx_params;
89*e7be843bSPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn eddsa_settable_variant_ctx_params;
90*e7be843bSPierre Pronchery 
91*e7be843bSPierre Pronchery /* there are five EdDSA instances:
92*e7be843bSPierre Pronchery 
93*e7be843bSPierre Pronchery          Ed25519
94*e7be843bSPierre Pronchery          Ed25519ph
95*e7be843bSPierre Pronchery          Ed25519ctx
96*e7be843bSPierre Pronchery          Ed448
97*e7be843bSPierre Pronchery          Ed448ph
98*e7be843bSPierre Pronchery 
99*e7be843bSPierre Pronchery    Quoting from RFC 8032, Section 5.1:
100*e7be843bSPierre Pronchery 
101*e7be843bSPierre Pronchery      For Ed25519, dom2(f,c) is the empty string.  The phflag value is
102*e7be843bSPierre Pronchery      irrelevant.  The context (if present at all) MUST be empty.  This
103*e7be843bSPierre Pronchery      causes the scheme to be one and the same with the Ed25519 scheme
104*e7be843bSPierre Pronchery      published earlier.
105*e7be843bSPierre Pronchery 
106*e7be843bSPierre Pronchery      For Ed25519ctx, phflag=0.  The context input SHOULD NOT be empty.
107*e7be843bSPierre Pronchery 
108*e7be843bSPierre Pronchery      For Ed25519ph, phflag=1 and PH is SHA512 instead.  That is, the input
109*e7be843bSPierre Pronchery      is hashed using SHA-512 before signing with Ed25519.
110*e7be843bSPierre Pronchery 
111*e7be843bSPierre Pronchery    Quoting from RFC 8032, Section 5.2:
112*e7be843bSPierre Pronchery 
113*e7be843bSPierre Pronchery      Ed448ph is the same but with PH being SHAKE256(x, 64) and phflag
114*e7be843bSPierre Pronchery      being 1, i.e., the input is hashed before signing with Ed448 with a
115*e7be843bSPierre Pronchery      hash constant modified.
116*e7be843bSPierre Pronchery 
117*e7be843bSPierre Pronchery      Value of context is set by signer and verifier (maximum of 255
118*e7be843bSPierre Pronchery      octets; the default is empty string) and has to match octet by octet
119*e7be843bSPierre Pronchery      for verification to be successful.
120*e7be843bSPierre Pronchery 
121*e7be843bSPierre Pronchery    Quoting from RFC 8032, Section 2:
122*e7be843bSPierre Pronchery 
123*e7be843bSPierre Pronchery      dom2(x, y)     The blank octet string when signing or verifying
124*e7be843bSPierre Pronchery                     Ed25519.  Otherwise, the octet string: "SigEd25519 no
125*e7be843bSPierre Pronchery                     Ed25519 collisions" || octet(x) || octet(OLEN(y)) ||
126*e7be843bSPierre Pronchery                     y, where x is in range 0-255 and y is an octet string
127*e7be843bSPierre Pronchery                     of at most 255 octets.  "SigEd25519 no Ed25519
128*e7be843bSPierre Pronchery                     collisions" is in ASCII (32 octets).
129*e7be843bSPierre Pronchery 
130*e7be843bSPierre Pronchery      dom4(x, y)     The octet string "SigEd448" || octet(x) ||
131*e7be843bSPierre Pronchery                     octet(OLEN(y)) || y, where x is in range 0-255 and y
132*e7be843bSPierre Pronchery                     is an octet string of at most 255 octets.  "SigEd448"
133*e7be843bSPierre Pronchery                     is in ASCII (8 octets).
134*e7be843bSPierre Pronchery 
135*e7be843bSPierre Pronchery    Note above that x is the pre-hash flag, and y is the context string.
136*e7be843bSPierre Pronchery */
137b077aed3SPierre Pronchery 
138b077aed3SPierre Pronchery typedef struct {
139b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx;
140b077aed3SPierre Pronchery     ECX_KEY *key;
141b077aed3SPierre Pronchery 
142b077aed3SPierre Pronchery     /* The Algorithm Identifier of the signature algorithm */
143b077aed3SPierre Pronchery     unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
144b077aed3SPierre Pronchery     size_t  aid_len;
145*e7be843bSPierre Pronchery 
146*e7be843bSPierre Pronchery     /* id indicating the EdDSA instance */
147*e7be843bSPierre Pronchery     int instance_id;
148*e7be843bSPierre Pronchery     /* indicates that instance_id and associated flags are preset / hardcoded */
149*e7be843bSPierre Pronchery     unsigned int instance_id_preset_flag : 1;
150*e7be843bSPierre Pronchery     /* for ph instances, this indicates whether the caller is expected to prehash */
151*e7be843bSPierre Pronchery     unsigned int prehash_by_caller_flag : 1;
152*e7be843bSPierre Pronchery 
153*e7be843bSPierre Pronchery     unsigned int dom2_flag : 1;
154*e7be843bSPierre Pronchery     unsigned int prehash_flag : 1;
155*e7be843bSPierre Pronchery 
156*e7be843bSPierre Pronchery     /* indicates that a non-empty context string is required, as in Ed25519ctx */
157*e7be843bSPierre Pronchery     unsigned int context_string_flag : 1;
158*e7be843bSPierre Pronchery 
159*e7be843bSPierre Pronchery     unsigned char context_string[EDDSA_MAX_CONTEXT_STRING_LEN];
160*e7be843bSPierre Pronchery     size_t context_string_len;
161*e7be843bSPierre Pronchery 
162b077aed3SPierre Pronchery } PROV_EDDSA_CTX;
163b077aed3SPierre Pronchery 
eddsa_newctx(void * provctx,const char * propq_unused)164b077aed3SPierre Pronchery static void *eddsa_newctx(void *provctx, const char *propq_unused)
165b077aed3SPierre Pronchery {
166b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx;
167b077aed3SPierre Pronchery 
168b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
169b077aed3SPierre Pronchery         return NULL;
170b077aed3SPierre Pronchery 
171b077aed3SPierre Pronchery     peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
172*e7be843bSPierre Pronchery     if (peddsactx == NULL)
173b077aed3SPierre Pronchery         return NULL;
174b077aed3SPierre Pronchery 
175b077aed3SPierre Pronchery     peddsactx->libctx = PROV_LIBCTX_OF(provctx);
176b077aed3SPierre Pronchery 
177b077aed3SPierre Pronchery     return peddsactx;
178b077aed3SPierre Pronchery }
179b077aed3SPierre Pronchery 
eddsa_setup_instance(void * vpeddsactx,int instance_id,unsigned int instance_id_preset,unsigned int prehash_by_caller)180*e7be843bSPierre Pronchery static int eddsa_setup_instance(void *vpeddsactx, int instance_id,
181*e7be843bSPierre Pronchery                                 unsigned int instance_id_preset,
182*e7be843bSPierre Pronchery                                 unsigned int prehash_by_caller)
183*e7be843bSPierre Pronchery {
184*e7be843bSPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
185*e7be843bSPierre Pronchery 
186*e7be843bSPierre Pronchery     switch (instance_id) {
187*e7be843bSPierre Pronchery     case ID_Ed25519:
188*e7be843bSPierre Pronchery         if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)
189*e7be843bSPierre Pronchery             return 0;
190*e7be843bSPierre Pronchery         peddsactx->dom2_flag = 0;
191*e7be843bSPierre Pronchery         peddsactx->prehash_flag = 0;
192*e7be843bSPierre Pronchery         peddsactx->context_string_flag = 0;
193*e7be843bSPierre Pronchery         break;
194*e7be843bSPierre Pronchery     case ID_Ed25519ctx:
195*e7be843bSPierre Pronchery         if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)
196*e7be843bSPierre Pronchery             return 0;
197*e7be843bSPierre Pronchery         peddsactx->dom2_flag = 1;
198*e7be843bSPierre Pronchery         peddsactx->prehash_flag = 0;
199*e7be843bSPierre Pronchery         peddsactx->context_string_flag = 1;
200*e7be843bSPierre Pronchery         break;
201*e7be843bSPierre Pronchery     case ID_Ed25519ph:
202*e7be843bSPierre Pronchery         if (peddsactx->key->type != ECX_KEY_TYPE_ED25519)
203*e7be843bSPierre Pronchery             return 0;
204*e7be843bSPierre Pronchery         peddsactx->dom2_flag = 1;
205*e7be843bSPierre Pronchery         peddsactx->prehash_flag = 1;
206*e7be843bSPierre Pronchery         peddsactx->context_string_flag = 0;
207*e7be843bSPierre Pronchery         break;
208*e7be843bSPierre Pronchery     case ID_Ed448:
209*e7be843bSPierre Pronchery         if (peddsactx->key->type != ECX_KEY_TYPE_ED448)
210*e7be843bSPierre Pronchery             return 0;
211*e7be843bSPierre Pronchery         peddsactx->prehash_flag = 0;
212*e7be843bSPierre Pronchery         peddsactx->context_string_flag = 0;
213*e7be843bSPierre Pronchery         break;
214*e7be843bSPierre Pronchery     case ID_Ed448ph:
215*e7be843bSPierre Pronchery         if (peddsactx->key->type != ECX_KEY_TYPE_ED448)
216*e7be843bSPierre Pronchery             return 0;
217*e7be843bSPierre Pronchery         peddsactx->prehash_flag = 1;
218*e7be843bSPierre Pronchery         peddsactx->context_string_flag = 0;
219*e7be843bSPierre Pronchery         break;
220*e7be843bSPierre Pronchery     default:
221*e7be843bSPierre Pronchery         /* we did not recognize the instance */
222*e7be843bSPierre Pronchery         return 0;
223*e7be843bSPierre Pronchery     }
224*e7be843bSPierre Pronchery     peddsactx->instance_id = instance_id;
225*e7be843bSPierre Pronchery     peddsactx->instance_id_preset_flag = instance_id_preset;
226*e7be843bSPierre Pronchery     peddsactx->prehash_by_caller_flag = prehash_by_caller;
227*e7be843bSPierre Pronchery     return 1;
228*e7be843bSPierre Pronchery }
229*e7be843bSPierre Pronchery 
eddsa_signverify_init(void * vpeddsactx,void * vedkey)230*e7be843bSPierre Pronchery static int eddsa_signverify_init(void *vpeddsactx, void *vedkey)
231b077aed3SPierre Pronchery {
232b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
233b077aed3SPierre Pronchery     ECX_KEY *edkey = (ECX_KEY *)vedkey;
234b077aed3SPierre Pronchery     WPACKET pkt;
235b077aed3SPierre Pronchery     int ret;
236*e7be843bSPierre Pronchery     unsigned char *aid = NULL;
237b077aed3SPierre Pronchery 
238b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
239b077aed3SPierre Pronchery         return 0;
240b077aed3SPierre Pronchery 
241b077aed3SPierre Pronchery     if (edkey == NULL) {
242b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
243b077aed3SPierre Pronchery         return 0;
244b077aed3SPierre Pronchery     }
245b077aed3SPierre Pronchery 
246b077aed3SPierre Pronchery     if (!ossl_ecx_key_up_ref(edkey)) {
247b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
248b077aed3SPierre Pronchery         return 0;
249b077aed3SPierre Pronchery     }
250b077aed3SPierre Pronchery 
251*e7be843bSPierre Pronchery     peddsactx->instance_id_preset_flag = 0;
252*e7be843bSPierre Pronchery     peddsactx->dom2_flag = 0;
253*e7be843bSPierre Pronchery     peddsactx->prehash_flag = 0;
254*e7be843bSPierre Pronchery     peddsactx->context_string_flag = 0;
255*e7be843bSPierre Pronchery     peddsactx->context_string_len = 0;
256*e7be843bSPierre Pronchery 
257*e7be843bSPierre Pronchery     peddsactx->key = edkey;
258*e7be843bSPierre Pronchery 
259b077aed3SPierre Pronchery     /*
260b077aed3SPierre Pronchery      * We do not care about DER writing errors.
261b077aed3SPierre Pronchery      * All it really means is that for some reason, there's no
262b077aed3SPierre Pronchery      * AlgorithmIdentifier to be had, but the operation itself is
263b077aed3SPierre Pronchery      * still valid, just as long as it's not used to construct
264b077aed3SPierre Pronchery      * anything that needs an AlgorithmIdentifier.
265b077aed3SPierre Pronchery      */
266b077aed3SPierre Pronchery     peddsactx->aid_len = 0;
267b077aed3SPierre Pronchery     ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
268b077aed3SPierre Pronchery     switch (edkey->type) {
269b077aed3SPierre Pronchery     case ECX_KEY_TYPE_ED25519:
270b077aed3SPierre Pronchery         ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
271b077aed3SPierre Pronchery         break;
272b077aed3SPierre Pronchery     case ECX_KEY_TYPE_ED448:
273b077aed3SPierre Pronchery         ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
274b077aed3SPierre Pronchery         break;
275b077aed3SPierre Pronchery     default:
276b077aed3SPierre Pronchery         /* Should never happen */
277b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
278b077aed3SPierre Pronchery         ossl_ecx_key_free(edkey);
279*e7be843bSPierre Pronchery         peddsactx->key = NULL;
2800d0c8621SEnji Cooper         WPACKET_cleanup(&pkt);
281b077aed3SPierre Pronchery         return 0;
282b077aed3SPierre Pronchery     }
283b077aed3SPierre Pronchery     if (ret && WPACKET_finish(&pkt)) {
284b077aed3SPierre Pronchery         WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
285*e7be843bSPierre Pronchery         aid = WPACKET_get_curr(&pkt);
286b077aed3SPierre Pronchery     }
287b077aed3SPierre Pronchery     WPACKET_cleanup(&pkt);
288*e7be843bSPierre Pronchery     if (aid != NULL && peddsactx->aid_len != 0)
289*e7be843bSPierre Pronchery         memmove(peddsactx->aid_buf, aid, peddsactx->aid_len);
290b077aed3SPierre Pronchery 
291b077aed3SPierre Pronchery     return 1;
292b077aed3SPierre Pronchery }
293b077aed3SPierre Pronchery 
ed25519_signverify_message_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])294*e7be843bSPierre Pronchery static int ed25519_signverify_message_init(void *vpeddsactx, void *vedkey,
295*e7be843bSPierre Pronchery                                              const OSSL_PARAM params[])
296*e7be843bSPierre Pronchery {
297*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
298*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed25519, 1, 0)
299*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
300*e7be843bSPierre Pronchery }
301*e7be843bSPierre Pronchery 
ed25519ph_signverify_message_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])302*e7be843bSPierre Pronchery static int ed25519ph_signverify_message_init(void *vpeddsactx, void *vedkey,
303*e7be843bSPierre Pronchery                                              const OSSL_PARAM params[])
304*e7be843bSPierre Pronchery {
305*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
306*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed25519ph, 1, 0)
307*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
308*e7be843bSPierre Pronchery }
309*e7be843bSPierre Pronchery 
ed25519ph_signverify_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])310*e7be843bSPierre Pronchery static int ed25519ph_signverify_init(void *vpeddsactx, void *vedkey,
311*e7be843bSPierre Pronchery                                      const OSSL_PARAM params[])
312*e7be843bSPierre Pronchery {
313*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
314*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed25519ph, 1, 1)
315*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
316*e7be843bSPierre Pronchery }
317*e7be843bSPierre Pronchery 
318*e7be843bSPierre Pronchery /*
319*e7be843bSPierre Pronchery  * This supports using ED25519 with EVP_PKEY_{sign,verify}_init_ex() and
320*e7be843bSPierre Pronchery  * EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller
321*e7be843bSPierre Pronchery  * explicitly sets the Ed25519ph instance (this is verified by ed25519_sign()
322*e7be843bSPierre Pronchery  * and ed25519_verify())
323*e7be843bSPierre Pronchery  */
ed25519_signverify_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])324*e7be843bSPierre Pronchery static int ed25519_signverify_init(void *vpeddsactx, void *vedkey,
325*e7be843bSPierre Pronchery                                    const OSSL_PARAM params[])
326*e7be843bSPierre Pronchery {
327*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
328*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 1)
329*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
330*e7be843bSPierre Pronchery }
331*e7be843bSPierre Pronchery 
ed25519ctx_signverify_message_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])332*e7be843bSPierre Pronchery static int ed25519ctx_signverify_message_init(void *vpeddsactx, void *vedkey,
333*e7be843bSPierre Pronchery                                              const OSSL_PARAM params[])
334*e7be843bSPierre Pronchery {
335*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
336*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed25519ctx, 1, 0)
337*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
338*e7be843bSPierre Pronchery }
339*e7be843bSPierre Pronchery 
ed448_signverify_message_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])340*e7be843bSPierre Pronchery static int ed448_signverify_message_init(void *vpeddsactx, void *vedkey,
341*e7be843bSPierre Pronchery                                          const OSSL_PARAM params[])
342*e7be843bSPierre Pronchery {
343*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
344*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed448, 1, 0)
345*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
346*e7be843bSPierre Pronchery }
347*e7be843bSPierre Pronchery 
ed448ph_signverify_message_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])348*e7be843bSPierre Pronchery static int ed448ph_signverify_message_init(void *vpeddsactx, void *vedkey,
349*e7be843bSPierre Pronchery                                            const OSSL_PARAM params[])
350*e7be843bSPierre Pronchery {
351*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
352*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed448ph, 1, 0)
353*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
354*e7be843bSPierre Pronchery }
355*e7be843bSPierre Pronchery 
ed448ph_signverify_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])356*e7be843bSPierre Pronchery static int ed448ph_signverify_init(void *vpeddsactx, void *vedkey,
357*e7be843bSPierre Pronchery                                    const OSSL_PARAM params[])
358*e7be843bSPierre Pronchery {
359*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
360*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed448ph, 1, 1)
361*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
362*e7be843bSPierre Pronchery }
363*e7be843bSPierre Pronchery 
364*e7be843bSPierre Pronchery /*
365*e7be843bSPierre Pronchery  * This supports using ED448 with EVP_PKEY_{sign,verify}_init_ex() and
366*e7be843bSPierre Pronchery  * EVP_PKEY_{sign,verify}_init_ex2(), under the condition that the caller
367*e7be843bSPierre Pronchery  * explicitly sets the Ed448ph instance (this is verified by ed448_sign()
368*e7be843bSPierre Pronchery  * and ed448_verify())
369*e7be843bSPierre Pronchery  */
ed448_signverify_init(void * vpeddsactx,void * vedkey,const OSSL_PARAM params[])370*e7be843bSPierre Pronchery static int ed448_signverify_init(void *vpeddsactx, void *vedkey,
371*e7be843bSPierre Pronchery                                    const OSSL_PARAM params[])
372*e7be843bSPierre Pronchery {
373*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
374*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 1)
375*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
376*e7be843bSPierre Pronchery }
377*e7be843bSPierre Pronchery 
378*e7be843bSPierre Pronchery /*
379*e7be843bSPierre Pronchery  * This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly
380*e7be843bSPierre Pronchery  * for OSSL_FUNC_SIGNATURE_DIGEST_SIGN
381*e7be843bSPierre Pronchery  */
ed25519_sign(void * vpeddsactx,unsigned char * sigret,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)382*e7be843bSPierre Pronchery static int ed25519_sign(void *vpeddsactx,
383*e7be843bSPierre Pronchery                         unsigned char *sigret, size_t *siglen, size_t sigsize,
384b077aed3SPierre Pronchery                         const unsigned char *tbs, size_t tbslen)
385b077aed3SPierre Pronchery {
386b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
387b077aed3SPierre Pronchery     const ECX_KEY *edkey = peddsactx->key;
388*e7be843bSPierre Pronchery     uint8_t md[EVP_MAX_MD_SIZE];
389*e7be843bSPierre Pronchery     size_t mdlen;
390b077aed3SPierre Pronchery 
391b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
392b077aed3SPierre Pronchery         return 0;
393b077aed3SPierre Pronchery 
394b077aed3SPierre Pronchery     if (sigret == NULL) {
395b077aed3SPierre Pronchery         *siglen = ED25519_SIGSIZE;
396b077aed3SPierre Pronchery         return 1;
397b077aed3SPierre Pronchery     }
398b077aed3SPierre Pronchery     if (sigsize < ED25519_SIGSIZE) {
399b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
400b077aed3SPierre Pronchery         return 0;
401b077aed3SPierre Pronchery     }
402b077aed3SPierre Pronchery     if (edkey->privkey == NULL) {
403b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
404b077aed3SPierre Pronchery         return 0;
405b077aed3SPierre Pronchery     }
406b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
407*e7be843bSPierre Pronchery     /*
408*e7be843bSPierre Pronchery      * s390x_ed25519_digestsign() does not yet support dom2 or context-strings.
409*e7be843bSPierre Pronchery      * fall back to non-accelerated sign if those options are set, or pre-hasing
410*e7be843bSPierre Pronchery      * is provided.
411*e7be843bSPierre Pronchery      */
412*e7be843bSPierre Pronchery     if (S390X_CAN_SIGN(ED25519)
413*e7be843bSPierre Pronchery             && !peddsactx->dom2_flag
414*e7be843bSPierre Pronchery             && !peddsactx->context_string_flag
415*e7be843bSPierre Pronchery             && peddsactx->context_string_len == 0
416*e7be843bSPierre Pronchery             && !peddsactx->prehash_flag
417*e7be843bSPierre Pronchery             && !peddsactx->prehash_by_caller_flag) {
418b077aed3SPierre Pronchery         if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
419b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
420b077aed3SPierre Pronchery             return 0;
421b077aed3SPierre Pronchery         }
422b077aed3SPierre Pronchery         *siglen = ED25519_SIGSIZE;
423b077aed3SPierre Pronchery         return 1;
424b077aed3SPierre Pronchery     }
425b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
426*e7be843bSPierre Pronchery 
427*e7be843bSPierre Pronchery     if (peddsactx->prehash_flag) {
428*e7be843bSPierre Pronchery         if (!peddsactx->prehash_by_caller_flag) {
429*e7be843bSPierre Pronchery             if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL,
430*e7be843bSPierre Pronchery                               tbs, tbslen, md, &mdlen)
431*e7be843bSPierre Pronchery                 || mdlen != EDDSA_PREHASH_OUTPUT_LEN) {
432*e7be843bSPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH);
433*e7be843bSPierre Pronchery                 return 0;
434*e7be843bSPierre Pronchery             }
435*e7be843bSPierre Pronchery             tbs = md;
436*e7be843bSPierre Pronchery             tbslen = mdlen;
437*e7be843bSPierre Pronchery         } else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {
438*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
439*e7be843bSPierre Pronchery             return 0;
440*e7be843bSPierre Pronchery         }
441*e7be843bSPierre Pronchery     } else if (peddsactx->prehash_by_caller_flag) {
442*e7be843bSPierre Pronchery         /* The caller is supposed to set up a ph instance! */
443*e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV,
444*e7be843bSPierre Pronchery                   PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);
445*e7be843bSPierre Pronchery         return 0;
446*e7be843bSPierre Pronchery     }
447*e7be843bSPierre Pronchery 
448b077aed3SPierre Pronchery     if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
449*e7be843bSPierre Pronchery             peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,
450*e7be843bSPierre Pronchery             peddsactx->context_string, peddsactx->context_string_len,
451b077aed3SPierre Pronchery             peddsactx->libctx, NULL) == 0) {
452b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
453b077aed3SPierre Pronchery         return 0;
454b077aed3SPierre Pronchery     }
455b077aed3SPierre Pronchery     *siglen = ED25519_SIGSIZE;
456b077aed3SPierre Pronchery     return 1;
457b077aed3SPierre Pronchery }
458b077aed3SPierre Pronchery 
459*e7be843bSPierre Pronchery /* EVP_Q_digest() does not allow variable output length for XOFs,
460*e7be843bSPierre Pronchery    so we use this function */
ed448_shake256(OSSL_LIB_CTX * libctx,const char * propq,const uint8_t * in,size_t inlen,uint8_t * out,size_t outlen)461*e7be843bSPierre Pronchery static int ed448_shake256(OSSL_LIB_CTX *libctx,
462*e7be843bSPierre Pronchery                           const char *propq,
463*e7be843bSPierre Pronchery                           const uint8_t *in, size_t inlen,
464*e7be843bSPierre Pronchery                           uint8_t *out, size_t outlen)
465*e7be843bSPierre Pronchery {
466*e7be843bSPierre Pronchery     int ret = 0;
467*e7be843bSPierre Pronchery     EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();
468*e7be843bSPierre Pronchery     EVP_MD *shake256 = EVP_MD_fetch(libctx, SN_shake256, propq);
469*e7be843bSPierre Pronchery 
470*e7be843bSPierre Pronchery     if (hash_ctx == NULL || shake256 == NULL)
471*e7be843bSPierre Pronchery         goto err;
472*e7be843bSPierre Pronchery 
473*e7be843bSPierre Pronchery     if (!EVP_DigestInit_ex(hash_ctx, shake256, NULL)
474*e7be843bSPierre Pronchery             || !EVP_DigestUpdate(hash_ctx, in, inlen)
475*e7be843bSPierre Pronchery             || !EVP_DigestFinalXOF(hash_ctx, out, outlen))
476*e7be843bSPierre Pronchery         goto err;
477*e7be843bSPierre Pronchery 
478*e7be843bSPierre Pronchery     ret = 1;
479*e7be843bSPierre Pronchery 
480*e7be843bSPierre Pronchery  err:
481*e7be843bSPierre Pronchery     EVP_MD_CTX_free(hash_ctx);
482*e7be843bSPierre Pronchery     EVP_MD_free(shake256);
483*e7be843bSPierre Pronchery     return ret;
484*e7be843bSPierre Pronchery }
485*e7be843bSPierre Pronchery 
486*e7be843bSPierre Pronchery /*
487*e7be843bSPierre Pronchery  * This is used directly for OSSL_FUNC_SIGNATURE_SIGN and indirectly
488*e7be843bSPierre Pronchery  * for OSSL_FUNC_SIGNATURE_DIGEST_SIGN
489*e7be843bSPierre Pronchery  */
ed448_sign(void * vpeddsactx,unsigned char * sigret,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)490*e7be843bSPierre Pronchery static int ed448_sign(void *vpeddsactx,
491*e7be843bSPierre Pronchery                       unsigned char *sigret, size_t *siglen, size_t sigsize,
492b077aed3SPierre Pronchery                       const unsigned char *tbs, size_t tbslen)
493b077aed3SPierre Pronchery {
494b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
495b077aed3SPierre Pronchery     const ECX_KEY *edkey = peddsactx->key;
496*e7be843bSPierre Pronchery     uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];
497*e7be843bSPierre Pronchery     size_t mdlen = sizeof(md);
498b077aed3SPierre Pronchery 
499b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
500b077aed3SPierre Pronchery         return 0;
501b077aed3SPierre Pronchery 
502b077aed3SPierre Pronchery     if (sigret == NULL) {
503b077aed3SPierre Pronchery         *siglen = ED448_SIGSIZE;
504b077aed3SPierre Pronchery         return 1;
505b077aed3SPierre Pronchery     }
506b077aed3SPierre Pronchery     if (sigsize < ED448_SIGSIZE) {
507b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
508b077aed3SPierre Pronchery         return 0;
509b077aed3SPierre Pronchery     }
510b077aed3SPierre Pronchery     if (edkey->privkey == NULL) {
511b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
512b077aed3SPierre Pronchery         return 0;
513b077aed3SPierre Pronchery     }
514b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
515*e7be843bSPierre Pronchery     /*
516*e7be843bSPierre Pronchery      * s390x_ed448_digestsign() does not yet support context-strings or
517*e7be843bSPierre Pronchery      * pre-hashing. Fall back to non-accelerated sign if a context-string or
518*e7be843bSPierre Pronchery      * pre-hasing is provided.
519*e7be843bSPierre Pronchery      */
520*e7be843bSPierre Pronchery     if (S390X_CAN_SIGN(ED448)
521*e7be843bSPierre Pronchery             && peddsactx->context_string_len == 0
522*e7be843bSPierre Pronchery             && !peddsactx->prehash_flag
523*e7be843bSPierre Pronchery             && !peddsactx->prehash_by_caller_flag) {
524b077aed3SPierre Pronchery         if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
525b077aed3SPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
526b077aed3SPierre Pronchery             return 0;
527b077aed3SPierre Pronchery         }
528b077aed3SPierre Pronchery         *siglen = ED448_SIGSIZE;
529b077aed3SPierre Pronchery         return 1;
530b077aed3SPierre Pronchery     }
531b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
532*e7be843bSPierre Pronchery 
533*e7be843bSPierre Pronchery     if (peddsactx->prehash_flag) {
534*e7be843bSPierre Pronchery         if (!peddsactx->prehash_by_caller_flag) {
535*e7be843bSPierre Pronchery             if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))
536*e7be843bSPierre Pronchery                 return 0;
537*e7be843bSPierre Pronchery             tbs = md;
538*e7be843bSPierre Pronchery             tbslen = mdlen;
539*e7be843bSPierre Pronchery         } else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {
540*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
541*e7be843bSPierre Pronchery             return 0;
542*e7be843bSPierre Pronchery         }
543*e7be843bSPierre Pronchery     } else if (peddsactx->prehash_by_caller_flag) {
544*e7be843bSPierre Pronchery         /* The caller is supposed to set up a ph instance! */
545*e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV,
546*e7be843bSPierre Pronchery                   PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);
547*e7be843bSPierre Pronchery         return 0;
548*e7be843bSPierre Pronchery     }
549*e7be843bSPierre Pronchery 
550*e7be843bSPierre Pronchery     if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen,
551*e7be843bSPierre Pronchery                         edkey->pubkey, edkey->privkey,
552*e7be843bSPierre Pronchery                         peddsactx->context_string, peddsactx->context_string_len,
553*e7be843bSPierre Pronchery                         peddsactx->prehash_flag, edkey->propq) == 0) {
554b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
555b077aed3SPierre Pronchery         return 0;
556b077aed3SPierre Pronchery     }
557b077aed3SPierre Pronchery     *siglen = ED448_SIGSIZE;
558b077aed3SPierre Pronchery     return 1;
559b077aed3SPierre Pronchery }
560b077aed3SPierre Pronchery 
561*e7be843bSPierre Pronchery /*
562*e7be843bSPierre Pronchery  * This is used directly for OSSL_FUNC_SIGNATURE_VERIFY and indirectly
563*e7be843bSPierre Pronchery  * for OSSL_FUNC_SIGNATURE_DIGEST_VERIFY
564*e7be843bSPierre Pronchery  */
ed25519_verify(void * vpeddsactx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)565*e7be843bSPierre Pronchery static int ed25519_verify(void *vpeddsactx,
566*e7be843bSPierre Pronchery                           const unsigned char *sig, size_t siglen,
567*e7be843bSPierre Pronchery                           const unsigned char *tbs, size_t tbslen)
568b077aed3SPierre Pronchery {
569b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
570b077aed3SPierre Pronchery     const ECX_KEY *edkey = peddsactx->key;
571*e7be843bSPierre Pronchery     uint8_t md[EVP_MAX_MD_SIZE];
572*e7be843bSPierre Pronchery     size_t mdlen;
573b077aed3SPierre Pronchery 
574b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
575b077aed3SPierre Pronchery         return 0;
576b077aed3SPierre Pronchery 
577b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
578*e7be843bSPierre Pronchery     /*
579*e7be843bSPierre Pronchery      * s390x_ed25519_digestverify() does not yet support dom2 or context-strings.
580*e7be843bSPierre Pronchery      * fall back to non-accelerated verify if those options are set, or
581*e7be843bSPierre Pronchery      * pre-hasing is provided.
582*e7be843bSPierre Pronchery      */
583*e7be843bSPierre Pronchery     if (S390X_CAN_SIGN(ED25519)
584*e7be843bSPierre Pronchery             && !peddsactx->dom2_flag
585*e7be843bSPierre Pronchery             && !peddsactx->context_string_flag
586*e7be843bSPierre Pronchery             && peddsactx->context_string_len == 0
587*e7be843bSPierre Pronchery             && !peddsactx->prehash_flag
588*e7be843bSPierre Pronchery             && !peddsactx->prehash_by_caller_flag)
589b077aed3SPierre Pronchery         return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
590b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
591b077aed3SPierre Pronchery 
592*e7be843bSPierre Pronchery     if (peddsactx->prehash_flag) {
593*e7be843bSPierre Pronchery         if (!peddsactx->prehash_by_caller_flag) {
594*e7be843bSPierre Pronchery             if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL,
595*e7be843bSPierre Pronchery                               tbs, tbslen, md, &mdlen)
596*e7be843bSPierre Pronchery                 || mdlen != EDDSA_PREHASH_OUTPUT_LEN) {
597*e7be843bSPierre Pronchery                 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PREHASHED_DIGEST_LENGTH);
598*e7be843bSPierre Pronchery                 return 0;
599*e7be843bSPierre Pronchery             }
600*e7be843bSPierre Pronchery             tbs = md;
601*e7be843bSPierre Pronchery             tbslen = mdlen;
602*e7be843bSPierre Pronchery         } else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {
603*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
604*e7be843bSPierre Pronchery             return 0;
605*e7be843bSPierre Pronchery         }
606*e7be843bSPierre Pronchery     } else if (peddsactx->prehash_by_caller_flag) {
607*e7be843bSPierre Pronchery         /* The caller is supposed to set up a ph instance! */
608*e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV,
609*e7be843bSPierre Pronchery                   PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);
610*e7be843bSPierre Pronchery         return 0;
611*e7be843bSPierre Pronchery     }
612*e7be843bSPierre Pronchery 
613b077aed3SPierre Pronchery     return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
614*e7be843bSPierre Pronchery                                peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,
615*e7be843bSPierre Pronchery                                peddsactx->context_string, peddsactx->context_string_len,
616b077aed3SPierre Pronchery                                peddsactx->libctx, edkey->propq);
617b077aed3SPierre Pronchery }
618b077aed3SPierre Pronchery 
619*e7be843bSPierre Pronchery /*
620*e7be843bSPierre Pronchery  * This is used directly for OSSL_FUNC_SIGNATURE_VERIFY and indirectly
621*e7be843bSPierre Pronchery  * for OSSL_FUNC_SIGNATURE_DIGEST_VERIFY
622*e7be843bSPierre Pronchery  */
ed448_verify(void * vpeddsactx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)623*e7be843bSPierre Pronchery static int ed448_verify(void *vpeddsactx,
624*e7be843bSPierre Pronchery                         const unsigned char *sig, size_t siglen,
625*e7be843bSPierre Pronchery                         const unsigned char *tbs, size_t tbslen)
626b077aed3SPierre Pronchery {
627b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
628b077aed3SPierre Pronchery     const ECX_KEY *edkey = peddsactx->key;
629*e7be843bSPierre Pronchery     uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];
630*e7be843bSPierre Pronchery     size_t mdlen = sizeof(md);
631b077aed3SPierre Pronchery 
632b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
633b077aed3SPierre Pronchery         return 0;
634b077aed3SPierre Pronchery 
635b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
636*e7be843bSPierre Pronchery     /*
637*e7be843bSPierre Pronchery      * s390x_ed448_digestverify() does not yet support context-strings or
638*e7be843bSPierre Pronchery      * pre-hashing. Fall back to non-accelerated verify if a context-string or
639*e7be843bSPierre Pronchery      * pre-hasing is provided.
640*e7be843bSPierre Pronchery      */
641*e7be843bSPierre Pronchery     if (S390X_CAN_SIGN(ED448)
642*e7be843bSPierre Pronchery             && peddsactx->context_string_len == 0
643*e7be843bSPierre Pronchery             && !peddsactx->prehash_flag
644*e7be843bSPierre Pronchery             && !peddsactx->prehash_by_caller_flag)
645b077aed3SPierre Pronchery         return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
646b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
647b077aed3SPierre Pronchery 
648*e7be843bSPierre Pronchery     if (peddsactx->prehash_flag) {
649*e7be843bSPierre Pronchery         if (!peddsactx->prehash_by_caller_flag) {
650*e7be843bSPierre Pronchery             if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))
651*e7be843bSPierre Pronchery                 return 0;
652*e7be843bSPierre Pronchery             tbs = md;
653*e7be843bSPierre Pronchery             tbslen = mdlen;
654*e7be843bSPierre Pronchery         } else if (tbslen != EDDSA_PREHASH_OUTPUT_LEN) {
655*e7be843bSPierre Pronchery             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
656*e7be843bSPierre Pronchery             return 0;
657*e7be843bSPierre Pronchery         }
658*e7be843bSPierre Pronchery     } else if (peddsactx->prehash_by_caller_flag) {
659*e7be843bSPierre Pronchery         /* The caller is supposed to set up a ph instance! */
660*e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV,
661*e7be843bSPierre Pronchery                   PROV_R_INVALID_EDDSA_INSTANCE_FOR_ATTEMPTED_OPERATION);
662*e7be843bSPierre Pronchery         return 0;
663*e7be843bSPierre Pronchery     }
664*e7be843bSPierre Pronchery 
665b077aed3SPierre Pronchery     return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
666*e7be843bSPierre Pronchery                              peddsactx->context_string, peddsactx->context_string_len,
667*e7be843bSPierre Pronchery                              peddsactx->prehash_flag, edkey->propq);
668*e7be843bSPierre Pronchery }
669*e7be843bSPierre Pronchery 
670*e7be843bSPierre Pronchery /* All digest_{sign,verify} are simple wrappers around the functions above */
671*e7be843bSPierre Pronchery 
ed25519_digest_signverify_init(void * vpeddsactx,const char * mdname,void * vedkey,const OSSL_PARAM params[])672*e7be843bSPierre Pronchery static int ed25519_digest_signverify_init(void *vpeddsactx, const char *mdname,
673*e7be843bSPierre Pronchery                                           void *vedkey,
674*e7be843bSPierre Pronchery                                           const OSSL_PARAM params[])
675*e7be843bSPierre Pronchery {
676*e7be843bSPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
677*e7be843bSPierre Pronchery 
678*e7be843bSPierre Pronchery     if (mdname != NULL && mdname[0] != '\0') {
679*e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
680*e7be843bSPierre Pronchery                         "Explicit digest not allowed with EdDSA operations");
681*e7be843bSPierre Pronchery         return 0;
682*e7be843bSPierre Pronchery     }
683*e7be843bSPierre Pronchery 
684*e7be843bSPierre Pronchery     if (vedkey == NULL && peddsactx->key != NULL)
685*e7be843bSPierre Pronchery         return eddsa_set_ctx_params(peddsactx, params);
686*e7be843bSPierre Pronchery 
687*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
688*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed25519, 0, 0)
689*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
690*e7be843bSPierre Pronchery }
691*e7be843bSPierre Pronchery 
ed25519_digest_sign(void * vpeddsactx,unsigned char * sigret,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)692*e7be843bSPierre Pronchery static int ed25519_digest_sign(void *vpeddsactx,
693*e7be843bSPierre Pronchery                                unsigned char *sigret, size_t *siglen, size_t sigsize,
694*e7be843bSPierre Pronchery                                const unsigned char *tbs, size_t tbslen)
695*e7be843bSPierre Pronchery {
696*e7be843bSPierre Pronchery     return ed25519_sign(vpeddsactx, sigret, siglen, sigsize, tbs, tbslen);
697*e7be843bSPierre Pronchery }
698*e7be843bSPierre Pronchery 
ed25519_digest_verify(void * vpeddsactx,const unsigned char * sigret,size_t siglen,const unsigned char * tbs,size_t tbslen)699*e7be843bSPierre Pronchery static int ed25519_digest_verify(void *vpeddsactx,
700*e7be843bSPierre Pronchery                                  const unsigned char *sigret, size_t siglen,
701*e7be843bSPierre Pronchery                                  const unsigned char *tbs, size_t tbslen)
702*e7be843bSPierre Pronchery {
703*e7be843bSPierre Pronchery     return ed25519_verify(vpeddsactx, sigret, siglen, tbs, tbslen);
704*e7be843bSPierre Pronchery }
705*e7be843bSPierre Pronchery 
ed448_digest_signverify_init(void * vpeddsactx,const char * mdname,void * vedkey,const OSSL_PARAM params[])706*e7be843bSPierre Pronchery static int ed448_digest_signverify_init(void *vpeddsactx, const char *mdname,
707*e7be843bSPierre Pronchery                                         void *vedkey,
708*e7be843bSPierre Pronchery                                         const OSSL_PARAM params[])
709*e7be843bSPierre Pronchery {
710*e7be843bSPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
711*e7be843bSPierre Pronchery 
712*e7be843bSPierre Pronchery     if (mdname != NULL && mdname[0] != '\0') {
713*e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
714*e7be843bSPierre Pronchery                         "Explicit digest not allowed with EdDSA operations");
715*e7be843bSPierre Pronchery         return 0;
716*e7be843bSPierre Pronchery     }
717*e7be843bSPierre Pronchery 
718*e7be843bSPierre Pronchery     if (vedkey == NULL && peddsactx->key != NULL)
719*e7be843bSPierre Pronchery         return eddsa_set_ctx_params(peddsactx, params);
720*e7be843bSPierre Pronchery 
721*e7be843bSPierre Pronchery     return eddsa_signverify_init(vpeddsactx, vedkey)
722*e7be843bSPierre Pronchery         && eddsa_setup_instance(vpeddsactx, ID_Ed448, 0, 0)
723*e7be843bSPierre Pronchery         && eddsa_set_ctx_params(vpeddsactx, params);
724*e7be843bSPierre Pronchery }
725*e7be843bSPierre Pronchery 
ed448_digest_sign(void * vpeddsactx,unsigned char * sigret,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)726*e7be843bSPierre Pronchery static int ed448_digest_sign(void *vpeddsactx,
727*e7be843bSPierre Pronchery                              unsigned char *sigret, size_t *siglen, size_t sigsize,
728*e7be843bSPierre Pronchery                              const unsigned char *tbs, size_t tbslen)
729*e7be843bSPierre Pronchery {
730*e7be843bSPierre Pronchery     return ed448_sign(vpeddsactx, sigret, siglen, sigsize, tbs, tbslen);
731*e7be843bSPierre Pronchery }
732*e7be843bSPierre Pronchery 
ed448_digest_verify(void * vpeddsactx,const unsigned char * sigret,size_t siglen,const unsigned char * tbs,size_t tbslen)733*e7be843bSPierre Pronchery static int ed448_digest_verify(void *vpeddsactx,
734*e7be843bSPierre Pronchery                                const unsigned char *sigret, size_t siglen,
735*e7be843bSPierre Pronchery                                const unsigned char *tbs, size_t tbslen)
736*e7be843bSPierre Pronchery {
737*e7be843bSPierre Pronchery     return ed448_verify(vpeddsactx, sigret, siglen, tbs, tbslen);
738b077aed3SPierre Pronchery }
739b077aed3SPierre Pronchery 
eddsa_freectx(void * vpeddsactx)740b077aed3SPierre Pronchery static void eddsa_freectx(void *vpeddsactx)
741b077aed3SPierre Pronchery {
742b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
743b077aed3SPierre Pronchery 
744b077aed3SPierre Pronchery     ossl_ecx_key_free(peddsactx->key);
745b077aed3SPierre Pronchery 
746b077aed3SPierre Pronchery     OPENSSL_free(peddsactx);
747b077aed3SPierre Pronchery }
748b077aed3SPierre Pronchery 
eddsa_dupctx(void * vpeddsactx)749b077aed3SPierre Pronchery static void *eddsa_dupctx(void *vpeddsactx)
750b077aed3SPierre Pronchery {
751b077aed3SPierre Pronchery     PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
752b077aed3SPierre Pronchery     PROV_EDDSA_CTX *dstctx;
753b077aed3SPierre Pronchery 
754b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
755b077aed3SPierre Pronchery         return NULL;
756b077aed3SPierre Pronchery 
757b077aed3SPierre Pronchery     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
758b077aed3SPierre Pronchery     if (dstctx == NULL)
759b077aed3SPierre Pronchery         return NULL;
760b077aed3SPierre Pronchery 
761b077aed3SPierre Pronchery     *dstctx = *srcctx;
762b077aed3SPierre Pronchery     dstctx->key = NULL;
763b077aed3SPierre Pronchery 
764b077aed3SPierre Pronchery     if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
765b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
766b077aed3SPierre Pronchery         goto err;
767b077aed3SPierre Pronchery     }
768b077aed3SPierre Pronchery     dstctx->key = srcctx->key;
769b077aed3SPierre Pronchery 
770b077aed3SPierre Pronchery     return dstctx;
771b077aed3SPierre Pronchery  err:
772b077aed3SPierre Pronchery     eddsa_freectx(dstctx);
773b077aed3SPierre Pronchery     return NULL;
774b077aed3SPierre Pronchery }
775b077aed3SPierre Pronchery 
ed25519_sigalg_query_key_types(void)776*e7be843bSPierre Pronchery static const char **ed25519_sigalg_query_key_types(void)
777*e7be843bSPierre Pronchery {
778*e7be843bSPierre Pronchery     static const char *keytypes[] = { "ED25519", NULL };
779*e7be843bSPierre Pronchery 
780*e7be843bSPierre Pronchery     return keytypes;
781*e7be843bSPierre Pronchery }
782*e7be843bSPierre Pronchery 
ed448_sigalg_query_key_types(void)783*e7be843bSPierre Pronchery static const char **ed448_sigalg_query_key_types(void)
784*e7be843bSPierre Pronchery {
785*e7be843bSPierre Pronchery     static const char *keytypes[] = { "ED448", NULL };
786*e7be843bSPierre Pronchery 
787*e7be843bSPierre Pronchery     return keytypes;
788*e7be843bSPierre Pronchery }
789*e7be843bSPierre Pronchery 
790*e7be843bSPierre Pronchery 
791*e7be843bSPierre Pronchery 
eddsa_get_ctx_params(void * vpeddsactx,OSSL_PARAM * params)792b077aed3SPierre Pronchery static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
793b077aed3SPierre Pronchery {
794b077aed3SPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
795b077aed3SPierre Pronchery     OSSL_PARAM *p;
796b077aed3SPierre Pronchery 
797b077aed3SPierre Pronchery     if (peddsactx == NULL)
798b077aed3SPierre Pronchery         return 0;
799b077aed3SPierre Pronchery 
800b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
801*e7be843bSPierre Pronchery     if (p != NULL
802*e7be843bSPierre Pronchery         && !OSSL_PARAM_set_octet_string(p,
803*e7be843bSPierre Pronchery                                         peddsactx->aid_len == 0 ? NULL : peddsactx->aid_buf,
804b077aed3SPierre Pronchery                                         peddsactx->aid_len))
805b077aed3SPierre Pronchery         return 0;
806b077aed3SPierre Pronchery 
807b077aed3SPierre Pronchery     return 1;
808b077aed3SPierre Pronchery }
809b077aed3SPierre Pronchery 
810b077aed3SPierre Pronchery static const OSSL_PARAM known_gettable_ctx_params[] = {
811b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
812*e7be843bSPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),
813*e7be843bSPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
814b077aed3SPierre Pronchery     OSSL_PARAM_END
815b077aed3SPierre Pronchery };
816b077aed3SPierre Pronchery 
eddsa_gettable_ctx_params(ossl_unused void * vpeddsactx,ossl_unused void * provctx)817b077aed3SPierre Pronchery static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
818b077aed3SPierre Pronchery                                                    ossl_unused void *provctx)
819b077aed3SPierre Pronchery {
820b077aed3SPierre Pronchery     return known_gettable_ctx_params;
821b077aed3SPierre Pronchery }
822b077aed3SPierre Pronchery 
eddsa_set_ctx_params(void * vpeddsactx,const OSSL_PARAM params[])823*e7be843bSPierre Pronchery static int eddsa_set_ctx_params(void *vpeddsactx, const OSSL_PARAM params[])
824*e7be843bSPierre Pronchery {
825*e7be843bSPierre Pronchery     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
826*e7be843bSPierre Pronchery     const OSSL_PARAM *p;
827*e7be843bSPierre Pronchery 
828*e7be843bSPierre Pronchery     if (peddsactx == NULL)
829*e7be843bSPierre Pronchery         return 0;
830*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
831*e7be843bSPierre Pronchery         return 1;
832*e7be843bSPierre Pronchery 
833*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_INSTANCE);
834*e7be843bSPierre Pronchery     if (p != NULL) {
835*e7be843bSPierre Pronchery         char instance_name[OSSL_MAX_NAME_SIZE] = "";
836*e7be843bSPierre Pronchery         char *pinstance_name = instance_name;
837*e7be843bSPierre Pronchery 
838*e7be843bSPierre Pronchery         if (peddsactx->instance_id_preset_flag) {
839*e7be843bSPierre Pronchery             /* When the instance is preset, the caller must no try to set it */
840*e7be843bSPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_NO_INSTANCE_ALLOWED,
841*e7be843bSPierre Pronchery                            "the EdDSA instance is preset, you may not try to specify it",
842*e7be843bSPierre Pronchery                            NULL);
843*e7be843bSPierre Pronchery             return 0;
844*e7be843bSPierre Pronchery         }
845*e7be843bSPierre Pronchery 
846*e7be843bSPierre Pronchery         if (!OSSL_PARAM_get_utf8_string(p, &pinstance_name, sizeof(instance_name)))
847*e7be843bSPierre Pronchery             return 0;
848*e7be843bSPierre Pronchery 
849*e7be843bSPierre Pronchery         /*
850*e7be843bSPierre Pronchery          * When setting the new instance, we're careful not to change the
851*e7be843bSPierre Pronchery          * prehash_by_caller flag, as that's always preset by the init
852*e7be843bSPierre Pronchery          * functions.  The sign functions will determine if the instance
853*e7be843bSPierre Pronchery          * matches this flag.
854*e7be843bSPierre Pronchery          */
855*e7be843bSPierre Pronchery         if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519) == 0) {
856*e7be843bSPierre Pronchery             eddsa_setup_instance(peddsactx, ID_Ed25519, 0,
857*e7be843bSPierre Pronchery                                  peddsactx->prehash_by_caller_flag);
858*e7be843bSPierre Pronchery         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ctx) == 0) {
859*e7be843bSPierre Pronchery             eddsa_setup_instance(peddsactx, ID_Ed25519ctx, 0,
860*e7be843bSPierre Pronchery                                  peddsactx->prehash_by_caller_flag);
861*e7be843bSPierre Pronchery         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ph) == 0) {
862*e7be843bSPierre Pronchery             eddsa_setup_instance(peddsactx, ID_Ed25519ph, 0,
863*e7be843bSPierre Pronchery                                  peddsactx->prehash_by_caller_flag);
864*e7be843bSPierre Pronchery         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448) == 0) {
865*e7be843bSPierre Pronchery             eddsa_setup_instance(peddsactx, ID_Ed448, 0,
866*e7be843bSPierre Pronchery                                  peddsactx->prehash_by_caller_flag);
867*e7be843bSPierre Pronchery         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448ph) == 0) {
868*e7be843bSPierre Pronchery             eddsa_setup_instance(peddsactx, ID_Ed448ph, 0,
869*e7be843bSPierre Pronchery                                  peddsactx->prehash_by_caller_flag);
870*e7be843bSPierre Pronchery         } else {
871*e7be843bSPierre Pronchery             /* we did not recognize the instance */
872*e7be843bSPierre Pronchery             return 0;
873*e7be843bSPierre Pronchery         }
874*e7be843bSPierre Pronchery 
875*e7be843bSPierre Pronchery     }
876*e7be843bSPierre Pronchery 
877*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);
878*e7be843bSPierre Pronchery     if (p != NULL) {
879*e7be843bSPierre Pronchery         void *vp_context_string = peddsactx->context_string;
880*e7be843bSPierre Pronchery 
881*e7be843bSPierre Pronchery         if (!OSSL_PARAM_get_octet_string(p, &vp_context_string, sizeof(peddsactx->context_string), &(peddsactx->context_string_len))) {
882*e7be843bSPierre Pronchery             peddsactx->context_string_len = 0;
883*e7be843bSPierre Pronchery             return 0;
884*e7be843bSPierre Pronchery         }
885*e7be843bSPierre Pronchery     }
886*e7be843bSPierre Pronchery 
887*e7be843bSPierre Pronchery     return 1;
888*e7be843bSPierre Pronchery }
889*e7be843bSPierre Pronchery 
890*e7be843bSPierre Pronchery static const OSSL_PARAM settable_ctx_params[] = {
891*e7be843bSPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),
892*e7be843bSPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
893*e7be843bSPierre Pronchery     OSSL_PARAM_END
894b077aed3SPierre Pronchery };
895b077aed3SPierre Pronchery 
eddsa_settable_ctx_params(ossl_unused void * vpeddsactx,ossl_unused void * provctx)896*e7be843bSPierre Pronchery static const OSSL_PARAM *eddsa_settable_ctx_params(ossl_unused void *vpeddsactx,
897*e7be843bSPierre Pronchery                                                    ossl_unused void *provctx)
898*e7be843bSPierre Pronchery {
899*e7be843bSPierre Pronchery     return settable_ctx_params;
900*e7be843bSPierre Pronchery }
901*e7be843bSPierre Pronchery 
902*e7be843bSPierre Pronchery static const OSSL_PARAM settable_variant_ctx_params[] = {
903*e7be843bSPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
904*e7be843bSPierre Pronchery     OSSL_PARAM_END
905b077aed3SPierre Pronchery };
906b077aed3SPierre Pronchery 
907*e7be843bSPierre Pronchery static const OSSL_PARAM *
eddsa_settable_variant_ctx_params(ossl_unused void * vpeddsactx,ossl_unused void * provctx)908*e7be843bSPierre Pronchery eddsa_settable_variant_ctx_params(ossl_unused void *vpeddsactx,
909*e7be843bSPierre Pronchery                                   ossl_unused void *provctx)
910*e7be843bSPierre Pronchery {
911*e7be843bSPierre Pronchery     return settable_variant_ctx_params;
912*e7be843bSPierre Pronchery }
913*e7be843bSPierre Pronchery 
914*e7be843bSPierre Pronchery /*
915*e7be843bSPierre Pronchery  * Ed25519 can be used with:
916*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_init_ex2()   [ instance and prehash assumed done by caller ]
917*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ]
918*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_message_init()
919*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_message_init()
920*e7be843bSPierre Pronchery  * - EVP_DigestSignInit_ex()
921*e7be843bSPierre Pronchery  * - EVP_DigestVerifyInit_ex()
922*e7be843bSPierre Pronchery  * Ed25519ph can be used with:
923*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_init_ex2()   [ prehash assumed done by caller ]
924*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_init_ex2() [ prehash assumed done by caller ]
925*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_message_init()
926*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_message_init()
927*e7be843bSPierre Pronchery  * Ed25519ctx can be used with:
928*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_message_init()
929*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_message_init()
930*e7be843bSPierre Pronchery  * Ed448 can be used with:
931*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_init_ex2()   [ instance and prehash assumed done by caller ]
932*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_init_ex2() [ instance and prehash assumed done by caller ]
933*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_message_init()
934*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_message_init()
935*e7be843bSPierre Pronchery  * - EVP_DigestSignInit_ex()
936*e7be843bSPierre Pronchery  * - EVP_DigestVerifyInit_ex()
937*e7be843bSPierre Pronchery  * Ed448ph can be used with:
938*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_init_ex2()   [ prehash assumed done by caller ]
939*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_init_ex2() [ prehash assumed done by caller ]
940*e7be843bSPierre Pronchery  * - EVP_PKEY_sign_message_init()
941*e7be843bSPierre Pronchery  * - EVP_PKEY_verify_message_init()
942*e7be843bSPierre Pronchery  */
943*e7be843bSPierre Pronchery 
944*e7be843bSPierre Pronchery #define ed25519_DISPATCH_END                                            \
945*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                    \
946*e7be843bSPierre Pronchery         (void (*)(void))ed25519_signverify_init },                      \
947*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                                  \
948*e7be843bSPierre Pronchery         (void (*)(void))ed25519_signverify_init },                      \
949*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,                             \
950*e7be843bSPierre Pronchery         (void (*)(void))ed25519_digest_signverify_init },               \
951*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,                                  \
952*e7be843bSPierre Pronchery         (void (*)(void))ed25519_digest_sign },                          \
953*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,                           \
954*e7be843bSPierre Pronchery         (void (*)(void))ed25519_digest_signverify_init },               \
955*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,                                \
956*e7be843bSPierre Pronchery         (void (*)(void))ed25519_digest_verify },                        \
957*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,                               \
958*e7be843bSPierre Pronchery         (void (*)(void))eddsa_get_ctx_params },                         \
959*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,                          \
960*e7be843bSPierre Pronchery         (void (*)(void))eddsa_gettable_ctx_params },                    \
961*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS,                               \
962*e7be843bSPierre Pronchery         (void (*)(void))eddsa_set_ctx_params },                         \
963*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,                          \
964*e7be843bSPierre Pronchery         (void (*)(void))eddsa_settable_ctx_params },                    \
965*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
966*e7be843bSPierre Pronchery 
967*e7be843bSPierre Pronchery #define eddsa_variant_DISPATCH_END(v)                                   \
968*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                    \
969*e7be843bSPierre Pronchery         (void (*)(void))v##_signverify_message_init },                  \
970*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                                  \
971*e7be843bSPierre Pronchery         (void (*)(void))v##_signverify_message_init },                  \
972*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,                               \
973*e7be843bSPierre Pronchery         (void (*)(void))eddsa_get_ctx_params },                         \
974*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,                          \
975*e7be843bSPierre Pronchery         (void (*)(void))eddsa_gettable_ctx_params },                    \
976*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS,                               \
977*e7be843bSPierre Pronchery         (void (*)(void))eddsa_set_ctx_params },                         \
978*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,                          \
979*e7be843bSPierre Pronchery         (void (*)(void))eddsa_settable_variant_ctx_params },            \
980*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
981*e7be843bSPierre Pronchery 
982*e7be843bSPierre Pronchery #define ed25519ph_DISPATCH_END                                          \
983*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                    \
984*e7be843bSPierre Pronchery         (void (*)(void))ed25519ph_signverify_init },                    \
985*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                                  \
986*e7be843bSPierre Pronchery         (void (*)(void))ed25519ph_signverify_init },                    \
987*e7be843bSPierre Pronchery     eddsa_variant_DISPATCH_END(ed25519ph)
988*e7be843bSPierre Pronchery 
989*e7be843bSPierre Pronchery #define ed25519ctx_DISPATCH_END eddsa_variant_DISPATCH_END(ed25519ctx)
990*e7be843bSPierre Pronchery 
991*e7be843bSPierre Pronchery #define ed448_DISPATCH_END                                              \
992*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                    \
993*e7be843bSPierre Pronchery         (void (*)(void))ed448_signverify_init },                        \
994*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                                  \
995*e7be843bSPierre Pronchery         (void (*)(void))ed448_signverify_init },                        \
996*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,                             \
997*e7be843bSPierre Pronchery         (void (*)(void))ed448_digest_signverify_init },                 \
998*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,                                  \
999*e7be843bSPierre Pronchery         (void (*)(void))ed448_digest_sign },                            \
1000*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,                           \
1001*e7be843bSPierre Pronchery         (void (*)(void))ed448_digest_signverify_init },                 \
1002*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,                                \
1003*e7be843bSPierre Pronchery         (void (*)(void))ed448_digest_verify },                          \
1004*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,                               \
1005*e7be843bSPierre Pronchery         (void (*)(void))eddsa_get_ctx_params },                         \
1006*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,                          \
1007*e7be843bSPierre Pronchery         (void (*)(void))eddsa_gettable_ctx_params },                    \
1008*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS,                               \
1009*e7be843bSPierre Pronchery         (void (*)(void))eddsa_set_ctx_params },                         \
1010*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,                          \
1011*e7be843bSPierre Pronchery         (void (*)(void))eddsa_settable_ctx_params },                    \
1012*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
1013*e7be843bSPierre Pronchery 
1014*e7be843bSPierre Pronchery #define ed448ph_DISPATCH_END                                            \
1015*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                    \
1016*e7be843bSPierre Pronchery         (void (*)(void))ed448ph_signverify_init },                      \
1017*e7be843bSPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                                  \
1018*e7be843bSPierre Pronchery         (void (*)(void))ed448ph_signverify_init },                      \
1019*e7be843bSPierre Pronchery     eddsa_variant_DISPATCH_END(ed448ph)
1020*e7be843bSPierre Pronchery 
1021*e7be843bSPierre Pronchery /* vn = variant name, bn = base name */
1022*e7be843bSPierre Pronchery #define IMPL_EDDSA_DISPATCH(vn,bn)                                      \
1023*e7be843bSPierre Pronchery     const OSSL_DISPATCH ossl_##vn##_signature_functions[] = {           \
1024*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },   \
1025*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT,                        \
1026*e7be843bSPierre Pronchery           (void (*)(void))vn##_signverify_message_init },               \
1027*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN,                                     \
1028*e7be843bSPierre Pronchery           (void (*)(void))bn##_sign },                                  \
1029*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT,                      \
1030*e7be843bSPierre Pronchery           (void (*)(void))vn##_signverify_message_init },               \
1031*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY,                                   \
1032*e7be843bSPierre Pronchery           (void (*)(void))bn##_verify },                                \
1033*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, \
1034*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },   \
1035*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES,                          \
1036*e7be843bSPierre Pronchery           (void (*)(void))bn##_sigalg_query_key_types },                \
1037*e7be843bSPierre Pronchery         vn##_DISPATCH_END                                               \
1038*e7be843bSPierre Pronchery     }
1039*e7be843bSPierre Pronchery 
1040*e7be843bSPierre Pronchery IMPL_EDDSA_DISPATCH(ed25519,ed25519);
1041*e7be843bSPierre Pronchery IMPL_EDDSA_DISPATCH(ed25519ph,ed25519);
1042*e7be843bSPierre Pronchery IMPL_EDDSA_DISPATCH(ed25519ctx,ed25519);
1043*e7be843bSPierre Pronchery IMPL_EDDSA_DISPATCH(ed448,ed448);
1044*e7be843bSPierre Pronchery IMPL_EDDSA_DISPATCH(ed448ph,ed448);
1045*e7be843bSPierre Pronchery 
1046b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
1047b077aed3SPierre Pronchery 
s390x_ed25519_digestsign(const ECX_KEY * edkey,unsigned char * sig,const unsigned char * tbs,size_t tbslen)1048b077aed3SPierre Pronchery static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
1049b077aed3SPierre Pronchery                                     const unsigned char *tbs, size_t tbslen)
1050b077aed3SPierre Pronchery {
1051b077aed3SPierre Pronchery     int rc;
1052b077aed3SPierre Pronchery     union {
1053b077aed3SPierre Pronchery         struct {
1054b077aed3SPierre Pronchery             unsigned char sig[64];
1055b077aed3SPierre Pronchery             unsigned char priv[32];
1056b077aed3SPierre Pronchery         } ed25519;
1057b077aed3SPierre Pronchery         unsigned long long buff[512];
1058b077aed3SPierre Pronchery     } param;
1059b077aed3SPierre Pronchery 
1060b077aed3SPierre Pronchery     memset(&param, 0, sizeof(param));
1061b077aed3SPierre Pronchery     memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1062b077aed3SPierre Pronchery 
1063b077aed3SPierre Pronchery     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1064b077aed3SPierre Pronchery     OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1065b077aed3SPierre Pronchery     if (rc != 0)
1066b077aed3SPierre Pronchery         return 0;
1067b077aed3SPierre Pronchery 
1068b077aed3SPierre Pronchery     s390x_flip_endian32(sig, param.ed25519.sig);
1069b077aed3SPierre Pronchery     s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1070b077aed3SPierre Pronchery     return 1;
1071b077aed3SPierre Pronchery }
1072b077aed3SPierre Pronchery 
s390x_ed448_digestsign(const ECX_KEY * edkey,unsigned char * sig,const unsigned char * tbs,size_t tbslen)1073b077aed3SPierre Pronchery static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
1074b077aed3SPierre Pronchery                                   const unsigned char *tbs, size_t tbslen)
1075b077aed3SPierre Pronchery {
1076b077aed3SPierre Pronchery     int rc;
1077b077aed3SPierre Pronchery     union {
1078b077aed3SPierre Pronchery         struct {
1079b077aed3SPierre Pronchery             unsigned char sig[128];
1080b077aed3SPierre Pronchery             unsigned char priv[64];
1081b077aed3SPierre Pronchery         } ed448;
1082b077aed3SPierre Pronchery         unsigned long long buff[512];
1083b077aed3SPierre Pronchery     } param;
1084b077aed3SPierre Pronchery 
1085b077aed3SPierre Pronchery     memset(&param, 0, sizeof(param));
1086b077aed3SPierre Pronchery     memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1087b077aed3SPierre Pronchery 
1088b077aed3SPierre Pronchery     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1089b077aed3SPierre Pronchery     OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1090b077aed3SPierre Pronchery     if (rc != 0)
1091b077aed3SPierre Pronchery         return 0;
1092b077aed3SPierre Pronchery 
1093b077aed3SPierre Pronchery     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1094b077aed3SPierre Pronchery     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1095b077aed3SPierre Pronchery     memcpy(sig, param.ed448.sig, 57);
1096b077aed3SPierre Pronchery     memcpy(sig + 57, param.ed448.sig + 64, 57);
1097b077aed3SPierre Pronchery     return 1;
1098b077aed3SPierre Pronchery }
1099b077aed3SPierre Pronchery 
s390x_ed25519_digestverify(const ECX_KEY * edkey,const unsigned char * sig,const unsigned char * tbs,size_t tbslen)1100b077aed3SPierre Pronchery static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
1101b077aed3SPierre Pronchery                                       const unsigned char *sig,
1102b077aed3SPierre Pronchery                                       const unsigned char *tbs, size_t tbslen)
1103b077aed3SPierre Pronchery {
1104b077aed3SPierre Pronchery     union {
1105b077aed3SPierre Pronchery         struct {
1106b077aed3SPierre Pronchery             unsigned char sig[64];
1107b077aed3SPierre Pronchery             unsigned char pub[32];
1108b077aed3SPierre Pronchery         } ed25519;
1109b077aed3SPierre Pronchery         unsigned long long buff[512];
1110b077aed3SPierre Pronchery     } param;
1111b077aed3SPierre Pronchery 
1112b077aed3SPierre Pronchery     memset(&param, 0, sizeof(param));
1113b077aed3SPierre Pronchery     s390x_flip_endian32(param.ed25519.sig, sig);
1114b077aed3SPierre Pronchery     s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1115b077aed3SPierre Pronchery     s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1116b077aed3SPierre Pronchery 
1117b077aed3SPierre Pronchery     return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1118b077aed3SPierre Pronchery                       &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1119b077aed3SPierre Pronchery }
1120b077aed3SPierre Pronchery 
s390x_ed448_digestverify(const ECX_KEY * edkey,const unsigned char * sig,const unsigned char * tbs,size_t tbslen)1121b077aed3SPierre Pronchery static int s390x_ed448_digestverify(const ECX_KEY *edkey,
1122b077aed3SPierre Pronchery                                     const unsigned char *sig,
1123b077aed3SPierre Pronchery                                     const unsigned char *tbs,
1124b077aed3SPierre Pronchery                                     size_t tbslen)
1125b077aed3SPierre Pronchery {
1126b077aed3SPierre Pronchery     union {
1127b077aed3SPierre Pronchery         struct {
1128b077aed3SPierre Pronchery             unsigned char sig[128];
1129b077aed3SPierre Pronchery             unsigned char pub[64];
1130b077aed3SPierre Pronchery         } ed448;
1131b077aed3SPierre Pronchery         unsigned long long buff[512];
1132b077aed3SPierre Pronchery     } param;
1133b077aed3SPierre Pronchery 
1134b077aed3SPierre Pronchery     memset(&param, 0, sizeof(param));
1135b077aed3SPierre Pronchery     memcpy(param.ed448.sig, sig, 57);
1136b077aed3SPierre Pronchery     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1137b077aed3SPierre Pronchery     memcpy(param.ed448.sig + 64, sig + 57, 57);
1138b077aed3SPierre Pronchery     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1139b077aed3SPierre Pronchery     memcpy(param.ed448.pub, edkey->pubkey, 57);
1140b077aed3SPierre Pronchery     s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1141b077aed3SPierre Pronchery 
1142b077aed3SPierre Pronchery     return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1143b077aed3SPierre Pronchery                       &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1144b077aed3SPierre Pronchery }
1145b077aed3SPierre Pronchery 
1146b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
1147