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(¶m, 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, ¶m.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(¶m, 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, ¶m.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(¶m, 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 ¶m.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(¶m, 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 ¶m.ed448, tbs, tbslen) == 0 ? 1 : 0;
1144b077aed3SPierre Pronchery }
1145b077aed3SPierre Pronchery
1146b077aed3SPierre Pronchery #endif /* S390X_EC_ASM */
1147