Coverage Report

Created: 2026-06-18 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/providers/implementations/keymgmt/ecx_kmgmt.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 <assert.h>
11
#include <string.h>
12
#include <openssl/core_dispatch.h>
13
#include <openssl/core_names.h>
14
#include <openssl/params.h>
15
#include <openssl/err.h>
16
#include <openssl/proverr.h>
17
#include <openssl/evp.h>
18
#include <openssl/rand.h>
19
#include <openssl/self_test.h>
20
#include "internal/fips.h"
21
#include "internal/param_build_set.h"
22
#include <openssl/param_build.h>
23
#include "crypto/ecx.h"
24
#include "prov/implementations.h"
25
#include "prov/providercommon.h"
26
#include "prov/provider_ctx.h"
27
#include "prov/ecx.h"
28
#include "prov/securitycheck.h"
29
#ifdef S390X_EC_ASM
30
#include "arch/s390x_arch.h"
31
#include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
32
#endif
33
34
static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
35
static OSSL_FUNC_keymgmt_new_fn x448_new_key;
36
static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
37
static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
38
static OSSL_FUNC_keymgmt_free_fn ecx_free_key;
39
static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
40
static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
41
static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
42
static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
43
static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
44
static OSSL_FUNC_keymgmt_gen_fn x448_gen;
45
static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
46
static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
47
static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
48
static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
49
static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
50
static OSSL_FUNC_keymgmt_load_fn ecx_load;
51
static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
52
static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
53
static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
54
static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
55
static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
56
static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
57
static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
58
static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
59
static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
60
static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
61
static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
62
static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
63
static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
64
static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
65
static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
66
static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
67
static OSSL_FUNC_keymgmt_has_fn ecx_has;
68
static OSSL_FUNC_keymgmt_match_fn ecx_match;
69
static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
70
static OSSL_FUNC_keymgmt_validate_fn x448_validate;
71
static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
72
static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
73
static OSSL_FUNC_keymgmt_import_fn ecx_import;
74
static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
75
static OSSL_FUNC_keymgmt_export_fn ecx_export;
76
static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
77
static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
78
79
0
#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
80
81
struct ecx_gen_ctx {
82
    OSSL_LIB_CTX *libctx;
83
    char *propq;
84
    ECX_KEY_TYPE type;
85
    int selection;
86
    unsigned char *dhkem_ikm;
87
    size_t dhkem_ikmlen;
88
};
89
90
#ifdef S390X_EC_ASM
91
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
92
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
93
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
94
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
95
#endif
96
97
#ifdef FIPS_MODULE
98
static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test);
99
#endif /* FIPS_MODULE */
100
101
static ossl_inline int ecx_key_type_is_ed(ECX_KEY_TYPE type)
102
0
{
103
0
    return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448;
104
0
}
105
106
static void *x25519_new_key(void *provctx)
107
0
{
108
0
    if (!ossl_prov_is_running())
109
0
        return 0;
110
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
111
0
        NULL);
112
0
}
113
114
static void *x448_new_key(void *provctx)
115
0
{
116
0
    if (!ossl_prov_is_running())
117
0
        return 0;
118
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
119
0
        NULL);
120
0
}
121
122
static void *ed25519_new_key(void *provctx)
123
0
{
124
0
    if (!ossl_prov_is_running())
125
0
        return 0;
126
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
127
0
        NULL);
128
0
}
129
130
static void *ed448_new_key(void *provctx)
131
0
{
132
0
    if (!ossl_prov_is_running())
133
0
        return 0;
134
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
135
0
        NULL);
136
0
}
137
138
static int ecx_has(const void *keydata, int selection)
139
0
{
140
0
    const ECX_KEY *key = keydata;
141
0
    int ok = 0;
142
143
0
    if (ossl_prov_is_running() && key != NULL) {
144
        /*
145
         * ECX keys always have all the parameters they need (i.e. none).
146
         * Therefore we always return with 1, if asked about parameters.
147
         */
148
0
        ok = 1;
149
150
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
151
0
            ok = ok && key->haspubkey;
152
153
0
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
154
0
            ok = ok && key->privkey != NULL;
155
0
    }
156
0
    return ok;
157
0
}
158
159
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
160
0
{
161
0
    const ECX_KEY *key1 = keydata1;
162
0
    const ECX_KEY *key2 = keydata2;
163
0
    int ok = 1;
164
165
0
    if (!ossl_prov_is_running())
166
0
        return 0;
167
168
0
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
169
0
        ok = ok && key1->type == key2->type;
170
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
171
0
        int key_checked = 0;
172
173
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
174
0
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
175
0
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
176
0
            size_t pal = key1->keylen;
177
0
            size_t pbl = key2->keylen;
178
179
0
            if (pa != NULL && pb != NULL) {
180
0
                ok = ok
181
0
                    && key1->type == key2->type
182
0
                    && pal == pbl
183
0
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
184
0
                key_checked = 1;
185
0
            }
186
0
        }
