Coverage Report

Created: 2026-05-24 07:14

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