Coverage Report

Created: 2026-07-23 06:28

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-2026 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
17.4k
#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
23
{
103
23
    return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448;
104
23
}
105
106
static void *x25519_new_key(void *provctx)
107
30
{
108
30
    if (!ossl_prov_is_running())
109
0
        return 0;
110
30
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
111
30
        NULL);
112
30
}
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
57.1k
{
140
57.1k
    const ECX_KEY *key = keydata;
141
57.1k
    int ok = 0;
142
143
57.1k
    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
28.7k
        ok = 1;
149
150
28.7k
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
151
96
            ok = ok && key->haspubkey;
152
153
28.7k
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
154
28
            ok = ok && key->privkey != NULL;
155
28.7k
    }
156
57.1k
    return ok;
157
57.1k
}
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
429k
{
228
429k
    if (key == NULL)
229
0
        return 0;
230
231
429k
    if (!ossl_param_build_set_octet_string(tmpl, params,
232
429k
            OSSL_PKEY_PARAM_PUB_KEY,
233
429k
            key->pubkey, key->keylen))
234
0
        return 0;
235
236
429k
    if (include_private
237
381k
        && key->privkey != NULL
238
341k
        && !ossl_param_build_set_octet_string(tmpl, params,
239
341k
            OSSL_PKEY_PARAM_PRIV_KEY,
240
341k
            key->privkey, key->keylen))
241
0
        return 0;
242
243
429k
    return 1;
244
429k
}
245
246
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
247
    void *cbarg)
248
48.1k
{
249
48.1k
    ECX_KEY *key = keydata;
250
48.1k
    OSSL_PARAM_BLD *tmpl;
251
48.1k
    OSSL_PARAM *params = NULL;
252
48.1k
    int ret = 0;
253
254
48.1k
    if (!ossl_prov_is_running() || key == NULL)
255
0
        return 0;
256
257
48.1k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
258
0
        return 0;
259
260
48.1k
    tmpl = OSSL_PARAM_BLD_new();
261
48.1k
    if (tmpl == NULL)
262
0
        return 0;
263
264
48.1k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
265
48.1k
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
266
267
48.1k
        if (!key_to_params(key, tmpl, NULL, include_private))
268
0
            goto err;
269
48.1k
    }
270
271
48.1k
    params = OSSL_PARAM_BLD_to_param(tmpl);
272
48.1k
    if (params == NULL)
273
0
        goto err;
274
275
48.1k
    ret = param_cb(params, cbarg);
276
48.1k
    OSSL_PARAM_free(params);
277
48.1k
err:
278
48.1k
    OSSL_PARAM_BLD_free(tmpl);
279
48.1k
    return ret;
280
48.1k
}
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
231k
{
300
231k
    ECX_KEY *ecx = key;
301
231k
    OSSL_PARAM *p;
302
303
231k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
304
104k
        && !OSSL_PARAM_set_int(p, bits))
305
0
        return 0;
306
231k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
307
104k
        && !OSSL_PARAM_set_int(p, secbits))
308
0
        return 0;
309
231k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
310
104k
        && !OSSL_PARAM_set_int(p, size))
311
0
        return 0;
312
231k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
313
126k
        && (ecx->type == ECX_KEY_TYPE_X25519
314
126k
            || ecx->type == ECX_KEY_TYPE_X448)) {
315
126k
        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
316
0
            return 0;
317
126k
    }
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
231k
    return key_to_params(ecx, NULL, params, 1);
330
231k
}
331
332
static int ed_get_params(void *key, OSSL_PARAM params[])
333
560
{
334
560
    OSSL_PARAM *p;
335
336
560
    if ((p = OSSL_PARAM_locate(params,
337
560
             OSSL_PKEY_PARAM_MANDATORY_DIGEST))
338
560
            != NULL
339
0
        && !OSSL_PARAM_set_utf8_string(p, ""))
340
0
        return 0;
341
560
    return 1;
342
560
}
343
344
static int x25519_get_params(void *key, OSSL_PARAM params[])
345
377k
{
346
377k
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
347
377k
        X25519_KEYLEN);
348
377k
}
349
350
static int x448_get_params(void *key, OSSL_PARAM params[])
351
1.98k
{
352
1.98k
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
353
1.98k
        X448_KEYLEN);