187
0
        if (!key_checked
188
0
            && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
189
0
            const unsigned char *pa = key1->privkey;
190
0
            const unsigned char *pb = key2->privkey;
191
0
            size_t pal = key1->keylen;
192
0
            size_t pbl = key2->keylen;
193
194
0
            if (pa != NULL && pb != NULL) {
195
0
                ok = ok
196
0
                    && key1->type == key2->type
197
0
                    && pal == pbl
198
0
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
199
0
                key_checked = 1;
200
0
            }
201
0
        }
202
0
        ok = ok && key_checked;
203
0
    }
204
0
    return ok;
205
0
}
206
207
struct ecx_ed_common_get_params_st {
208
    OSSL_PARAM *bits;
209
    OSSL_PARAM *secbits;
210
    OSSL_PARAM *size;
211
    OSSL_PARAM *seccat;
212
    OSSL_PARAM *pub;
213
    OSSL_PARAM *priv;
214
    OSSL_PARAM *encpub; /* ECX only */
215
    OSSL_PARAM *ind; /* ECX only */
216
    OSSL_PARAM *digest; /* Ed only */
217
};
218
219
#define ecx_get_params_st ecx_ed_common_get_params_st
220
#define ed_get_params_st ecx_ed_common_get_params_st
221
222
#include "providers/implementations/keymgmt/ecx_kmgmt.inc"
223
224
static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
225
0
{
226
0
    ECX_KEY *key = keydata;
227
0
    int ok = 1;
228
0
    int include_private;
229
0
    struct ecx_imexport_types_st p;
230
231
0
    if (!ossl_prov_is_running()
232
0
        || key == NULL
233
0
        || !ecx_imexport_types_decoder(params, &p))
234
0
        return 0;
235
236
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
237
0
        return 0;
238
239
0
    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
240
0
    ok = ok && ossl_ecx_key_fromdata(key, p.pub, p.priv, include_private);
241
242
0
    return ok;
243
0
}
244
245
static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
246
    OSSL_PARAM *pub, OSSL_PARAM *priv, int include_private)
247
0
{
248
0
    if (key == NULL)
249
0
        return 0;
250
251
0
    if (!ossl_param_build_set_octet_string(tmpl, pub,
252
0
            OSSL_PKEY_PARAM_PUB_KEY,
253
0
            key->pubkey, key->keylen))
254
0
        return 0;
255
256
0
    if (include_private
257
0
        && key->privkey != NULL
258
0
        && !ossl_param_build_set_octet_string(tmpl, priv,
259
0
            OSSL_PKEY_PARAM_PRIV_KEY,
260
0
            key->privkey, key->keylen))
261
0
        return 0;
262
263
0
    return 1;
264
0
}
265
266
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
267
    void *cbarg)
268
0
{
269
0
    ECX_KEY *key = keydata;
270
0
    OSSL_PARAM_BLD *tmpl;
271
0
    OSSL_PARAM *params = NULL;
272
0
    int ret = 0;
273
274
0
    if (!ossl_prov_is_running() || key == NULL)
275
0
        return 0;
276
277
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
278
0
        return 0;
279
280
0
    tmpl = OSSL_PARAM_BLD_new();
281
0
    if (tmpl == NULL)
282
0
        return 0;
283
284
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
285
0
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
286
287
0
        if (!key_to_params(key, tmpl, NULL, NULL, include_private))
288
0
            goto err;
289
0
    }
290
291
0
    params = OSSL_PARAM_BLD_to_param(tmpl);
292
0
    if (params == NULL)
293
0
        goto err;
294
295
0
    ret = param_cb(params, cbarg);
296
0
    OSSL_PARAM_clear_free(params);
297
0
err:
298
0
    OSSL_PARAM_BLD_free(tmpl);
299
0
    return ret;
300
0
}
301
302
static const OSSL_PARAM *ecx_imexport_types(int selection)
303
0
{
304
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
305
0
        return ecx_imexport_types_list;
306
0
    return NULL;
307
0
}
308
309
/* This getter is shared by ED25519, ED448, X25519 and X448 */
310
static int ecx_ed_common_get_params(void *key,
311
    const struct ecx_ed_common_get_params_st *p,
312
    int bits, int secbits, int size)
