Coverage Report

Created: 2025-08-11 07:04

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