Coverage Report

Created: 2025-12-31 06:58

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