Coverage Report

Created: 2025-12-04 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl33/providers/implementations/signature/eddsa_sig.c
Line
Count
Source
1
/*
2
 * Copyright 2020-2025 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
0
#define SN_Ed25519    "Ed25519"
56
0
#define SN_Ed25519ph  "Ed25519ph"
57
0
#define SN_Ed25519ctx "Ed25519ctx"
58
0
#define SN_Ed448      "Ed448"
59
0
#define SN_Ed448ph    "Ed448ph"
60
61
#define EDDSA_MAX_CONTEXT_STRING_LEN 255
62
0
#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
147
static void *eddsa_newctx(void *provctx, const char *propq_unused)
148
212
{
149
212
    PROV_EDDSA_CTX *peddsactx;
150
151
212
    if (!ossl_prov_is_running())
152
0
        return NULL;
153
154
212
    peddsactx = OPENSSL_zalloc(sizeof(PROV_EDDSA_CTX));
155
212
    if (peddsactx == NULL)
156
0
        return NULL;
157
158
212
    peddsactx->libctx = PROV_LIBCTX_OF(provctx);
159
160
212
    return peddsactx;
161
212
}
162
163
static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname,
164
                                        void *vedkey,
165
                                        const OSSL_PARAM params[])
166
52
{
167
52
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
168
52
    ECX_KEY *edkey = (ECX_KEY *)vedkey;
169
52
    WPACKET pkt;
170
52
    int ret;
171
172
52
    if (!ossl_prov_is_running())
173
0
        return 0;
174
175
52
    if (mdname != NULL && mdname[0] != '\0') {
176
0
        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
177
0
        return 0;
178
0
    }
179
180
52
    if (edkey == NULL) {
181
0
        if (peddsactx->key != NULL)
182
0
            return eddsa_set_ctx_params(peddsactx, params);
183
0
        ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
184
0
        return 0;
185
0
    }
186
187
52
    if (!ossl_ecx_key_up_ref(edkey)) {
188
0
        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
189
0
        return 0;
190
0
    }
191
192
52
    peddsactx->dom2_flag = 0;
193
52
    peddsactx->prehash_flag = 0;
194
52
    peddsactx->context_string_flag = 0;
195
52
    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
52
    peddsactx->aid_len = 0;
205
52
    ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf));
206
52
    switch (edkey->type) {
207
0
    case ECX_KEY_TYPE_ED25519:
208
0
        ret = ret && ossl_DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey);
209
0
        peddsactx->instance_id = ID_Ed25519;
210
0
        break;
211
52
    case ECX_KEY_TYPE_ED448:
212
52
        ret = ret && ossl_DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey);
213
52
        peddsactx->instance_id = ID_Ed448;
214
52
        break;
215
0
    default:
216
        /* Should never happen */
217
0
        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
218
0
        ossl_ecx_key_free(edkey);
219
0
        WPACKET_cleanup(&pkt);
220
0
        return 0;
221
52
    }
222
52
    if (ret && WPACKET_finish(&pkt)) {
223
52
        WPACKET_get_total_written(&pkt, &peddsactx->aid_len);
224
52
        peddsactx->aid = WPACKET_get_curr(&pkt);
225
52
    }
226
52
    WPACKET_cleanup(&pkt);
227
228
52
    peddsactx->key = edkey;
229
230
52
    if (!eddsa_set_ctx_params(peddsactx, params))
231
0
        return 0;
232
233
52
    return 1;
234
52
}
235
236
int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
237
                        size_t *siglen, size_t sigsize,
238
                        const unsigned char *tbs, size_t tbslen)
239
0
{
240
0
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
241
0
    const ECX_KEY *edkey = peddsactx->key;
242
0
    uint8_t md[EVP_MAX_MD_SIZE];
243
0
    size_t mdlen;
244
245
0
    if (!ossl_prov_is_running())
246
0
        return 0;
247
248
0
    if (sigret == NULL) {
249
0
        *siglen = ED25519_SIGSIZE;
250
0
        return 1;
251
0
    }
252
0
    if (sigsize < ED25519_SIGSIZE) {
253
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
254
0
        return 0;
255
0
    }
256
0
    if (edkey->privkey == NULL) {
257
0
        ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
258
0
        return 0;
259
0
    }
260
#ifdef S390X_EC_ASM
261
    /* s390x_ed25519_digestsign() does not yet support dom2 or context-strings.
262
       fall back to non-accelerated sign if those options are set. */
263
    if (S390X_CAN_SIGN(ED25519)
264
            && !peddsactx->dom2_flag
265
            && !peddsactx->context_string_flag
266
            && peddsactx->context_string_len == 0) {
267
        if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
268
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
269
            return 0;
270
        }
271
        *siglen = ED25519_SIGSIZE;
272
        return 1;
273
    }