313
0
{
314
0
    ECX_KEY *ecx = key;
315
316
0
    if (p->bits != NULL && !OSSL_PARAM_set_int(p->bits, bits))
317
0
        return 0;
318
0
    if (p->secbits != NULL && !OSSL_PARAM_set_int(p->secbits, secbits))
319
0
        return 0;
320
0
    if (p->size != NULL && !OSSL_PARAM_set_int(p->size, size))
321
0
        return 0;
322
0
    if (p->seccat != NULL && !OSSL_PARAM_set_int(p->seccat, 0))
323
0
        return 0;
324
0
    return key_to_params(ecx, NULL, p->pub, p->priv, 1);
325
0
}
326
327
/* X25519/X448 getter */
328
static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
329
    int size)
330
0
{
331
0
    ECX_KEY *ecx = key;
332
0
    struct ecx_ed_common_get_params_st p;
333
334
0
    if (key == NULL || !ecx_get_params_decoder(params, &p))
335
0
        return 0;
336
337
0
    if (p.encpub != NULL
338
0
        && !OSSL_PARAM_set_octet_string(p.encpub, ecx->pubkey, ecx->keylen))
339
0
        return 0;
340
#ifdef FIPS_MODULE
341
    {
342
        /* Currently X25519 and X448 are not approved */
343
        int approved = 0;
344
345
        if (p.ind != NULL && !OSSL_PARAM_set_int(p.ind, approved))
346
            return 0;
347
    }
348
#endif
349
350
0
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
351
0
}
352
353
/* ED25519/ED448 getter */
354
static int ed_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
355
    int size)
356
0
{
357
0
    struct ecx_ed_common_get_params_st p;
358
359
0
    if (key == NULL || !ed_get_params_decoder(params, &p))
360
0
        return 0;
361
0
    if (p.digest != NULL && !OSSL_PARAM_set_utf8_string(p.digest, ""))
362
0
        return 0;
363
0
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
364
0
}
365
366
static int x25519_get_params(void *key, OSSL_PARAM params[])
367
0
{
368
0
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
369
0
        X25519_KEYLEN);
370
0
}
371
372
static int x448_get_params(void *key, OSSL_PARAM params[])
373
0
{
374
0
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
375
0
        X448_KEYLEN);
376
0
}
377
378
static int ed25519_get_params(void *key, OSSL_PARAM params[])
379
0
{
380
0
    return ed_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
381
0
        ED25519_SIGSIZE);
382
0
}
383
static int ed448_get_params(void *key, OSSL_PARAM params[])
384
0
{
385
0
    return ed_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
386
0
        ED448_SIGSIZE);
387
0
}
388
389
static const OSSL_PARAM *x25519_gettable_params(void *provctx)
390
0
{
391
0
    return ecx_get_params_list;
392
0
}
393
394
static const OSSL_PARAM *x448_gettable_params(void *provctx)
395
0
{
396
0
    return ecx_get_params_list;
397
0
}
398
399
static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
400
0
{
401
0
    return ed_get_params_list;
402
0
}
403
404
static const OSSL_PARAM *ed448_gettable_params(void *provctx)
405
0
{
406
0
    return ed_get_params_list;
407
0
}
408
409
static int set_property_query(ECX_KEY *ecxkey, const char *propq)
410
0
{
411
0
    OPENSSL_free(ecxkey->propq);
412
0
    ecxkey->propq = NULL;
413
0
    if (propq != NULL) {
414
0
        ecxkey->propq = OPENSSL_strdup(propq);
415
0
        if (ecxkey->propq == NULL)
416
0
            return 0;
417
0
    }
418
0
    return 1;
419
0
}
420
421
static int ecx_set_params(void *key, const OSSL_PARAM params[])
422
0
{
423
0
    ECX_KEY *ecxkey = key;
424
0
    struct ecx_set_params_st p;
425
426
0
    if (key == NULL || !ecx_set_params_decoder(params, &p))
427
0
        return 0;
428
429
0
    if (p.pub != NULL) {
430
0
        void *buf = ecxkey->pubkey;
431
432
0
        if (p.pub->data_size != ecxkey->keylen
433
0
            || !OSSL_PARAM_get_octet_string(p.pub, &buf, sizeof(ecxkey->pubkey),
434
0
                NULL))
435
0
            return 0;
436
0
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
437
0
        ecxkey->privkey = NULL;
438
0
        ecxkey->haspubkey = 1;
439
0
    }
440
441
0
    if (p.propq != NULL) {
442
0
        if (p.propq->data_type != OSSL_PARAM_UTF8_STRING
443
0
            || !set_property_query(ecxkey, p.propq->data))
444
0
            return 0;
445
0
    }
446
447
0
    return 1;
448
0
}
449
450
static int x25519_set_params(void *key, const OSSL_PARAM params[])
451
0
{
452
0
    return ecx_set_params(key, params);
453
0
}
454
455
static int x448_set_params(void *key, const OSSL_PARAM params[])
456
0
{
457
0
    return ecx_set_params(key, params);
458
0
}
459
460
static int ed25519_set_params(void *key, const OSSL_PARAM params[])
461
0
{
462
0
    return 1;
463
0
}
464
465
static int ed448_set_params(void *key, const OSSL_PARAM params[])
466
0
{
467
0
    return 1;
468
0
}
469
470
static const OSSL_PARAM ed_settable_params[] = {
471
    OSSL_PARAM_END
472
};
473
474
static const OSSL_PARAM *x25519_settable_params(void *provctx)
475
0
{
476
0
    return ecx_set_params_list;
477
0
}
478
479
static const OSSL_PARAM *x448_settable_params(void *provctx)
480
0
{
481
0
    return ecx_set_params_list;
482
0
}
483
484
static const OSSL_PARAM *ed25519_settable_params(void *provctx)
485
0
{
486
0
    return ed_settable_params;
487
0
}
488
489
static const OSSL_PARAM *ed448_settable_params(void *provctx)
490
0
{
491
0
    return ed_settable_params;
492
0
}
493
494
static void *ecx_gen_init(void *provctx, int selection,
495
    const OSSL_PARAM params[], ECX_KEY_TYPE type,
496
    const char *algdesc)
