Coverage Report

Created: 2025-08-28 07:07

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