274
#endif /* S390X_EC_ASM */
275
276
0
    if (peddsactx->prehash_flag) {
277
0
        if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL, tbs, tbslen, md, &mdlen)
278
0
                || mdlen != EDDSA_PREHASH_OUTPUT_LEN)
279
0
            return 0;
280
0
        tbs = md;
281
0
        tbslen = mdlen;
282
0
    }
283
284
0
    if (ossl_ed25519_sign(sigret, tbs, tbslen, edkey->pubkey, edkey->privkey,
285
0
            peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,
286
0
            peddsactx->context_string, peddsactx->context_string_len,
287
0
            peddsactx->libctx, NULL) == 0) {
288
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
289
0
        return 0;
290
0
    }
291
0
    *siglen = ED25519_SIGSIZE;
292
0
    return 1;
293
0
}
294
295
/* EVP_Q_digest() does not allow variable output length for XOFs,
296
   so we use this function */
297
static int ed448_shake256(OSSL_LIB_CTX *libctx,
298
                          const char *propq,
299
                          const uint8_t *in, size_t inlen,
300
                          uint8_t *out, size_t outlen)
301
0
{
302
0
    int ret = 0;
303
0
    EVP_MD_CTX *hash_ctx = EVP_MD_CTX_new();
304
0
    EVP_MD *shake256 = EVP_MD_fetch(libctx, SN_shake256, propq);
305
306
0
    if (hash_ctx == NULL || shake256 == NULL)
307
0
        goto err;
308
309
0
    if (!EVP_DigestInit_ex(hash_ctx, shake256, NULL)
310
0
            || !EVP_DigestUpdate(hash_ctx, in, inlen)
311
0
            || !EVP_DigestFinalXOF(hash_ctx, out, outlen))
312
0
        goto err;
313
314
0
    ret = 1;
315
316
0
 err:
317
0
    EVP_MD_CTX_free(hash_ctx);
318
0
    EVP_MD_free(shake256);
319
0
    return ret;
320
0
}
321
322
int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
323
                      size_t *siglen, size_t sigsize,
324
                      const unsigned char *tbs, size_t tbslen)
325
0
{
326
0
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
327
0
    const ECX_KEY *edkey = peddsactx->key;
328
0
    uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];
329
0
    size_t mdlen = sizeof(md);
330
331
0
    if (!ossl_prov_is_running())
332
0
        return 0;
333
334
0
    if (sigret == NULL) {
335
0
        *siglen = ED448_SIGSIZE;
336
0
        return 1;
337
0
    }
338
0
    if (sigsize < ED448_SIGSIZE) {
339
0
        ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
340
0
        return 0;
341
0
    }
342
0
    if (edkey->privkey == NULL) {
343
0
        ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
344
0
        return 0;
345
0
    }
346
#ifdef S390X_EC_ASM
347
    /* s390x_ed448_digestsign() does not yet support context-strings or pre-hashing.
348
       fall back to non-accelerated sign if a context-string or pre-hasing is provided. */
349
    if (S390X_CAN_SIGN(ED448)
350
            && peddsactx->context_string_len == 0
351
            && peddsactx->prehash_flag == 0) {
352
        if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
353
            ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
354
            return 0;
355
        }
356
        *siglen = ED448_SIGSIZE;
357
        return 1;
358
    }
359
#endif /* S390X_EC_ASM */
360
361
0
    if (peddsactx->prehash_flag) {
362
0
        if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))
363
0
            return 0;
364
0
        tbs = md;
365
0
        tbslen = mdlen;
366
0
    }
367
368
0
    if (ossl_ed448_sign(peddsactx->libctx, sigret, tbs, tbslen,
369
0
                        edkey->pubkey, edkey->privkey,
370
0
                        peddsactx->context_string, peddsactx->context_string_len,
371
0
                        peddsactx->prehash_flag, edkey->propq) == 0) {
372
0
        ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SIGN);
373
0
        return 0;
374
0
    }
375
0
    *siglen = ED448_SIGSIZE;
376
0
    return 1;