497
0
{
498
0
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
499
0
    struct ecx_gen_ctx *gctx = NULL;
500
501
0
    if (!ossl_prov_is_running())
502
0
        return NULL;
503
504
0
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
505
0
        gctx->libctx = libctx;
506
0
        gctx->type = type;
507
0
        gctx->selection = selection;
508
#ifdef FIPS_MODULE
509
        /* X25519/X448 are not FIPS approved, (ED25519/ED448 are approved) */
510
        if (algdesc != NULL
511
            && !ossl_FIPS_IND_callback(libctx, algdesc, "KeyGen Init")) {
512
            OPENSSL_free(gctx);
513
            return NULL;
514
        }
515
#endif
516
0
    } else {
517
0
        return NULL;
518
0
    }
519
0
    if (!ecx_gen_set_params(gctx, params)) {
520
0
        ecx_gen_cleanup(gctx);
521
0
        gctx = NULL;
522
0
    }
523
0
    return gctx;
524
0
}
525
526
static void *x25519_gen_init(void *provctx, int selection,
527
    const OSSL_PARAM params[])
528
0
{
529
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
530
0
}
531
532
static void *x448_gen_init(void *provctx, int selection,
533
    const OSSL_PARAM params[])
534
0
{
535
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
536
0
}
537
538
static void *ed25519_gen_init(void *provctx, int selection,
539
    const OSSL_PARAM params[])
540
0
{
541
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519, NULL);
542
0
}
543
544
static void *ed448_gen_init(void *provctx, int selection,
545
    const OSSL_PARAM params[])
546
0
{
547
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448, NULL);
548
0
}
549
550
static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
551
0
{
552
0
    struct ecx_gen_ctx *gctx = genctx;
553
0
    struct ecx_gen_set_params_st p;
554
555
0
    if (gctx == NULL || !ecx_gen_set_params_decoder(params, &p))
556
0
        return 0;
557
558
0
    if (p.group != NULL) {
559
0
        const char *groupname = NULL;
560
561
        /*
562
         * We optionally allow setting a group name - but each algorithm only
563
         * support one such name, so all we do is verify that it is the one we
564
         * expected.
565
         */
566
0
        switch (gctx->type) {
567
0
        case ECX_KEY_TYPE_X25519:
568
0
            groupname = "x25519";
569
0
            break;
570
0
        case ECX_KEY_TYPE_X448:
571
0
            groupname = "x448";
572
0
            break;
573
0
        default:
574
            /* We only support this for key exchange at the moment */
575
0
            break;
576
0
        }
577
0
        if (p.group->data_type != OSSL_PARAM_UTF8_STRING
578
0
            || groupname == NULL
579
0
            || OPENSSL_strcasecmp(p.group->data, groupname) != 0) {
580
0
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
581
0
            return 0;
582
0
        }
583
0
    }
584
585
0
    if (p.kdfpropq != NULL) {
586
0
        if (p.kdfpropq->data_type != OSSL_PARAM_UTF8_STRING)
587
0
            return 0;
588
0
        OPENSSL_free(gctx->propq);
589
0
        gctx->propq = OPENSSL_strdup(p.kdfpropq->data);
590
0
        if (gctx->propq == NULL)
591
0
            return 0;
592
0
    }
593
594
0
    if (p.ikm != NULL) {
595
0
        if (p.ikm->data_size != 0 && p.ikm->data != NULL) {
596
0
            OPENSSL_free(gctx->dhkem_ikm);
597
0
            gctx->dhkem_ikm = NULL;
598
0
            if (!OSSL_PARAM_get_octet_string(p.ikm, (void **)&gctx->dhkem_ikm, 0,
599
0
                    &gctx->dhkem_ikmlen))
600
0
                return 0;
601
0
        }
602
0
    }
603
604
0
    return 1;
605
0
}
606
607
static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
608
    ossl_unused void *provctx)