354
1.98k
}
355
356
static int ed25519_get_params(void *key, OSSL_PARAM params[])
357
195
{
358
195
    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
359
195
               ED25519_SIGSIZE)
360
195
        && ed_get_params(key, params);
361
195
}
362
363
static int ed448_get_params(void *key, OSSL_PARAM params[])
364
365
{
365
365
    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
366
365
               ED448_SIGSIZE)
367
365
        && ed_get_params(key, params);
368
365
}
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.23k
{
423
6.23k
    ECX_KEY *ecxkey = key;
424
6.23k
    const OSSL_PARAM *p;
425
426
6.23k
    if (ossl_param_is_empty(params))
427
0
        return 1;
428
429
6.23k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
430
6.23k
    if (p != NULL) {
431
6.23k
        void *buf = ecxkey->pubkey;
432
433
6.23k
        if (p->data_size != ecxkey->keylen
434
6.22k
            || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
435
6.22k
                NULL))
436
17
            return 0;
437
6.22k
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
438
6.22k
        ecxkey->privkey = NULL;
439
6.22k
        ecxkey->haspubkey = 1;
440
6.22k
    }
441
6.22k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
442
6.22k
    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.22k
    return 1;
449
6.22k
}
450
451
static int x25519_set_params(void *key, const OSSL_PARAM params[])
452
34.3k
{
453
34.3k
    return ecx_set_params(key, params);
454
34.3k
}
455
456
static int x448_set_params(void *key, const OSSL_PARAM params[])
457
69
{
458
69
    return ecx_set_params(key, params);
459
69
}
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
151k
{
505
151k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
506
151k
    struct ecx_gen_ctx *gctx = NULL;
507
508
151k
    if (!ossl_prov_is_running())
509
0
        return NULL;
510
511
151k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
512
151k
        gctx->libctx = libctx;
513
151k
        gctx->type = type;
514
151k
        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
151k
    } else {
524
0
        return NULL;
525
0
    }
526
151k
    if (!ecx_gen_set_params(gctx, params)) {
527
0
        ecx_gen_cleanup(gctx);
528
0
        gctx = NULL;
529
0
    }
530
151k
    return gctx;
531
151k
}
532
533
static void *x25519_gen_init(void *provctx, int selection,
534
    const OSSL_PARAM params[])
535
151k
{
536
151k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
537
151k
}
538
539
static void *x448_gen_init(void *provctx, int selection,
540
    const OSSL_PARAM params[])
541
312
{
542
312
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
543
312
}
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
150k
{
559
150k
    struct ecx_gen_ctx *gctx = genctx;
560
150k
    const OSSL_PARAM *p;
561
562
150k
    if (gctx == NULL)
563
0
        return 0;
564
565
150k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
566
150k
    if (p != NULL) {
567
57.4k
        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
57.4k
        switch (gctx->type) {
575
57.2k
        case ECX_KEY_TYPE_X25519:
576
57.2k
            groupname = "x25519";
577
57.2k
            break;
578
206
        case ECX_KEY_TYPE_X448:
579
206
            groupname = "x448";
580
206
            break;
581
0
        default:
582
            /* We only support this for key exchange at the moment */
583
0
            break;
584
57.4k
        }
585
57.4k
        if (p->data_type != OSSL_PARAM_UTF8_STRING
586
57.4k
            || groupname == NULL
587
57.4k
            || 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
57.4k
    }
592
150k
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
593
150k
    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
150k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
602
150k
    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
150k
    return 1;
613
150k
}
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
103k
{
697
103k
    ECX_KEY *key;
698
103k
    unsigned char *privkey;
699
700
103k
    if (gctx == NULL)
701
0
        return NULL;
702
103k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
703
103k
             gctx->propq))
704
103k
        == 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
103k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
711
3.06k
        return key;
712
713
100k
    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
100k
#ifndef FIPS_MODULE
718
100k
    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
100k
#endif
726
100k
    {
727
100k
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
728
0
            goto err;
729
100k
    }
