Coverage Report

Created: 2025-12-31 06:58

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