Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl35/crypto/evp/pmeth_gn.c
Line
Count
Source
1
/*
2
 * Copyright 2006-2023 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 <stdio.h>
11
#include <stdlib.h>
12
#include <openssl/core.h>
13
#include <openssl/core_names.h>
14
#include "internal/cryptlib.h"
15
#include "internal/core.h"
16
#include <openssl/objects.h>
17
#include <openssl/evp.h>
18
#include "crypto/bn.h"
19
#ifndef FIPS_MODULE
20
#include "crypto/asn1.h"
21
#endif
22
#include "crypto/evp.h"
23
#include "evp_local.h"
24
25
static int gen_init(EVP_PKEY_CTX *ctx, int operation)
26
202k
{
27
202k
    int ret = 0;
28
29
202k
    if (ctx == NULL)
30
0
        goto not_supported;
31
32
202k
    evp_pkey_ctx_free_old_ops(ctx);
33
202k
    ctx->operation = operation;
34
35
202k
    if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
36
0
        goto legacy;
37
38
202k
    switch (operation) {
39
9.59k
    case EVP_PKEY_OP_PARAMGEN:
40
9.59k
        ctx->op.keymgmt.genctx = evp_keymgmt_gen_init(ctx->keymgmt,
41
9.59k
            OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, NULL);
42
9.59k
        break;
43
193k
    case EVP_PKEY_OP_KEYGEN:
44
193k
        ctx->op.keymgmt.genctx = evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR,
45
193k
            NULL);
46
193k
        break;
47
202k
    }
48
49
202k
    if (ctx->op.keymgmt.genctx == NULL)
50
202k
        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
51
202k
    else
52
202k
        ret = 1;
53
202k
    goto end;
54
55
0
legacy:
56
#ifdef FIPS_MODULE
57
    goto not_supported;
58
#else
59
0
    if (ctx->pmeth == NULL
60
0
        || (operation == EVP_PKEY_OP_PARAMGEN
61
0
            && ctx->pmeth->paramgen == NULL)
62
0
        || (operation == EVP_PKEY_OP_KEYGEN
63
0
            && ctx->pmeth->keygen == NULL))
64
0
        goto not_supported;
65
66
0
    ret = 1;
67
0
    switch (operation) {
68
0
    case EVP_PKEY_OP_PARAMGEN:
69
0
        if (ctx->pmeth->paramgen_init != NULL)
70
0
            ret = ctx->pmeth->paramgen_init(ctx);
71
0
        break;
72
0
    case EVP_PKEY_OP_KEYGEN:
73
0
        if (ctx->pmeth->keygen_init != NULL)
74
0
            ret = ctx->pmeth->keygen_init(ctx);
75
0
        break;
76
0
    }
77
0
#endif
78
79
202k
end:
80
202k
    if (ret <= 0 && ctx != NULL) {
81
0
        evp_pkey_ctx_free_old_ops(ctx);
82
0
        ctx->operation = EVP_PKEY_OP_UNDEFINED;
83
0
    }
84
202k
    return ret;
85
86
0
not_supported:
87
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
88
0
    ret = -2;
89
0
    goto end;
90
0
}
91
92
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
93
11.5k
{
94
11.5k
    return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
95
11.5k
}
96
97
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
98
264k
{
99
264k
    return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
100
264k
}
101
102
static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
103
0
{
104
0
    EVP_PKEY_CTX *ctx = arg;
105
0
    const OSSL_PARAM *param = NULL;
106
0
    int p = -1, n = -1;
107
108
0
    if (ctx->pkey_gencb == NULL)
109
0
        return 1; /* No callback?  That's fine */
110
111
0
    if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
112
0
            == NULL
113
0
        || !OSSL_PARAM_get_int(param, &p))
114
0
        return 0;
115
0
    if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
116
0
            == NULL
117
0
        || !OSSL_PARAM_get_int(param, &n))
118
0
        return 0;
119
120
0
    ctx->keygen_info[0] = p;
121
0
    ctx->keygen_info[1] = n;
122
123
0
    return ctx->pkey_gencb(ctx);