730
731
100k
    switch (gctx->type) {
732
100k
    case ECX_KEY_TYPE_X25519:
733
100k
        privkey[0] &= 248;
734
100k
        privkey[X25519_KEYLEN - 1] &= 127;
735
100k
        privkey[X25519_KEYLEN - 1] |= 64;
736
100k
        ossl_x25519_public_from_private(key->pubkey, privkey);
737
100k
        break;
738
107
    case ECX_KEY_TYPE_X448:
739
107
        privkey[0] &= 252;
740
107
        privkey[X448_KEYLEN - 1] |= 128;
741
107
        ossl_x448_public_from_private(key->pubkey, privkey);
742
107
        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
100k
    }
754
100k
    key->haspubkey = 1;
755
100k
    return key;
756
0
err:
757
0
    ossl_ecx_key_free(key);
758
0
    return NULL;
759
100k
}
760
761
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
762
151k
{
763
151k
    struct ecx_gen_ctx *gctx = genctx;
764
765
151k
    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
151k
    return ecx_gen(gctx);
773
151k
}
774
775
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
776
312
{
777
312
    struct ecx_gen_ctx *gctx = genctx;
778
779
312
    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
312
    return ecx_gen(gctx);
787
312
}
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
151k
{
858
151k
    struct ecx_gen_ctx *gctx = genctx;
859
860
151k
    if (gctx == NULL)
861
0
        return;
862
863
151k
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
864
151k
    OPENSSL_free(gctx->propq);
865
151k
    OPENSSL_free(gctx);
866
151k
}
867
868
void *ecx_load(const void *reference, size_t reference_sz)
869
5.35k
{
870
5.35k
    ECX_KEY *key = NULL;
871
872
5.35k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
873
        /* The contents of the reference is the address to our object */
874
5.35k
        key = *(ECX_KEY **)reference;
875
        /* We grabbed, so we detach it */
876
5.35k
        *(ECX_KEY **)reference = NULL;
877
5.35k
        return key;
878
5.35k
    }
879
0
    return NULL;
880
5.35k
}
881
882
static void *ecx_dup(const void *keydata_from, int selection)
883
28.5k
{
884
28.5k
    if (ossl_prov_is_running())
885
28.5k
        return ossl_ecx_key_dup(keydata_from, selection);
886
0
    return NULL;
887
28.5k
}
888
889
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
890
13
{
891
13
    uint8_t pub[64];
892
893
13
    switch (type) {
894
6
    case ECX_KEY_TYPE_X25519:
895
6
        ossl_x25519_public_from_private(pub, ecx->privkey);
896
6
        break;
897
7
    case ECX_KEY_TYPE_X448:
898
7
        ossl_x448_public_from_private(pub, ecx->privkey);
899
7
        break;
900
0
    default:
901
0
        return 0;
902
13
    }
903
13
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
904
13
}
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
15
{
933
15
    uint8_t pub[64];
934
935
15
    switch (type) {
936
7
    case ECX_KEY_TYPE_ED25519:
937
7
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
938
7
                ecx->propq))
939
0
            return 0;
940
7
        break;
941
8
    case ECX_KEY_TYPE_ED448:
942
8
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
943
8
                ecx->propq))
944
0
            return 0;
945
8
        break;
946
8
    default:
947
0
        return 0;
948
15
    }
949
15
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
950
15
}
951
#endif
952
953
static int ecx_validate(const void *keydata, int selection, int type,
954
    size_t keylen)
955
17.4k
{
956
17.4k
    const ECX_KEY *ecx = keydata;
957
17.4k
    int ok = keylen == ecx->keylen;
958
959
17.4k
    if (!ossl_prov_is_running())
960
0
        return 0;
961
962
17.4k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
963
23
        return 1; /* nothing to validate */
964
965
17.4k
    if (!ok) {
966
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
967
0
        return 0;
968
0
    }
969
970
17.4k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
971
17.4k
        ok = ok && ecx->haspubkey;
972
#ifdef FIPS_MODULE
973
        ok = ok && ecd_key_pub_check(ecx, type);
974
#endif
975
17.4k
    }
976
977
17.4k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
978
46
        ok = ok && ecx->privkey != NULL;
979
980
17.4k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
981
17.4k
        return ok;
982
983
23
    if (ecx_key_type_is_ed(type))
984
11
        ok = ok && ecd_key_pairwise_check(ecx, type);
985
12
    else