377
0
}
378
379
int ed25519_digest_verify(void *vpeddsactx, const unsigned char *sig,
380
                          size_t siglen, const unsigned char *tbs,
381
                          size_t tbslen)
382
0
{
383
0
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
384
0
    const ECX_KEY *edkey = peddsactx->key;
385
0
    uint8_t md[EVP_MAX_MD_SIZE];
386
0
    size_t mdlen;
387
388
0
    if (!ossl_prov_is_running() || siglen != ED25519_SIGSIZE)
389
0
        return 0;
390
391
#ifdef S390X_EC_ASM
392
    /* s390x_ed25519_digestverify() does not yet support dom2 or context-strings.
393
       fall back to non-accelerated verify if those options are set. */
394
    if (S390X_CAN_SIGN(ED25519)
395
            && !peddsactx->dom2_flag
396
            && !peddsactx->context_string_flag
397
            && peddsactx->context_string_len == 0) {
398
        return s390x_ed25519_digestverify(edkey, sig, tbs, tbslen);
399
    }
400
#endif /* S390X_EC_ASM */
401
402
0
    if (peddsactx->prehash_flag) {
403
0
        if (!EVP_Q_digest(peddsactx->libctx, SN_sha512, NULL, tbs, tbslen, md, &mdlen)
404
0
                || mdlen != EDDSA_PREHASH_OUTPUT_LEN)
405
0
            return 0;
406
0
        tbs = md;
407
0
        tbslen = mdlen;
408
0
    }
409
410
0
    return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
411
0
                               peddsactx->dom2_flag, peddsactx->prehash_flag, peddsactx->context_string_flag,
412
0
                               peddsactx->context_string, peddsactx->context_string_len,
413
0
                               peddsactx->libctx, edkey->propq);
414
0
}
415
416
int ed448_digest_verify(void *vpeddsactx, const unsigned char *sig,
417
                        size_t siglen, const unsigned char *tbs,
418
                        size_t tbslen)
419
52
{
420
52
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
421
52
    const ECX_KEY *edkey = peddsactx->key;
422
52
    uint8_t md[EDDSA_PREHASH_OUTPUT_LEN];
423
52
    size_t mdlen = sizeof(md);
424
425
52
    if (!ossl_prov_is_running() || siglen != ED448_SIGSIZE)
426
5
        return 0;
427
428
#ifdef S390X_EC_ASM
429
    /* s390x_ed448_digestverify() does not yet support context-strings or pre-hashing.
430
       fall back to non-accelerated verify if a context-string or pre-hasing is provided. */
431
    if (S390X_CAN_SIGN(ED448)
432
            && peddsactx->context_string_len == 0
433
            && peddsactx->prehash_flag == 0) {
434
        return s390x_ed448_digestverify(edkey, sig, tbs, tbslen);
435
    }
436
#endif /* S390X_EC_ASM */
437
438
47
    if (peddsactx->prehash_flag) {
439
0
        if (!ed448_shake256(peddsactx->libctx, NULL, tbs, tbslen, md, mdlen))
440
0
            return 0;
441
0
        tbs = md;
442
0
        tbslen = mdlen;
443
0
    }
444
445
47
    return ossl_ed448_verify(peddsactx->libctx, tbs, tbslen, sig, edkey->pubkey,
446
47
                             peddsactx->context_string, peddsactx->context_string_len,
447
47
                             peddsactx->prehash_flag, edkey->propq);
448
47
}
449
450
static void eddsa_freectx(void *vpeddsactx)
451
212
{
452
212
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
453
454
212
    ossl_ecx_key_free(peddsactx->key);
455
456
212
    OPENSSL_free(peddsactx);
457
212
}
458
459
static void *eddsa_dupctx(void *vpeddsactx)
460
0
{
461
0
    PROV_EDDSA_CTX *srcctx = (PROV_EDDSA_CTX *)vpeddsactx;
462
0
    PROV_EDDSA_CTX *dstctx;
463
464
0
    if (!ossl_prov_is_running())
465
0
        return NULL;
466
467
0
    dstctx = OPENSSL_zalloc(sizeof(*srcctx));
468
0
    if (dstctx == NULL)
469
0
        return NULL;
470
471
0
    *dstctx = *srcctx;
472
0
    dstctx->key = NULL;
473
474
0
    if (srcctx->key != NULL && !ossl_ecx_key_up_ref(srcctx->key)) {
475
0
        ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
476
0
        goto err;
477
0
    }
478
0
    dstctx->key = srcctx->key;
479
480
0
    return dstctx;
481
0
 err:
482
0
    eddsa_freectx(dstctx);
483
0
    return NULL;
484
0
}
485
486
static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params)
487
0
{
488
0
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
489
0
    OSSL_PARAM *p;
490
491
0
    if (peddsactx == NULL)
492
0
        return 0;
493
494
0
    p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
495
0
    if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid,
496
0
                                                  peddsactx->aid_len))
