Coverage Report

Created: 2025-12-31 06:58

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