609
0
{
610
0
    return ecx_gen_set_params_list;
611
0
}
612
613
#ifdef FIPS_MODULE
614
/*
615
 * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1
616
 * Perform a pairwise test for EDDSA by signing and verifying signature.
617
 *
618
 * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST
619
 * instance.
620
 */
621
static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test)
622
{
623
    int ret = 0;
624
    OSSL_SELF_TEST *st = NULL;
625
    OSSL_CALLBACK *cb = NULL;
626
    void *cbarg = NULL;
627
628
    unsigned char msg[16] = { 0 };
629
    size_t msg_len = sizeof(msg);
630
    unsigned char sig[ED448_SIGSIZE] = { 0 };
631
632
    int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0;
633
    int operation_result = 0;
634
635
    /*
636
     * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
637
     * is NULL.
638
     */
639
    if (self_test) {
640
        OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg);
641
642
        st = OSSL_SELF_TEST_new(cb, cbarg);
643
        if (st == NULL)
644
            return 0;
645
    }
646
647
    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
648
        OSSL_SELF_TEST_DESC_PCT_EDDSA);
649
650
    if (is_ed25519)
651
        operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey,
652
            ecx->privkey, 0, 0, 0, NULL, 0,
653
            ecx->libctx, ecx->propq);
654
    else
655
        operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len,
656
            ecx->pubkey, ecx->privkey, NULL, 0,
657
            0, ecx->propq);
658
    if (operation_result != 1)
659
        goto err;
660
661
    OSSL_SELF_TEST_oncorrupt_byte(st, sig);
662
663
    if (is_ed25519)
664
        operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey,
665
            0, 0, 0, NULL, 0, ecx->libctx,
666
            ecx->propq);
667
    else
668
        operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig,
669
            ecx->pubkey, NULL, 0, 0, ecx->propq);
670
    if (operation_result != 1)
671
        goto err;
672
673
    ret = 1;
674
err:
675
    OSSL_SELF_TEST_onend(st, ret);
676
    OSSL_SELF_TEST_free(st);
677
    return ret;
678
}
679
#endif
680
681
static void *ecx_gen(struct ecx_gen_ctx *gctx)
682
0
{
683
0
    ECX_KEY *key;
684
0
    unsigned char *privkey;
685
686
0
    if (gctx == NULL)
687
0
        return NULL;
688
0
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
689
0
             gctx->propq))
690
0
        == NULL) {
691
0
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
692
0
        return NULL;
693
0
    }
694
695
    /* If we're doing parameter generation then we just return a blank key */
696
0
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
697
0
        return key;
698
699
0
    if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
700
0
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
701
0
        goto err;
702
0
    }
703
0
#ifndef FIPS_MODULE
704
0
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
705
0
        if (ecx_key_type_is_ed(gctx->type))
706
0
            goto err;
707
0
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
708
0
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
709
0
            goto err;
710
0
    } else
711
0
#endif
712
0
    {
713
0
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
714
0
            goto err;
715
0
    }
716
717
0
    switch (gctx->type) {
718
0
    case ECX_KEY_TYPE_X25519:
719
0
        privkey[0] &= 248;
720
0
        privkey[X25519_KEYLEN - 1] &= 127;
721
0
        privkey[X25519_KEYLEN - 1] |= 64;
722
0
        ossl_x25519_public_from_private(key->pubkey, privkey);
723
0
        break;
724
0
    case ECX_KEY_TYPE_X448:
725
0
        privkey[0] &= 252;
726
0
        privkey[X448_KEYLEN - 1] |= 128;
727
0
        ossl_x448_public_from_private(key->pubkey, privkey);
728
0
        break;
729
0
    case ECX_KEY_TYPE_ED25519:
730
0
        if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
731
0
                gctx->propq))
732
0
            goto err;
733
0
        break;
734
0
    case ECX_KEY_TYPE_ED448:
735
0
        if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
736
0
                gctx->propq))
737
0
            goto err;
738
0
        break;
739
0
    }
740
0
    key->haspubkey = 1;
741
0
    return key;
742
0
err:
743
0
    ossl_ecx_key_free(key);
744
0
    return NULL;