986
12
        ok = ok && ecx_key_pairwise_check(ecx, type);
987
988
23
    return ok;
989
17.4k
}
990
991
static int x25519_validate(const void *keydata, int selection, int checktype)
992
32.2k
{
993
32.2k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
994
32.2k
}
995
996
static int x448_validate(const void *keydata, int selection, int checktype)
997
84
{
998
84
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
999
84
}
1000
1001
static int ed25519_validate(const void *keydata, int selection, int checktype)
1002
48
{
1003
48
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
1004
48
}
1005
1006
static int ed448_validate(const void *keydata, int selection, int checktype)
1007
52
{
1008
52
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
1009
52
}
1010
1011
static void ecx_free_key(void *keydata)
1012
122k
{
1013
122k
    ossl_ecx_key_free((ECX_KEY *)keydata);
1014
122k
}
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, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1170
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1171
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1172
        0x66, 0x66
1173
    };
1174
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1175
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1176
        gctx->propq);
1177
    unsigned char *privkey = NULL, *pubkey;
1178
    unsigned int sz;
1179
    EVP_MD *sha = NULL;
1180
    int j;
1181
1182
    if (key == NULL) {
1183
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1184
        goto err;
1185
    }
1186
1187
    /* If we're doing parameter generation then we just return a blank key */
1188
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1189
        return key;
1190
1191
    pubkey = key->pubkey;
1192
1193
    privkey = ossl_ecx_key_allocate_privkey(key);
1194
    if (privkey == NULL) {
1195
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1196
        goto err;
1197
    }
1198
1199
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1200
        goto err;
1201
1202
    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1203
    if (sha == NULL)
1204
        goto err;
1205
    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1206
    EVP_MD_free(sha);
1207
    if (!j)
1208
        goto err;
1209
1210
    buff[0] &= 248;
1211
    buff[31] &= 63;
1212
    buff[31] |= 64;
1213
1214
    if (s390x_ed25519_mul(x_dst, pubkey,
1215
            generator_x, generator_y, buff)
1216
        != 1)
1217
        goto err;
1218
1219
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1220
    key->haspubkey = 1;
1221
    return key;
1222
err:
1223
    ossl_ecx_key_free(key);
1224
    return NULL;
1225
}
1226
1227
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1228
{
1229
    static const unsigned char generator_x[] = {
1230
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1231
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1232
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1233
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1234
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1235
    };
1236
    static const unsigned char generator_y[] = {
1237
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1238
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1239
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1240
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1241
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1242
    };
1243
    unsigned char x_dst[57], buff[114];
1244
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1245
        gctx->propq);
1246
    unsigned char *privkey = NULL, *pubkey;
1247
    EVP_MD_CTX *hashctx = NULL;
1248
    EVP_MD *shake = NULL;
1249
1250
    if (key == NULL) {
1251
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1252
        goto err;
1253
    }
1254
1255
    /* If we're doing parameter generation then we just return a blank key */
1256
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1257
        return key;
1258
1259
    pubkey = key->pubkey;
1260
1261
    privkey = ossl_ecx_key_allocate_privkey(key);
1262
    if (privkey == NULL) {
1263
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1264
        goto err;
1265
    }
1266
1267
    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1268
    if (shake == NULL)
1269
        goto err;
1270
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1271
        goto err;
1272
1273
    hashctx = EVP_MD_CTX_new();
1274
    if (hashctx == NULL)
1275
        goto err;
1276
    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1277
        goto err;
1278
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1279
        goto err;
1280
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1281
        goto err;
1282
1283
    buff[0] &= -4;
1284
    buff[55] |= 0x80;
1285
    buff[56] = 0;
1286
1287
    if (s390x_ed448_mul(x_dst, pubkey,
1288
            generator_x, generator_y, buff)
1289
        != 1)
1290
        goto err;
1291
1292
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1293
    EVP_MD_CTX_free(hashctx);
1294
    EVP_MD_free(shake);
1295
    key->haspubkey = 1;
1296
    return key;
1297
err:
1298
    ossl_ecx_key_free(key);
1299
    EVP_MD_CTX_free(hashctx);
1300
    EVP_MD_free(shake);
1301
    return NULL;
1302
}
1303
#endif