497
0
        return 0;
498
499
0
    return 1;
500
0
}
501
502
static const OSSL_PARAM known_gettable_ctx_params[] = {
503
    OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
504
    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),
505
    OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
506
    OSSL_PARAM_END
507
};
508
509
static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *vpeddsactx,
510
                                                   ossl_unused void *provctx)
511
0
{
512
0
    return known_gettable_ctx_params;
513
0
}
514
515
static int eddsa_set_ctx_params(void *vpeddsactx, const OSSL_PARAM params[])
516
52
{
517
52
    PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx;
518
52
    const OSSL_PARAM *p;
519
520
52
    if (peddsactx == NULL)
521
0
        return 0;
522
52
    if (params == NULL)
523
52
        return 1;
524
525
0
    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_INSTANCE);
526
0
    if (p != NULL) {
527
0
        char instance_name[OSSL_MAX_NAME_SIZE] = "";
528
0
        char *pinstance_name = instance_name;
529
530
0
        if (!OSSL_PARAM_get_utf8_string(p, &pinstance_name, sizeof(instance_name)))
531
0
            return 0;
532
533
0
        if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519) == 0) {
534
0
            peddsactx->instance_id = ID_Ed25519;
535
0
            if (peddsactx->key->type != ECX_KEY_TYPE_ED25519) return 0;
536
0
            peddsactx->dom2_flag = 0;
537
0
            peddsactx->prehash_flag = 0;
538
0
            peddsactx->context_string_flag = 0;
539
0
#ifndef FIPS_MODULE
540
0
        } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ctx) == 0) {
541
0
            peddsactx->instance_id = ID_Ed25519ctx;
542
0
            if (peddsactx->key->type != ECX_KEY_TYPE_ED25519) return 0;
543
0
            peddsactx->dom2_flag = 1;
544
0
            peddsactx->prehash_flag = 0;
545
0
            peddsactx->context_string_flag = 1;
546
0
#endif
547
0
        } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed25519ph) == 0) {
548
0
            peddsactx->instance_id = ID_Ed25519ph;
549
0
            if (peddsactx->key->type != ECX_KEY_TYPE_ED25519) return 0;
550
0
            peddsactx->dom2_flag = 1;
551
0
            peddsactx->prehash_flag = 1;
552
0
            peddsactx->context_string_flag = 0;
553
0
        } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448) == 0) {
554
0
            peddsactx->instance_id = ID_Ed448;
555
0
            if (peddsactx->key->type != ECX_KEY_TYPE_ED448) return 0;
556
0
            peddsactx->prehash_flag = 0;
557
0
            peddsactx->context_string_flag = 0;
558
0
        } else if (OPENSSL_strcasecmp(pinstance_name, SN_Ed448ph) == 0) {
559
0
            peddsactx->instance_id = ID_Ed448ph;
560
0
            if (peddsactx->key->type != ECX_KEY_TYPE_ED448) return 0;
561
0
            peddsactx->prehash_flag = 1;
562
0
            peddsactx->context_string_flag = 0;
563
0
        } else {
564
            /* we did not recognize the instance */
565
0
            return 0;
566
0
        }
567
568
0
    }
569
570
0
    p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_CONTEXT_STRING);
571
0
    if (p != NULL) {
572
0
        void *vp_context_string = peddsactx->context_string;
573
574
0
        if (!OSSL_PARAM_get_octet_string(p, &vp_context_string, sizeof(peddsactx->context_string), &(peddsactx->context_string_len))) {
575
0
            peddsactx->context_string_len = 0;
576
0
            return 0;
577
0
        }
578
0
    }
579
580
0
    return 1;
581
0
}
582
583
static const OSSL_PARAM settable_ctx_params[] = {
584
    OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_INSTANCE, NULL, 0),
585
    OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING, NULL, 0),
586
    OSSL_PARAM_END
587
};
588
589
static const OSSL_PARAM *eddsa_settable_ctx_params(ossl_unused void *vpeddsactx,
590
                                                   ossl_unused void *provctx)