745
0
}
746
747
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
748
0
{
749
0
    struct ecx_gen_ctx *gctx = genctx;
750
751
0
    if (!ossl_prov_is_running())
752
0
        return 0;
753
754
#ifdef S390X_EC_ASM
755
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
756
        return s390x_ecx_keygen25519(gctx);
757
#endif
758
0
    return ecx_gen(gctx);
759
0
}
760
761
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
762
0
{
763
0
    struct ecx_gen_ctx *gctx = genctx;
764
765
0
    if (!ossl_prov_is_running())
766
0
        return 0;
767
768
#ifdef S390X_EC_ASM
769
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
770
        return s390x_ecx_keygen448(gctx);
771
#endif
772
0
    return ecx_gen(gctx);
773
0
}
774
775
static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
776
0
{
777
0
    ECX_KEY *key = NULL;
778
0
    struct ecx_gen_ctx *gctx = genctx;
779
780
0
    if (!ossl_prov_is_running())
781
0
        return 0;
782
783
#ifdef S390X_EC_ASM
784
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
785
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
786
        && OPENSSL_s390xcap_P.kdsa[0]
787
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) {
788
        key = s390x_ecd_keygen25519(gctx);
789
    } else
790
#endif
791
0
    {
792
0
        key = ecx_gen(gctx);
793
0
    }
794
795
#ifdef FIPS_MODULE
796
    /* Exit if keygen failed OR we are doing parameter generation (blank key) */
797
    if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
798
        return key;
799
    if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) {
800
        ossl_ecx_key_free(key);
801
        return NULL;
802
    }
803
#endif
804
805
0
    return key;
806
0
}
807
808
static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
809
0
{
810
0
    ECX_KEY *key = NULL;
811
0
    struct ecx_gen_ctx *gctx = genctx;
812
813
0
    if (!ossl_prov_is_running())
814
0
        return 0;
815
816
#ifdef S390X_EC_ASM
817
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
818
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
819
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) {
820
        key = s390x_ecd_keygen448(gctx);
821
    } else
822
#endif
823
0
    {
824
0
        key = ecx_gen(gctx);
825
0
    }
826
827
#ifdef FIPS_MODULE
828
    /* Exit if keygen failed OR we are doing parameter generation (blank key) */
829
    if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
830
        return key;
831
    if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
832
        ossl_ecx_key_free(key);
833
        return NULL;
834
    }
835
#endif
836
837
0
    return key;
838
0
}
839
840
static void ecx_gen_cleanup(void *genctx)
841
0
{
842
0
    struct ecx_gen_ctx *gctx = genctx;
843
844
0
    if (gctx == NULL)
845
0
        return;
846
847
0
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
848
0
    OPENSSL_free(gctx->propq);
849
0
    OPENSSL_free(gctx);
850
0
}
851
852
void *ecx_load(const void *reference, size_t reference_sz)
853
0
{
854
0
    ECX_KEY *key = NULL;
855
856
0
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
857
        /* The contents of the reference is the address to our object */
858
0
        key = *(ECX_KEY **)reference;
859
        /* We grabbed, so we detach it */
860
0
        *(ECX_KEY **)reference = NULL;
861
0
        return key;
862
0
    }
863
0
    return NULL;
864
0
}
865
866
static void *ecx_dup(const void *keydata_from, int selection)
867
0
{
868
0
    if (ossl_prov_is_running())
869
0
        return ossl_ecx_key_dup(keydata_from, selection);
870
0
    return NULL;
871
0
}
872
873
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
874
0
{
875
0
    uint8_t pub[64];
876
877
0
    switch (type) {
878
0
    case ECX_KEY_TYPE_X25519:
879
0
        ossl_x25519_public_from_private(pub, ecx->privkey);
880
0
        break;
881
0
    case ECX_KEY_TYPE_X448:
882
0
        ossl_x448_public_from_private(pub, ecx->privkey);
883
0
        break;
884
0
    default:
885
0
        return 0;
886
0
    }
887
0
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
888
0
}
889
890
#ifdef FIPS_MODULE
891
/*
892
 * FIPS ACVP testing requires the ability to check if the public key is valid
893
 * This is not required normally since the ED signature verify does the test
894
 * internally.
895
 */
896
static int ecd_key_pub_check(const ECX_KEY *ecx, int type)
897
{
898
    switch (type) {
899
    case ECX_KEY_TYPE_ED25519:
900
        return ossl_ed25519_pubkey_verify(ecx->pubkey, ecx->keylen);
901
    case ECX_KEY_TYPE_ED448:
902
        return ossl_ed448_pubkey_verify(ecx->pubkey, ecx->keylen);
903
    default:
904
        return 1;
905
    }
906
}
907
#endif
908
909
#ifdef FIPS_MODULE
910
static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
911
{
912
    return ecd_fips140_pairwise_test(ecx, type, 0);
913
}
914
#else
915
static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
916
0
{
917
0
    uint8_t pub[64];
918
919
0
    switch (type) {
920
0
    case ECX_KEY_TYPE_ED25519:
921
0
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
922
0
                ecx->propq))
