Coverage Report

Created: 2025-12-31 06:58

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