1 /*
2  * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <openssl/crypto.h>
11 #include <openssl/core_dispatch.h>
12 #include <openssl/core_names.h>
13 #include <openssl/err.h>
14 #include <openssl/params.h>
15 #include <openssl/evp.h>
16 #include <openssl/proverr.h>
17 #include "internal/nelem.h"
18 #include "internal/sizes.h"
19 #include "prov/providercommon.h"
20 #include "prov/implementations.h"
21 #include "prov/provider_ctx.h"
22 #include "prov/der_ecx.h"
23 #include "crypto/ecx.h"
24 
25 #ifdef S390X_EC_ASM
26 # include "s390x_arch.h"
27 
28 # define S390X_CAN_SIGN(edtype)                                                \
29 ((OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_##edtype))    \
30 && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_##edtype))      \
31 && (OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_##edtype)))
32 
33 static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
34                                     const unsigned char *tbs, size_t tbslen);
35 static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
36                                   const unsigned char *tbs, size_t tbslen);
37 static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
38                                       const unsigned char *sig,
39                                       const unsigned char *tbs, size_t tbslen);
40 static int s390x_ed448_digestverify(const ECX_KEY *edkey,
41                                     const unsigned char *sig,
42                                     const unsigned char *tbs, size_t tbslen);
43 
44 #endif /* S390X_EC_ASM */
45 
46 enum ID_EdDSA_INSTANCE {
47     ID_NOT_SET = 0,
48     ID_Ed25519,
49     ID_Ed25519ctx,
50     ID_Ed25519ph,
51     ID_Ed448,
52     ID_Ed448ph
53 };
54 
55 #define SN_Ed25519    "Ed25519"
56 #define SN_Ed25519ph  "Ed25519ph"
57 #define SN_Ed25519ctx "Ed25519ctx"
58 #define SN_Ed448      "Ed448"
59 #define SN_Ed448ph    "Ed448ph"
60 
61 #define EDDSA_MAX_CONTEXT_STRING_LEN 255
62 #define EDDSA_PREHASH_OUTPUT_LEN 64
63 
64 static OSSL_FUNC_signature_newctx_fn eddsa_newctx;
65 static OSSL_FUNC_signature_digest_sign_init_fn eddsa_digest_signverify_init;
66 static OSSL_FUNC_signature_digest_sign_fn ed25519_digest_sign;
67 static OSSL_FUNC_signature_digest_sign_fn ed448_digest_sign;
68 static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify;
69 static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify;
70 static OSSL_FUNC_signature_freectx_fn eddsa_freectx;
71 static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx;
72 static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params;
73 static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params;
74 static OSSL_FUNC_signature_set_ctx_params_fn eddsa_set_ctx_params;
75 static OSSL_FUNC_signature_settable_ctx_params_fn eddsa_settable_ctx_params;
76 
77 /* there are five EdDSA instances:
78 
79          Ed25519
80          Ed25519ph
81          Ed25519ctx
82          Ed448
83          Ed448ph
84 
85    Quoting from RFC 8032, Section 5.1:
86 
87      For Ed25519, dom2(f,c) is the empty string.  The phflag value is
88      irrelevant.  The context (if present at all) MUST be empty.  This
89      causes the scheme to be one and the same with the Ed25519 scheme
90      published earlier.
91 
92      For Ed25519ctx, phflag=0.  The context input SHOULD NOT be empty.
93 
94      For Ed25519ph, phflag=1 and PH is SHA512 instead.  That is, the input
95      is hashed using SHA-512 before signing with Ed25519.
96 
97    Quoting from RFC 8032, Section 5.2:
98 
99      Ed448ph is the same but with PH being SHAKE256(x, 64) and phflag
100      being 1, i.e., the input is hashed before signing with Ed448 with a
101      hash constant modified.
102 
103      Value of context is set by signer and verifier (maximum of 255
104      octets; the default is empty string) and has to match octet by octet
105      for verification to be successful.
106 
107    Quoting from RFC 8032, Section 2:
108 
109      dom2(x, y)     The blank octet string when signing or verifying
110                     Ed25519.  Otherwise, the octet string: "SigEd25519 no
111                     Ed25519 collisions" || octet(x) || octet(OLEN(y)) ||
112                     y, where x is in range 0-255 and y is an octet string
113                     of at most 255 octets.  "SigEd25519 no Ed25519
114                     collisions" is in ASCII (32 octets).
115 
116      dom4(x, y)     The octet string "SigEd448" || octet(x) ||
117                     octet(OLEN(y)) || y, where x is in range 0-255 and y
118                     is an octet string of at most 255 octets.  "SigEd448"
119                     is in ASCII (8 octets).
120 
121    Note above that x is the pre-hash flag, and y is the context string.
122 */
123 
124 typedef struct {
125     OSSL_LIB_CTX *libctx;
126     ECX_KEY *key;
127 
128     /* The Algorithm Identifier of the signature algorithm */
129     unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
130     unsigned char *aid;
131     size_t  aid_len;
132 
133     /* id indicating the EdDSA instance */
134     int instance_id;
135 
136     unsigned int dom2_flag : 1;
137     unsigned int prehash_flag : 1;
138 
139     /* indicates that a non-empty context string is required, as in Ed25519ctx */
140     unsigned int context_string_flag : 1;
141 
142     unsigned char context_string[EDDSA_MAX_CONTEXT_STRING_LEN];
143     size_t context_string_len;
144 
145 } PROV_EDDSA_CTX;
146 
eddsa_newctx(void * provctx,const char * propq_unused)147 static void *eddsa_newctx(void *provctx, const char *propq_unused)
148 {
149     PROV_EDDSA_CTX *peddsactx;
150 
151     if (!ossl_prov_is_running())
152         return NULL;
153 
154     peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
155     if (peddsactx == NULL)
156         return NULL;
157 
158     peddsactx->libctx = PROV_LIBCTX_OF(provctx);
159 
160     return peddsactx;
161 }
162 
eddsa_digest_signverify_init(void * vpeddsactx,const char * mdname,void * vedkey,const OSSL_PARAM params[])163 static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
164                                         void *vedkey,
165                                         const OSSL_PARAM params[])
166 {
167     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
168     ECX_KEY *edkey = (ECX_KEY *)vedkey;
169     WPACKET pkt;
170     int ret;
171 
172     if (!ossl_prov_is_running())
173         return 0;
174 
175     if (mdname != NULL && mdname[0] != '\0') {
176         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
177         return 0;
178     }
179 
180     if (edkey == NULL) {
181         if (peddsactx->key != NULL)
182             return eddsa_set_ctx_params(peddsactx, params);
183         ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
184         return 0;
185     }
186 
187     if (!ossl_ecx_key_up_ref(edkey)) {
188         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
189         return 0;
190     }
191 
192     peddsactx->dom2_flag = 0;
193     peddsactx->prehash_flag = 0;
194     peddsactx->context_string_flag = 0;
195     peddsactx->context_string_len = 0;
196 
197     /*
198      * We do not care about DER writing errors.
199      * All it really means is that for some reason, there's no
200      * AlgorithmIdentifier to be had, but the operation itself is
201      * still valid, just as long as it's not used to construct
202      * anything that needs an AlgorithmIdentifier.
203      */
204     peddsactx->aid_len = 0;
205     ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
206     switch (edkey->type) {
207     case ECX_KEY_TYPE_ED25519:
208         ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
209         peddsactx->instance_id = ID_Ed25519;
210         break;
211     case ECX_KEY_TYPE_ED448:
212         ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
213         peddsactx->instance_id = ID_Ed448;
214         break;
215     default:
216         /* Should never happen */
217         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
218         ossl_ecx_key_free(edkey);
219         return 0;
220     }
221     if (ret && WPACKET_finish(&pkt)) {
222         WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
223         peddsactx->aid = WPACKET_get_curr(&pkt);
224     }
225     WPACKET_cleanup(&pkt);
226 
227     peddsactx->key = edkey;
228 
229     if (!eddsa_set_ctx_params(peddsactx, params))
230         return 0;
231 
232     return 1;
233 }
234 
ed25519_digest_sign(void * vpeddsactx,unsigned char * sigret,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)235 int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
236                         size_t *siglen, size_t sigsize,
237                         const unsigned char *tbs, size_t tbslen)
238 {
239     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
240     const ECX_KEY *edkey = peddsactx->key;
241     uint8_t md[EVP_MAX_MD_SIZE];
242     size_t mdlen;
243 
244     if (!ossl_prov_is_running())
245         return 0;
246 
247     if (sigret == NULL) {
248         *siglen = ED25519_SIGSIZE;
249         return 1;
250     }
251     if (sigsize < ED25519_SIGSIZE) {
252         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
253         return 0;
254     }
255     if (edkey->privkey == NULL) {
256         ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
257         return 0;
258     }
259 #ifdef S390X_EC_ASM
260     /* s390x_ed25519_digestsign() does not yet support dom2 or context-strings.
261        fall back to non-accelerated sign if those options are set. */
262     if (S390X_CAN_SIGN(ED25519)
263             && !peddsactx->dom2_flag
264             && !peddsactx->context_string_flag
265             && peddsactx->context_string_len == 0) {
266         if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
267             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
268             return 0;
269         }
270         *siglen = ED25519_SIGSIZE;
271         return 1;
272     }
273 #endif /* S390X_EC_ASM */
274 
275     if (peddsactx->prehash_flag) {
276         if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL, tbs, tbslen, md, &mdlen)
277                 || mdlen != EDDSA_PREHASH_OUTPUT_LEN)
278             return 0;
279         tbs = md;
280         tbslen = mdlen;
281     }
282 
283     if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
284             peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,
285             peddsactx->context_string, peddsactx->context_string_len,
286             peddsactx->libctx, NULL) == 0) {
287         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
288         return 0;
289     }
290     *siglen = ED25519_SIGSIZE;
291     return 1;
292 }
293 
294 /* EVP_Q_digest() does not allow variable output length for XOFs,
295    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)296 static int ed448_shake256(OSSL_LIB_CTX *libctx,
297                           const char *propq,
298                           const uint8_t *in, size_t inlen,
299                           uint8_t *out, size_t outlen)
300 {
301     int ret = 0;
302     EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();
303     EVP_MD *shake256 = EVP_MD_fetch(libctx, SN_shake256, propq);
304 
305     if (hash_ctx == NULL || shake256 == NULL)
306         goto err;
307 
308     if (!EVP_DigestInit_ex(hash_ctx, shake256, NULL)
309             || !EVP_DigestUpdate(hash_ctx, in, inlen)
310             || !EVP_DigestFinalXOF(hash_ctx, out, outlen))
311         goto err;
312 
313     ret = 1;
314 
315  err:
316     EVP_MD_CTX_free(hash_ctx);
317     EVP_MD_free(shake256);
318     return ret;
319 }
320 
ed448_digest_sign(void * vpeddsactx,unsigned char * sigret,size_t * siglen,size_t sigsize,const unsigned char * tbs,size_t tbslen)321 int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
322                       size_t *siglen, size_t sigsize,
323                       const unsigned char *tbs, size_t tbslen)
324 {
325     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
326     const ECX_KEY *edkey = peddsactx->key;
327     uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];
328     size_t mdlen = sizeof(md);
329 
330     if (!ossl_prov_is_running())
331         return 0;
332 
333     if (sigret == NULL) {
334         *siglen = ED448_SIGSIZE;
335         return 1;
336     }
337     if (sigsize < ED448_SIGSIZE) {
338         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
339         return 0;
340     }
341     if (edkey->privkey == NULL) {
342         ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
343         return 0;
344     }
345 #ifdef S390X_EC_ASM
346     /* s390x_ed448_digestsign() does not yet support context-strings or pre-hashing.
347        fall back to non-accelerated sign if a context-string or pre-hasing is provided. */
348     if (S390X_CAN_SIGN(ED448)
349             && peddsactx->context_string_len == 0
350             && peddsactx->prehash_flag == 0) {
351         if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
352             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
353             return 0;
354         }
355         *siglen = ED448_SIGSIZE;
356         return 1;
357     }
358 #endif /* S390X_EC_ASM */
359 
360     if (peddsactx->prehash_flag) {
361         if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))
362             return 0;
363         tbs = md;
364         tbslen = mdlen;
365     }
366 
367     if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen,
368                         edkey->pubkey, edkey->privkey,
369                         peddsactx->context_string, peddsactx->context_string_len,
370                         peddsactx->prehash_flag, edkey->propq) == 0) {
371         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
372         return 0;
373     }
374     *siglen = ED448_SIGSIZE;
375     return 1;
376 }
377 
ed25519_digest_verify(void * vpeddsactx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)378 int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
379                           size_t siglen, const unsigned char *tbs,
380                           size_t tbslen)
381 {
382     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
383     const ECX_KEY *edkey = peddsactx->key;
384     uint8_t md[EVP_MAX_MD_SIZE];
385     size_t mdlen;
386 
387     if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
388         return 0;
389 
390 #ifdef S390X_EC_ASM
391     /* s390x_ed25519_digestverify() does not yet support dom2 or context-strings.
392        fall back to non-accelerated verify if those options are set. */
393     if (S390X_CAN_SIGN(ED25519)
394             && !peddsactx->dom2_flag
395             && !peddsactx->context_string_flag
396             && peddsactx->context_string_len == 0) {
397         return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
398     }
399 #endif /* S390X_EC_ASM */
400 
401     if (peddsactx->prehash_flag) {
402         if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL, tbs, tbslen, md, &mdlen)
403                 || mdlen != EDDSA_PREHASH_OUTPUT_LEN)
404             return 0;
405         tbs = md;
406         tbslen = mdlen;
407     }
408 
409     return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
410                                peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,
411                                peddsactx->context_string, peddsactx->context_string_len,
412                                peddsactx->libctx, edkey->propq);
413 }
414 
ed448_digest_verify(void * vpeddsactx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)415 int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
416                         size_t siglen, const unsigned char *tbs,
417                         size_t tbslen)
418 {
419     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
420     const ECX_KEY *edkey = peddsactx->key;
421     uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];
422     size_t mdlen = sizeof(md);
423 
424     if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
425         return 0;
426 
427 #ifdef S390X_EC_ASM
428     /* s390x_ed448_digestverify() does not yet support context-strings or pre-hashing.
429        fall back to non-accelerated verify if a context-string or pre-hasing is provided. */
430     if (S390X_CAN_SIGN(ED448)
431             && peddsactx->context_string_len == 0
432             && peddsactx->prehash_flag == 0) {
433         return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
434     }
435 #endif /* S390X_EC_ASM */
436 
437     if (peddsactx->prehash_flag) {
438         if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))
439             return 0;
440         tbs = md;
441         tbslen = mdlen;
442     }
443 
444     return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
445                              peddsactx->context_string, peddsactx->context_string_len,
446                              peddsactx->prehash_flag, edkey->propq);
447 }
448 
eddsa_freectx(void * vpeddsactx)449 static void eddsa_freectx(void *vpeddsactx)
450 {
451     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
452 
453     ossl_ecx_key_free(peddsactx->key);
454 
455     OPENSSL_free(peddsactx);
456 }
457 
eddsa_dupctx(void * vpeddsactx)458 static void *eddsa_dupctx(void *vpeddsactx)
459 {
460     PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
461     PROV_EDDSA_CTX *dstctx;
462 
463     if (!ossl_prov_is_running())
464         return NULL;
465 
466     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
467     if (dstctx == NULL)
468         return NULL;
469 
470     *dstctx = *srcctx;
471     dstctx->key = NULL;
472 
473     if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
474         ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
475         goto err;
476     }
477     dstctx->key = srcctx->key;
478 
479     return dstctx;
480  err:
481     eddsa_freectx(dstctx);
482     return NULL;
483 }
484 
eddsa_get_ctx_params(void * vpeddsactx,OSSL_PARAM * params)485 static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
486 {
487     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
488     OSSL_PARAM *p;
489 
490     if (peddsactx == NULL)
491         return 0;
492 
493     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
494     if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
495                                                   peddsactx->aid_len))
496         return 0;
497 
498     return 1;
499 }
500 
501 static const OSSL_PARAM known_gettable_ctx_params[] = {
502     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
503     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),
504     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
505     OSSL_PARAM_END
506 };
507 
eddsa_gettable_ctx_params(ossl_unused void * vpeddsactx,ossl_unused void * provctx)508 static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
509                                                    ossl_unused void *provctx)
510 {
511     return known_gettable_ctx_params;
512 }
513 
eddsa_set_ctx_params(void * vpeddsactx,const OSSL_PARAM params[])514 static int eddsa_set_ctx_params(void *vpeddsactx, const OSSL_PARAM params[])
515 {
516     PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
517     const OSSL_PARAM *p;
518 
519     if (peddsactx == NULL)
520         return 0;
521     if (params == NULL)
522         return 1;
523 
524     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_INSTANCE);
525     if (p != NULL) {
526         char instance_name[OSSL_MAX_NAME_SIZE] = "";
527         char *pinstance_name = instance_name;
528 
529         if (!OSSL_PARAM_get_utf8_string(p, &pinstance_name, sizeof(instance_name)))
530             return 0;
531 
532         if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519) == 0) {
533             peddsactx->instance_id = ID_Ed25519;
534             if (peddsactx->key->type != ECX_KEY_TYPE_ED25519) return 0;
535             peddsactx->dom2_flag = 0;
536             peddsactx->prehash_flag = 0;
537             peddsactx->context_string_flag = 0;
538         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ctx) == 0) {
539             peddsactx->instance_id = ID_Ed25519ctx;
540             if (peddsactx->key->type != ECX_KEY_TYPE_ED25519) return 0;
541             peddsactx->dom2_flag = 1;
542             peddsactx->prehash_flag = 0;
543             peddsactx->context_string_flag = 1;
544         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ph) == 0) {
545             peddsactx->instance_id = ID_Ed25519ph;
546             if (peddsactx->key->type != ECX_KEY_TYPE_ED25519) return 0;
547             peddsactx->dom2_flag = 1;
548             peddsactx->prehash_flag = 1;
549             peddsactx->context_string_flag = 0;
550         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448) == 0) {
551             peddsactx->instance_id = ID_Ed448;
552             if (peddsactx->key->type != ECX_KEY_TYPE_ED448) return 0;
553             peddsactx->prehash_flag = 0;
554             peddsactx->context_string_flag = 0;
555         } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448ph) == 0) {
556             peddsactx->instance_id = ID_Ed448ph;
557             if (peddsactx->key->type != ECX_KEY_TYPE_ED448) return 0;
558             peddsactx->prehash_flag = 1;
559             peddsactx->context_string_flag = 0;
560         } else {
561             /* we did not recognize the instance */
562             return 0;
563         }
564 
565     }
566 
567     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);
568     if (p != NULL) {
569         void *vp_context_string = peddsactx->context_string;
570 
571         if (!OSSL_PARAM_get_octet_string(p, &vp_context_string, sizeof(peddsactx->context_string), &(peddsactx->context_string_len))) {
572             peddsactx->context_string_len = 0;
573             return 0;
574         }
575     }
576 
577     return 1;
578 }
579 
580 static const OSSL_PARAM settable_ctx_params[] = {
581     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),
582     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
583     OSSL_PARAM_END
584 };
585 
eddsa_settable_ctx_params(ossl_unused void * vpeddsactx,ossl_unused void * provctx)586 static const OSSL_PARAM *eddsa_settable_ctx_params(ossl_unused void *vpeddsactx,
587                                                    ossl_unused void *provctx)
588 {
589     return settable_ctx_params;
590 }
591 
592 const OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
593     { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
594     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
595       (void (*)(void))eddsa_digest_signverify_init },
596     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
597       (void (*)(void))ed25519_digest_sign },
598     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
599       (void (*)(void))eddsa_digest_signverify_init },
600     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
601       (void (*)(void))ed25519_digest_verify },
602     { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
603     { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
604     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
605     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
606       (void (*)(void))eddsa_gettable_ctx_params },
607     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))eddsa_set_ctx_params },
608     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
609       (void (*)(void))eddsa_settable_ctx_params },
610     OSSL_DISPATCH_END
611 };
612 
613 const OSSL_DISPATCH ossl_ed448_signature_functions[] = {
614     { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
615     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
616       (void (*)(void))eddsa_digest_signverify_init },
617     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
618       (void (*)(void))ed448_digest_sign },
619     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
620       (void (*)(void))eddsa_digest_signverify_init },
621     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
622       (void (*)(void))ed448_digest_verify },
623     { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
624     { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
625     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
626     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
627       (void (*)(void))eddsa_gettable_ctx_params },
628     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))eddsa_set_ctx_params },
629     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
630       (void (*)(void))eddsa_settable_ctx_params },
631     OSSL_DISPATCH_END
632 };
633 
634 #ifdef S390X_EC_ASM
635 
s390x_ed25519_digestsign(const ECX_KEY * edkey,unsigned char * sig,const unsigned char * tbs,size_t tbslen)636 static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
637                                     const unsigned char *tbs, size_t tbslen)
638 {
639     int rc;
640     union {
641         struct {
642             unsigned char sig[64];
643             unsigned char priv[32];
644         } ed25519;
645         unsigned long long buff[512];
646     } param;
647 
648     memset(&param, 0, sizeof(param));
649     memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
650 
651     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
652     OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
653     if (rc != 0)
654         return 0;
655 
656     s390x_flip_endian32(sig, param.ed25519.sig);
657     s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
658     return 1;
659 }
660 
s390x_ed448_digestsign(const ECX_KEY * edkey,unsigned char * sig,const unsigned char * tbs,size_t tbslen)661 static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
662                                   const unsigned char *tbs, size_t tbslen)
663 {
664     int rc;
665     union {
666         struct {
667             unsigned char sig[128];
668             unsigned char priv[64];
669         } ed448;
670         unsigned long long buff[512];
671     } param;
672 
673     memset(&param, 0, sizeof(param));
674     memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
675 
676     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
677     OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
678     if (rc != 0)
679         return 0;
680 
681     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
682     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
683     memcpy(sig, param.ed448.sig, 57);
684     memcpy(sig + 57, param.ed448.sig + 64, 57);
685     return 1;
686 }
687 
s390x_ed25519_digestverify(const ECX_KEY * edkey,const unsigned char * sig,const unsigned char * tbs,size_t tbslen)688 static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
689                                       const unsigned char *sig,
690                                       const unsigned char *tbs, size_t tbslen)
691 {
692     union {
693         struct {
694             unsigned char sig[64];
695             unsigned char pub[32];
696         } ed25519;
697         unsigned long long buff[512];
698     } param;
699 
700     memset(&param, 0, sizeof(param));
701     s390x_flip_endian32(param.ed25519.sig, sig);
702     s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
703     s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
704 
705     return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
706                       &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
707 }
708 
s390x_ed448_digestverify(const ECX_KEY * edkey,const unsigned char * sig,const unsigned char * tbs,size_t tbslen)709 static int s390x_ed448_digestverify(const ECX_KEY *edkey,
710                                     const unsigned char *sig,
711                                     const unsigned char *tbs,
712                                     size_t tbslen)
713 {
714     union {
715         struct {
716             unsigned char sig[128];
717             unsigned char pub[64];
718         } ed448;
719         unsigned long long buff[512];
720     } param;
721 
722     memset(&param, 0, sizeof(param));
723     memcpy(param.ed448.sig, sig, 57);
724     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
725     memcpy(param.ed448.sig + 64, sig + 57, 57);
726     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
727     memcpy(param.ed448.pub, edkey->pubkey, 57);
728     s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
729 
730     return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
731                       &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
732 }
733 
734 #endif /* S390X_EC_ASM */
735