923
0
            return 0;
924
0
        break;
925
0
    case ECX_KEY_TYPE_ED448:
926
0
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
927
0
                ecx->propq))
928
0
            return 0;
929
0
        break;
930
0
    default:
931
0
        return 0;
932
0
    }
933
0
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
934
0
}
935
#endif
936
937
static int ecx_validate(const void *keydata, int selection, int type,
938
    size_t keylen)
939
0
{
940
0
    const ECX_KEY *ecx = keydata;
941
0
    int ok = keylen == ecx->keylen;
942
943
0
    if (!ossl_prov_is_running())
944
0
        return 0;
945
946
0
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
947
0
        return 1; /* nothing to validate */
948
949
0
    if (!ok) {
950
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
951
0
        return 0;
952
0
    }
953
954
0
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
955
0
        ok = ok && ecx->haspubkey;
956
#ifdef FIPS_MODULE
957
        ok = ok && ecd_key_pub_check(ecx, type);
958
#endif
959
0
    }
960
961
0
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
962
0
        ok = ok && ecx->privkey != NULL;
963
964
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
965
0
        return ok;
966
967
0
    if (ecx_key_type_is_ed(type))
968
0
        ok = ok && ecd_key_pairwise_check(ecx, type);
969
0
    else
970
0
        ok = ok && ecx_key_pairwise_check(ecx, type);
971
972
0
    return ok;
973
0
}
974
975
static int x25519_validate(const void *keydata, int selection, int checktype)
976
0
{
977
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
978
0
}
979
980
static int x448_validate(const void *keydata, int selection, int checktype)
981
0
{
982
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
983
0
}
984
985
static int ed25519_validate(const void *keydata, int selection, int checktype)
986
0
{
987
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
988
0
}
989
990
static int ed448_validate(const void *keydata, int selection, int checktype)
991
0
{
992
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
993
0
}
994
995
static void ecx_free_key(void *keydata)
996
0
{
997
0
    ossl_ecx_key_free((ECX_KEY *)keydata);
998
0
}
999
1000
#define MAKE_KEYMGMT_FUNCTIONS(alg)                                                   \
1001
    const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = {                          \
1002
        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key },                     \
1003
        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_free_key },                     \
1004
        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))alg##_get_params },           \
1005
        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))alg##_gettable_params }, \
1006
        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))alg##_set_params },           \
1007
        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))alg##_settable_params }, \
1008
        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has },                           \
1009
        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match },                       \
1010
        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate },               \
1011
        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import },                     \
1012
        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types },       \
1013
        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export },                     \
1014
        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types },       \
1015
        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init },               \
1016
        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params },     \
1017
        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,                                      \
1018
            (void (*)(void))ecx_gen_settable_params },                                \
1019
        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen },                         \
1020
        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup },           \
1021
        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load },                         \
1022
        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup },                           \
1023
        OSSL_DISPATCH_END                                                             \
1024
    };
1025
1026
MAKE_KEYMGMT_FUNCTIONS(x25519)
1027
MAKE_KEYMGMT_FUNCTIONS(x448)
1028
MAKE_KEYMGMT_FUNCTIONS(ed25519)
1029
MAKE_KEYMGMT_FUNCTIONS(ed448)
1030
1031
#ifdef S390X_EC_ASM
1032
#include "arch/s390x_arch.h"
1033
1034
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
1035
{
1036
    static const unsigned char generator[] = {
1037
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1038
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1039
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1040
    };
1041
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
1042
        gctx->propq);
1043
    unsigned char *privkey = NULL, *pubkey;
1044
1045
    if (key == NULL) {
1046
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1047
        goto err;
1048
    }
1049
1050
    /* If we're doing parameter generation then we just return a blank key */
1051
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1052
        return key;
1053
1054
    pubkey = key->pubkey;
1055
1056
    privkey = ossl_ecx_key_allocate_privkey(key);
1057
    if (privkey == NULL) {
1058
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1059
        goto err;
1060
    }
1061
1062
#ifndef FIPS_MODULE
1063
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1064
        if (gctx->type != ECX_KEY_TYPE_X25519)
1065
            goto err;
1066
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
1067
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1068
            goto err;
1069
    } else
1070
#endif
1071
    {
1072
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
1073
            goto err;
1074
    }
1075
1076
    privkey[0] &= 248;
1077
    privkey[31] &= 127;
1078
    privkey[31] |= 64;
1079
1080
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1081
        goto err;
1082
    key->haspubkey = 1;
1083
    return key;
1084
err:
1085
    ossl_ecx_key_free(key);
1086
    return NULL;