124
0
}
125
126
int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
127
202k
{
128
202k
    int ret = 0;
129
202k
    EVP_PKEY *allocated_pkey = NULL;
130
    /* Legacy compatible keygen callback info, only used with provider impls */
131
202k
    int gentmp[2];
132
133
202k
    if (ppkey == NULL)
134
0
        return -1;
135
136
202k
    if (ctx == NULL)
137
0
        goto not_supported;
138
139
202k
    if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
140
0
        goto not_initialized;
141
142
202k
    if (*ppkey == NULL)
143
201k
        *ppkey = allocated_pkey = EVP_PKEY_new();
144
145
202k
    if (*ppkey == NULL) {
146
0
        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
147
0
        return -1;
148
0
    }
149
150
202k
    if (ctx->op.keymgmt.genctx == NULL)
151
0
        goto legacy;
152
153
    /*
154
     * Assigning gentmp to ctx->keygen_info is something our legacy
155
     * implementations do.  Because the provider implementations aren't
156
     * allowed to reach into our EVP_PKEY_CTX, we need to provide similar
157
     * space for backward compatibility.  It's ok that we attach a local
158
     * variable, as it should only be useful in the calls down from here.
159
     * This is cleared as soon as it isn't useful any more, i.e. directly
160
     * after the evp_keymgmt_util_gen() call.
161
     */
162
202k
    ctx->keygen_info = gentmp;
163
202k
    ctx->keygen_info_count = 2;
164
165
202k
    ret = 1;
166
202k
    if (ctx->pkey != NULL) {
167
8.87k
        EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
168
8.87k
        void *keydata = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
169
8.87k
            &tmp_keymgmt, ctx->propquery);
170
171
8.87k
        if (tmp_keymgmt == NULL)
172
0
            goto not_supported;
173
        /*
174
         * It's ok if keydata is NULL here.  The backend is expected to deal
175
         * with that as it sees fit.
176
         */
177
8.87k
        ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
178
8.87k
            ctx->op.keymgmt.genctx, keydata);
179
8.87k
    }
180
181
    /*
182
     * the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
183
     * so we do not need to save it, just check it.
184
     */
185
202k
    ret = ret
186
202k
        && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
187
202k
                ossl_callback_to_pkey_gencb, ctx)
188
202k
            != NULL);
189
190
202k
    ctx->keygen_info = NULL;
191
192
202k
#ifndef FIPS_MODULE
193
    /* In case |*ppkey| was originally a legacy key */
194
202k
    if (ret)
195
202k
        evp_pkey_free_legacy(*ppkey);
196
202k
#endif
197
198
    /*
199
     * Because we still have legacy keys
200
     */
201
202k
    (*ppkey)->type = ctx->legacy_keytype;
202
203
202k
    goto end;
204
205
0
legacy:
206
#ifdef FIPS_MODULE
207
    goto not_supported;
208
#else
209
    /*
210
     * If we get here then we're using legacy paramgen/keygen. In that case
211
     * the pkey in ctx (if there is one) had better not be provided (because the
212
     * legacy methods may not know how to handle it). However we can only get
213
     * here if ctx->op.keymgmt.genctx == NULL, but that should never be the case
214
     * if ctx->pkey is provided because we don't allow this when we initialise
215
     * the ctx.
216
     */
217
0
    if (ctx->pkey != NULL && !ossl_assert(!evp_pkey_is_provided(ctx->pkey)))
218
0
        goto not_accessible;
219
220
0
    switch (ctx->operation) {
221
0
    case EVP_PKEY_OP_PARAMGEN:
222
0
        ret = ctx->pmeth->paramgen(ctx, *ppkey);
223
0
        break;
224
0
    case EVP_PKEY_OP_KEYGEN:
225
0
        ret = ctx->pmeth->keygen(ctx, *ppkey);
226
0
        break;
227
0
    default:
228
0
        goto not_supported;
229
0
    }
230
0
#endif
231
232
202k
end:
233
202k
    if (ret <= 0) {
234
0
        if (allocated_pkey != NULL)
235
0
            *ppkey = NULL;
236
0
        EVP_PKEY_free(allocated_pkey);
237
0
    }
238
202k
    return ret;
239
240
0
not_supported:
241
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
242
0
    ret = -2;
243
0
    goto end;
244
0
not_initialized:
245
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
246
0
    ret = -1;
247
0
    goto end;
248
0
#ifndef FIPS_MODULE
249
0
not_accessible:
250
0
    ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
251
0
    ret = -1;
252
0
    goto end;
253
0
#endif
254
0
}
255
256
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
257
11.5k
{
258
11.5k
    if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
259
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
260
0
        return -1;
261
0
    }
262
11.5k
    return EVP_PKEY_generate(ctx, ppkey);
263
11.5k
}
264
265
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
266
162k
{
267
162k
    if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
268
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
269
0
        return -1;
270
0
    }
271
162k
    return EVP_PKEY_generate(ctx, ppkey);
272
162k
}
273
274
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
275
0
{
276
0
    ctx->pkey_gencb = cb;
277
0
}
278
279
EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
280
0
{
281
0
    return ctx->pkey_gencb;
282
0
}
283
284
/*
285
 * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
286
 * callbacks.
287
 */
288
289
static int trans_cb(int a, int b, BN_GENCB *gcb)
290
0
{
291
0
    EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb);
292
0
    ctx->keygen_info[0] = a;
293
0
    ctx->keygen_info[1] = b;
294
0
    return ctx->pkey_gencb(ctx);
295
0
}
296
297
void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
298
0
{
299
0
    BN_GENCB_set(cb, trans_cb, ctx);
300
0
}
301
302
int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
303
0
{
304
0
    if (idx == -1)
305
0
        return ctx->keygen_info_count;
306
0
    if (idx < 0 || idx > ctx->keygen_info_count)
307
0
        return 0;
308
0
    return ctx->keygen_info[idx];
309
0
}
310
311
#ifndef FIPS_MODULE
312
313
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
314
    const unsigned char *key, int keylen)