591
7
{
592
7
    return settable_ctx_params;
593
7
}
594
595
const OSSL_DISPATCH ossl_ed25519_signature_functions[] = {
596
    { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
597
    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
598
      (void (*)(void))eddsa_digest_signverify_init },
599
    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
600
      (void (*)(void))ed25519_digest_sign },
601
    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
602
      (void (*)(void))eddsa_digest_signverify_init },
603
    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
604
      (void (*)(void))ed25519_digest_verify },
605
    { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
606
    { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
607
    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
608
    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
609
      (void (*)(void))eddsa_gettable_ctx_params },
610
    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))eddsa_set_ctx_params },
611
    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
612
      (void (*)(void))eddsa_settable_ctx_params },
613
    OSSL_DISPATCH_END
614
};
615
616
const OSSL_DISPATCH ossl_ed448_signature_functions[] = {
617
    { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx },
618
    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
619
      (void (*)(void))eddsa_digest_signverify_init },
620
    { OSSL_FUNC_SIGNATURE_DIGEST_SIGN,
621
      (void (*)(void))ed448_digest_sign },
622
    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
623
      (void (*)(void))eddsa_digest_signverify_init },
624
    { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,
625
      (void (*)(void))ed448_digest_verify },
626
    { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx },
627
    { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx },
628
    { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params },
629
    { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
630
      (void (*)(void))eddsa_gettable_ctx_params },
631
    { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))eddsa_set_ctx_params },
632
    { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
633
      (void (*)(void))eddsa_settable_ctx_params },
634
    OSSL_DISPATCH_END
635
};
636
637
#ifdef S390X_EC_ASM
638
639
static int s390x_ed25519_digestsign(const ECX_KEY *edkey, unsigned char *sig,
640
                                    const unsigned char *tbs, size_t tbslen)
641
{
642
    int rc;
643
    union {
644
        struct {
645
            unsigned char sig[64];
646
            unsigned char priv[32];
647
        } ed25519;
648
        unsigned long long buff[512];
649
    } param;
650
651
    memset(&param, 0, sizeof(param));
652
    memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
653
654
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
655
    OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
656
    if (rc != 0)
657
        return 0;
658
659
    s390x_flip_endian32(sig, param.ed25519.sig);
660
    s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
661
    return 1;
662
}
663
664
static int s390x_ed448_digestsign(const ECX_KEY *edkey, unsigned char *sig,
665
                                  const unsigned char *tbs, size_t tbslen)
666
{
667
    int rc;
668
    union {
669
        struct {
670
            unsigned char sig[128];
671
            unsigned char priv[64];
672
        } ed448;
673
        unsigned long long buff[512];
674
    } param;
675
676
    memset(&param, 0, sizeof(param));
677
    memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
678
679
    rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
680
    OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
681
    if (rc != 0)
682
        return 0;
683
684
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
685
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
686
    memcpy(sig, param.ed448.sig, 57);
687
    memcpy(sig + 57, param.ed448.sig + 64, 57);
688
    return 1;
689
}
690
691
static int s390x_ed25519_digestverify(const ECX_KEY *edkey,
692
                                      const unsigned char *sig,
693
                                      const unsigned char *tbs, size_t tbslen)
694
{
695
    union {
696
        struct {
697
            unsigned char sig[64];
698
            unsigned char pub[32];
699
        } ed25519;
700
        unsigned long long buff[512];
701
    } param;
702
703
    memset(&param, 0, sizeof(param));
704
    s390x_flip_endian32(param.ed25519.sig, sig);
705
    s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
706
    s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
707
708
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
709
                      &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
710
}
711
712
static int s390x_ed448_digestverify(const ECX_KEY *edkey,
713
                                    const unsigned char *sig,
714
                                    const unsigned char *tbs,
715
                                    size_t tbslen)
716
{
717
    union {
718
        struct {
719
            unsigned char sig[128];
720
            unsigned char pub[64];
721
        } ed448;
722
        unsigned long long buff[512];
723
    } param;
724
725
    memset(&param, 0, sizeof(param));
726
    memcpy(param.ed448.sig, sig, 57);
727
    s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
728
    memcpy(param.ed448.sig + 64, sig + 57, 57);
729
    s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
730
    memcpy(param.ed448.pub, edkey->pubkey, 57);
731
    s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
732
733
    return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
734
                      &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
735
}
736
737
#endif /* S390X_EC_ASM */