1087
}
1088
1089
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
1090
{
1091
    static const unsigned char generator[] = {
1092
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1095
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1097
    };
1098
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
1099
        gctx->propq);
1100
    unsigned char *privkey = NULL, *pubkey;
1101
1102
    if (key == NULL) {
1103
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1104
        goto err;
1105
    }
1106
1107
    /* If we're doing parameter generation then we just return a blank key */
1108
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1109
        return key;
1110
1111
    pubkey = key->pubkey;
1112
1113
    privkey = ossl_ecx_key_allocate_privkey(key);
1114
    if (privkey == NULL) {
1115
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1116
        goto err;
1117
    }
1118
1119
#ifndef FIPS_MODULE
1120
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1121
        if (gctx->type != ECX_KEY_TYPE_X448)
1122
            goto err;
1123
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
1124
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1125
            goto err;
1126
    } else
1127
#endif
1128
    {
1129
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1130
            goto err;
1131
    }
1132
1133
    privkey[0] &= 252;
1134
    privkey[55] |= 128;
1135
1136
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1137
        goto err;
1138
    key->haspubkey = 1;
1139
    return key;
1140
err:
1141
    ossl_ecx_key_free(key);
1142
    return NULL;
1143
}
1144
1145
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
1146
{
1147
    static const unsigned char generator_x[] = {
1148
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1149
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1150
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1151
    };
1152
    static const unsigned char generator_y[] = {
1153
        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1154
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1155
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1156
        0x66, 0x66
1157
    };
1158
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1159
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1160
        gctx->propq);
1161
    unsigned char *privkey = NULL, *pubkey;
1162
    unsigned int sz;
1163
    EVP_MD *sha = NULL;
1164
    int j;
1165
1166
    if (key == NULL) {
1167
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1168
        goto err;
1169
    }
1170
1171
    /* If we're doing parameter generation then we just return a blank key */
1172
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1173
        return key;
1174
1175
    pubkey = key->pubkey;
1176
1177
    privkey = ossl_ecx_key_allocate_privkey(key);
1178
    if (privkey == NULL) {
1179
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1180
        goto err;
1181
    }
1182
1183
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1184
        goto err;
1185
1186
    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1187
    if (sha == NULL)
1188
        goto err;
1189
    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1190
    EVP_MD_free(sha);
1191
    if (!j)
1192
        goto err;
1193
1194
    buff[0] &= 248;
1195
    buff[31] &= 63;
1196
    buff[31] |= 64;
1197
1198
    if (s390x_ed25519_mul(x_dst, pubkey,
1199
            generator_x, generator_y, buff)
1200
        != 1)
1201
        goto err;
1202
1203
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1204
    key->haspubkey = 1;
1205
    return key;
1206
err:
1207
    ossl_ecx_key_free(key);
1208
    return NULL;
1209
}
1210
1211
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1212
{
1213
    static const unsigned char generator_x[] = {
1214
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1215
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1216
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1217
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1218
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1219
    };
1220
    static const unsigned char generator_y[] = {
1221
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1222
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1223
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1224
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1225
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1226
    };
1227
    unsigned char x_dst[57], buff[114];
1228
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1229
        gctx->propq);
1230
    unsigned char *privkey = NULL, *pubkey;
1231
    EVP_MD_CTX *hashctx = NULL;
1232
    EVP_MD *shake = NULL;
1233
1234
    if (key == NULL) {
1235
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1236
        goto err;
1237
    }
1238
1239
    /* If we're doing parameter generation then we just return a blank key */
1240
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1241
        return key;
1242
1243
    pubkey = key->pubkey;
1244
1245
    privkey = ossl_ecx_key_allocate_privkey(key);
1246
    if (privkey == NULL) {
1247
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1248
        goto err;
1249
    }
1250
1251
    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1252
    if (shake == NULL)
1253
        goto err;
1254
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1255
        goto err;
1256
1257
    hashctx = EVP_MD_CTX_new();
1258
    if (hashctx == NULL)
1259
        goto err;
1260
    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1261
        goto err;
1262
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1263
        goto err;
1264
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1265
        goto err;
1266
1267
    buff[0] &= -4;
1268
    buff[55] |= 0x80;
1269
    buff[56] = 0;
1270
1271
    if (s390x_ed448_mul(x_dst, pubkey,
1272
            generator_x, generator_y, buff)
1273
        != 1)
1274
        goto err;
1275
1276
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1277
    EVP_MD_CTX_free(hashctx);
1278
    EVP_MD_free(shake);
1279
    key->haspubkey = 1;
1280
    return key;
1281
err:
1282
    ossl_ecx_key_free(key);
1283
    EVP_MD_CTX_free(hashctx);
1284
    EVP_MD_free(shake);
1285
    return NULL;
1286
}
1287
#endif