315
0
{
316
0
    EVP_PKEY_CTX *mac_ctx = NULL;
317
0
    EVP_PKEY *mac_key = NULL;
318
0
    mac_ctx = EVP_PKEY_CTX_new_id(type, e);
319
0
    if (!mac_ctx)
320
0
        return NULL;
321
0
    if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
322
0
        goto merr;
323
0
    if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0)
324
0
        goto merr;
325
0
    if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
326
0
        goto merr;
327
0
merr:
328
0
    EVP_PKEY_CTX_free(mac_ctx);
329
0
    return mac_key;
330
0
}
331
332
#endif /* FIPS_MODULE */
333
334
/*- All methods below can also be used in FIPS_MODULE */
335
336
static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
337
30.5k
{
338
30.5k
    if (ctx == NULL || ctx->keytype == NULL)
339
0
        goto not_supported;
340
341
30.5k
    evp_pkey_ctx_free_old_ops(ctx);
342
30.5k
    if (ctx->keymgmt == NULL)
343
0
        goto not_supported;
344
345
30.5k
    ctx->operation = operation;
346
30.5k
    return 1;
347
348
0
not_supported:
349
0
    if (ctx != NULL)
350
0
        ctx->operation = EVP_PKEY_OP_UNDEFINED;
351
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
352
0
    return -2;
353
30.5k
}
354
355
int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx)
356
30.5k
{
357
30.5k
    return fromdata_init(ctx, EVP_PKEY_OP_FROMDATA);
358
30.5k
}
359
360
int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
361
    OSSL_PARAM params[])
362
30.5k
{
363
30.5k
    void *keydata = NULL;
364
30.5k
    EVP_PKEY *allocated_pkey = NULL;
365
366
30.5k
    if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_FROMDATA) == 0) {
367
28
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
368
28
        return -2;
369
28
    }
370
371
30.5k
    if (ppkey == NULL)
372
0
        return -1;
373
374
30.5k
    if (*ppkey == NULL)
375
30.1k
        allocated_pkey = *ppkey = EVP_PKEY_new();
376
377
30.5k
    if (*ppkey == NULL) {
378
0
        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
379
0
        return -1;
380
0
    }
381
382
30.5k
    keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection, params);
383
30.5k
    if (keydata == NULL) {
384
401
        if (allocated_pkey != NULL) {
385
317
            *ppkey = NULL;
386
317
            EVP_PKEY_free(allocated_pkey);
387
317
        }
388
401
        return 0;
389
401
    }
390
    /* keydata is cached in *ppkey, so we need not bother with it further */
391
30.1k
    return 1;
392
30.5k
}
393
394
const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection)
395
0
{
396
    /* We call fromdata_init to get ctx->keymgmt populated */
397
0
    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED) == 1)
398
0
        return evp_keymgmt_import_types(ctx->keymgmt, selection);
399
0
    return NULL;
400
0
}
401
402
static OSSL_CALLBACK ossl_pkey_todata_cb;
403
404
static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg)
405
340
{
406
340
    OSSL_PARAM **ret = arg;
407
408
340
    *ret = OSSL_PARAM_dup(params);
409
340
    return 1;
410
340
}
411
412
int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params)
413
340
{
414
340
    if (params == NULL)
415
0
        return 0;
416
340
    return EVP_PKEY_export(pkey, selection, ossl_pkey_todata_cb, params);
417
340
}
418
419
#ifndef FIPS_MODULE
420
struct fake_import_data_st {
421
    OSSL_CALLBACK *export_cb;
422
    void *export_cbarg;
423
};
424
425
static OSSL_FUNC_keymgmt_import_fn pkey_fake_import;
426
static int pkey_fake_import(void *fake_keydata, int ignored_selection,
427
    const OSSL_PARAM params[])
428
0
{
429
0
    struct fake_import_data_st *data = fake_keydata;
430
431
0
    return data->export_cb(params, data->export_cbarg);
432
0
}
433
#endif
434
435
int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
436
    OSSL_CALLBACK *export_cb, void *export_cbarg)
437
98.9k
{
438
98.9k
    if (pkey == NULL) {
439
0
        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
440
0
        return 0;
441
0
    }
442
98.9k
#ifndef FIPS_MODULE
443
98.9k
    if (evp_pkey_is_legacy(pkey)) {
444
0
        struct fake_import_data_st data;
445
446
0
        data.export_cb = export_cb;
447
0
        data.export_cbarg = export_cbarg;
448
449
        /*
450
         * We don't need to care about libctx or propq here, as we're only
451
         * interested in the resulting OSSL_PARAM array.
452
         */
453
0
        return pkey->ameth->export_to(pkey, &data, pkey_fake_import,
454
0
            NULL, NULL);
455
0
    }
456
98.9k
#endif
457
98.9k
    return evp_keymgmt_util_export(pkey, selection, export_cb, export_cbarg);
458
98.9k
}