Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl33/crypto/evp/keymgmt_meth.c
Line
Count
Source
1
/*
2
 * Copyright 2019-2024 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 <openssl/crypto.h>
11
#include <openssl/core_dispatch.h>
12
#include <openssl/evp.h>
13
#include <openssl/err.h>
14
#include "internal/provider.h"
15
#include "internal/refcount.h"
16
#include "internal/core.h"
17
#include "crypto/evp.h"
18
#include "evp_local.h"
19
20
static void *keymgmt_new(void)
21
2.47k
{
22
2.47k
    EVP_KEYMGMT *keymgmt = NULL;
23
24
2.47k
    if ((keymgmt = OPENSSL_zalloc(sizeof(*keymgmt))) == NULL)
25
0
        return NULL;
26
2.47k
    if (!CRYPTO_NEW_REF(&keymgmt->refcnt, 1)) {
27
0
        EVP_KEYMGMT_free(keymgmt);
28
0
        return NULL;
29
0
    }
30
2.47k
    return keymgmt;
31
2.47k
}
32
33
#ifndef FIPS_MODULE
34
static void help_get_legacy_alg_type_from_keymgmt(const char *keytype,
35
    void *arg)
36
6.58k
{
37
6.58k
    int *type = arg;
38
39
6.58k
    if (*type == NID_undef)
40
4.82k
        *type = evp_pkey_name2type(keytype);
41
6.58k
}
42
43
static int get_legacy_alg_type_from_keymgmt(const EVP_KEYMGMT *keymgmt)
44
2.47k
{
45
2.47k
    int type = NID_undef;
46
47
2.47k
    EVP_KEYMGMT_names_do_all(keymgmt, help_get_legacy_alg_type_from_keymgmt,
48
2.47k
        &type);
49
2.47k
    return type;
50
2.47k
}
51
#endif
52
53
static void *keymgmt_from_algorithm(int name_id,
54
    const OSSL_ALGORITHM *algodef,
55
    OSSL_PROVIDER *prov)
56
198
{
57
198
    const OSSL_DISPATCH *fns = algodef->implementation;
58
198
    EVP_KEYMGMT *keymgmt = NULL;
59
198
    int setparamfncnt = 0, getparamfncnt = 0;
60
198
    int setgenparamfncnt = 0;
61
198
    int importfncnt = 0, exportfncnt = 0;
62
198
    int importtypesfncnt = 0, exporttypesfncnt = 0;
63
64
198
    if ((keymgmt = keymgmt_new()) == NULL)
65
0
        return NULL;
66
67
198
    keymgmt->name_id = name_id;
68
198
    if ((keymgmt->type_name = ossl_algorithm_get1_first_name(algodef)) == NULL) {
69
0
        EVP_KEYMGMT_free(keymgmt);
70
0
        return NULL;
71
0
    }
72
198
    keymgmt->description = algodef->algorithm_description;
73
74
3.49k
    for (; fns->function_id != 0; fns++) {
75
3.30k
        switch (fns->function_id) {
76
198
        case OSSL_FUNC_KEYMGMT_NEW:
77
198
            if (keymgmt->new == NULL)
78
198
                keymgmt->new = OSSL_FUNC_keymgmt_new(fns);
79
198
            break;
80
165
        case OSSL_FUNC_KEYMGMT_GEN_INIT:
81
165
            if (keymgmt->gen_init == NULL)
82
165
                keymgmt->gen_init = OSSL_FUNC_keymgmt_gen_init(fns);
83
165
            break;
84
55
        case OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE:
85
55
            if (keymgmt->gen_set_template == NULL)
86
55
                keymgmt->gen_set_template = OSSL_FUNC_keymgmt_gen_set_template(fns);
87
55
            break;
88
165
        case OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS:
89
165
            if (keymgmt->gen_set_params == NULL) {
90
165
                setgenparamfncnt++;
91
165
                keymgmt->gen_set_params = OSSL_FUNC_keymgmt_gen_set_params(fns);
92
165
            }
93
165
            break;
94
165
        case OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS:
95
165
            if (keymgmt->gen_settable_params == NULL) {
96
165
                setgenparamfncnt++;
97
165
                keymgmt->gen_settable_params = OSSL_FUNC_keymgmt_gen_settable_params(fns);
98
165
            }
99
165
            break;
100
165
        case OSSL_FUNC_KEYMGMT_GEN:
101
165
            if (keymgmt->gen == NULL)
102
165
                keymgmt->gen = OSSL_FUNC_keymgmt_gen(fns);
103
165
            break;
104
165
        case OSSL_FUNC_KEYMGMT_GEN_CLEANUP:
105
165
            if (keymgmt->gen_cleanup == NULL)
106
165
                keymgmt->gen_cleanup = OSSL_FUNC_keymgmt_gen_cleanup(fns);
107
165
            break;
108
198
        case OSSL_FUNC_KEYMGMT_FREE:
109
198
            if (keymgmt->free == NULL)
110
198
                keymgmt->free = OSSL_FUNC_keymgmt_free(fns);
111
198
            break;
112
121
        case OSSL_FUNC_KEYMGMT_LOAD:
113
121
            if (keymgmt->load == NULL)
114
121
                keymgmt->load = OSSL_FUNC_keymgmt_load(fns);
115
121
            break;
116
165
        case OSSL_FUNC_KEYMGMT_GET_PARAMS:
117
165
            if (keymgmt->get_params == NULL) {
118
165
                getparamfncnt++;
119
165
                keymgmt->get_params = OSSL_FUNC_keymgmt_get_params(fns);
120
165
            }
121
165
            break;
122
165
        case OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS:
123
165
            if (keymgmt->gettable_params == NULL) {
124
165
                getparamfncnt++;
125
165
                keymgmt->gettable_params = OSSL_FUNC_keymgmt_gettable_params(fns);
126
165
            }
127
165
            break;
128
132
        case OSSL_FUNC_KEYMGMT_SET_PARAMS:
129
132
            if (keymgmt->set_params == NULL) {
130
132
                setparamfncnt++;
131
132
                keymgmt->set_params = OSSL_FUNC_keymgmt_set_params(fns);
132
132
            }
133
132
            break;
134
132
        case OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS:
135
132
            if (keymgmt->settable_params == NULL) {
136
132
                setparamfncnt++;
137
132
                keymgmt->settable_params = OSSL_FUNC_keymgmt_settable_params(fns);
138
132
            }
139
132
            break;
140
44
        case OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME:
141
44
            if (keymgmt->query_operation_name == NULL)
142
44
                keymgmt->query_operation_name = OSSL_FUNC_keymgmt_query_operation_name(fns);
143
44
            break;
144
198
        case OSSL_FUNC_KEYMGMT_HAS:
145
198
            if (keymgmt->has == NULL)
146
198
                keymgmt->has = OSSL_FUNC_keymgmt_has(fns);
147
198
            break;
148
121
        case OSSL_FUNC_KEYMGMT_DUP:
149
121
            if (keymgmt->dup == NULL)
150
121
                keymgmt->dup = OSSL_FUNC_keymgmt_dup(fns);
151
121
            break;
152
121
        case OSSL_FUNC_KEYMGMT_VALIDATE:
153
121
            if (keymgmt->validate == NULL)
154
121
                keymgmt->validate = OSSL_FUNC_keymgmt_validate(fns);
155
121
            break;
156
165
        case OSSL_FUNC_KEYMGMT_MATCH:
157
165
            if (keymgmt->match == NULL)
158
165
                keymgmt->match = OSSL_FUNC_keymgmt_match(fns);
159
165
            break;
160
165
        case OSSL_FUNC_KEYMGMT_IMPORT:
161
165
            if (keymgmt->import == NULL) {
162
165
                importfncnt++;
163
165
                keymgmt->import = OSSL_FUNC_keymgmt_import(fns);
164
165
            }
165
165
            break;
166
165
        case OSSL_FUNC_KEYMGMT_IMPORT_TYPES:
167
165
            if (keymgmt->import_types == NULL) {
168
165
                if (importtypesfncnt == 0)
169
165
                    importfncnt++;
170
165
                importtypesfncnt++;
171
165
                keymgmt->import_types = OSSL_FUNC_keymgmt_import_types(fns);
172
165
            }
173
165
            break;
174
0
        case OSSL_FUNC_KEYMGMT_IMPORT_TYPES_EX:
175
0
            if (keymgmt->import_types_ex == NULL) {
176
0
                if (importtypesfncnt == 0)
177
0
                    importfncnt++;
178
0
                importtypesfncnt++;
179
0
                keymgmt->import_types_ex = OSSL_FUNC_keymgmt_import_types_ex(fns);
180
0
            }
181
0
            break;
182
165
        case OSSL_FUNC_KEYMGMT_EXPORT:
183
165
            if (keymgmt->export == NULL) {
184
165
                exportfncnt++;
185
165
                keymgmt->export = OSSL_FUNC_keymgmt_export(fns);
186
165
            }
187
165
            break;
188
165
        case OSSL_FUNC_KEYMGMT_EXPORT_TYPES:
189
165
            if (keymgmt->export_types == NULL) {
190
165
                if (exporttypesfncnt == 0)
191
165
                    exportfncnt++;
192
165
                exporttypesfncnt++;
193
165
                keymgmt->export_types = OSSL_FUNC_keymgmt_export_types(fns);
194
165
            }
195
165
            break;
196
0
        case OSSL_FUNC_KEYMGMT_EXPORT_TYPES_EX:
197
0
            if (keymgmt->export_types_ex == NULL) {
198
0
                if (exporttypesfncnt == 0)
199
0
                    exportfncnt++;
200
0
                exporttypesfncnt++;
201
0
                keymgmt->export_types_ex = OSSL_FUNC_keymgmt_export_types_ex(fns);
202
0
            }
203
0
            break;
204
3.30k
        }
205
3.30k
    }
206
    /*
207
     * Try to check that the method is sensible.
208
     * At least one constructor and the destructor are MANDATORY
209
     * The functions 'has' is MANDATORY
210
     * It makes no sense being able to free stuff if you can't create it.
211
     * It makes no sense providing OSSL_PARAM descriptors for import and
212
     * export if you can't import or export.
213
     */
214
198
    if (keymgmt->free == NULL
215
198
        || (keymgmt->new == NULL
216
0
            && keymgmt->gen == NULL
217
0
            && keymgmt->load == NULL)
218
198
        || keymgmt->has == NULL
219
198
        || (getparamfncnt != 0 && getparamfncnt != 2)
220
198
        || (setparamfncnt != 0 && setparamfncnt != 2)
221
198
        || (setgenparamfncnt != 0 && setgenparamfncnt != 2)
222
198
        || (importfncnt != 0 && importfncnt != 2)
223
198
        || (exportfncnt != 0 && exportfncnt != 2)
224
198
        || (keymgmt->gen != NULL
225
165
            && (keymgmt->gen_init == NULL
226
165
                || keymgmt->gen_cleanup == NULL))) {
227
0
        EVP_KEYMGMT_free(keymgmt);
228
0
        ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_PROVIDER_FUNCTIONS);
229
0
        return NULL;
230
0
    }
231
198
    keymgmt->prov = prov;
232
198
    if (prov != NULL)
233
198
        ossl_provider_up_ref(prov);
234
235
198
#ifndef FIPS_MODULE
236
198
    keymgmt->legacy_alg = get_legacy_alg_type_from_keymgmt(keymgmt);
237
198
#endif
238
239
198
    return keymgmt;
240
198
}
241
242
EVP_KEYMGMT *evp_keymgmt_fetch_from_prov(OSSL_PROVIDER *prov,
243
    const char *name,
244
    const char *properties)
245
217k
{
246
217k
    return evp_generic_fetch_from_prov(prov, OSSL_OP_KEYMGMT,
247
217k
        name, properties,
248
217k
        keymgmt_from_algorithm,
249
217k
        (int (*)(void *))EVP_KEYMGMT_up_ref,
250
217k
        (void (*)(void *))EVP_KEYMGMT_free);
251
217k
}
252
253
EVP_KEYMGMT *EVP_KEYMGMT_fetch(OSSL_LIB_CTX *ctx, const char *algorithm,
254
    const char *properties)
255
14.1M
{
256
14.1M
    return evp_generic_fetch(ctx, OSSL_OP_KEYMGMT, algorithm, properties,
257
14.1M
        keymgmt_from_algorithm,
258
14.1M
        (int (*)(void *))EVP_KEYMGMT_up_ref,
259
14.1M
        (void (*)(void *))EVP_KEYMGMT_free);
260
14.1M
}
261
262
int EVP_KEYMGMT_up_ref(EVP_KEYMGMT *keymgmt)
263
30.1M
{
264
30.1M
    int ref = 0;
265
266
30.1M
    CRYPTO_UP_REF(&keymgmt->refcnt, &ref);
267
30.1M
    return 1;
268
30.1M
}
269
270
void EVP_KEYMGMT_free(EVP_KEYMGMT *keymgmt)
271
30.9M
{
272
30.9M
    int ref = 0;
273
274
30.9M
    if (keymgmt == NULL)
275
850k
        return;
276
277
30.1M
    CRYPTO_DOWN_REF(&keymgmt->refcnt, &ref);
278
30.1M
    if (ref > 0)
279
30.1M
        return;
280
1.70k
    OPENSSL_free(keymgmt->type_name);
281
1.70k
    ossl_provider_free(keymgmt->prov);
282
1.70k
    CRYPTO_FREE_REF(&keymgmt->refcnt);
283
1.70k
    OPENSSL_free(keymgmt);
284
1.70k
}
285
286
const OSSL_PROVIDER *EVP_KEYMGMT_get0_provider(const EVP_KEYMGMT *keymgmt)
287
6.22M
{
288
6.22M
    return keymgmt->prov;
289
6.22M
}
290
291
int evp_keymgmt_get_number(const EVP_KEYMGMT *keymgmt)
292
0
{
293
0
    return keymgmt->name_id;
294
0
}
295
296
int evp_keymgmt_get_legacy_alg(const EVP_KEYMGMT *keymgmt)
297
4.58M
{
298
4.58M
    return keymgmt->legacy_alg;
299
4.58M
}
300
301
const char *EVP_KEYMGMT_get0_description(const EVP_KEYMGMT *keymgmt)
302
0
{
303
0
    return keymgmt->description;
304
0
}
305
306
const char *EVP_KEYMGMT_get0_name(const EVP_KEYMGMT *keymgmt)
307
684k
{
308
684k
    return keymgmt->type_name;
309
684k
}
310
311
int EVP_KEYMGMT_is_a(const EVP_KEYMGMT *keymgmt, const char *name)
312
8.64M
{
313
8.64M
    return keymgmt != NULL
314
8.64M
        && evp_is_a(keymgmt->prov, keymgmt->name_id, NULL, name);
315
8.64M
}
316
317
void EVP_KEYMGMT_do_all_provided(OSSL_LIB_CTX *libctx,
318
    void (*fn)(EVP_KEYMGMT *keymgmt, void *arg),
319
    void *arg)
320
278k
{
321
278k
    evp_generic_do_all(libctx, OSSL_OP_KEYMGMT,
322
278k
        (void (*)(void *, void *))fn, arg,
323
278k
        keymgmt_from_algorithm,
324
278k
        (int (*)(void *))EVP_KEYMGMT_up_ref,
325
278k
        (void (*)(void *))EVP_KEYMGMT_free);
326
278k
}
327
328
int EVP_KEYMGMT_names_do_all(const EVP_KEYMGMT *keymgmt,
329
    void (*fn)(const char *name, void *data),
330
    void *data)
331
2.56M
{
332
2.56M
    if (keymgmt->prov != NULL)
333
2.56M
        return evp_names_do_all(keymgmt->prov, keymgmt->name_id, fn, data);
334
335
0
    return 1;
336
2.56M
}
337
338
/*
339
 * Internal API that interfaces with the method function pointers
340
 */
341
void *evp_keymgmt_newdata(const EVP_KEYMGMT *keymgmt)
342
184k
{
343
184k
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
344
345
    /*
346
     * 'new' is currently mandatory on its own, but when new
347
     * constructors appear, it won't be quite as mandatory,
348
     * so we have a check for future cases.
349
     */
350
184k
    if (keymgmt->new == NULL)
351
0
        return NULL;
352
184k
    return keymgmt->new(provctx);
353
184k
}
354
355
void evp_keymgmt_freedata(const EVP_KEYMGMT *keymgmt, void *keydata)
356
1.19M
{
357
    /* This is mandatory, no need to check for its presence */
358
1.19M
    keymgmt->free(keydata);
359
1.19M
}
360
361
void *evp_keymgmt_gen_init(const EVP_KEYMGMT *keymgmt, int selection,
362
    const OSSL_PARAM params[])
363
276k
{
364
276k
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
365
366
276k
    if (keymgmt->gen_init == NULL)
367
0
        return NULL;
368
276k
    return keymgmt->gen_init(provctx, selection, params);
369
276k
}
370
371
int evp_keymgmt_gen_set_template(const EVP_KEYMGMT *keymgmt, void *genctx,
372
    void *templ)
373
10.7k
{
374
    /*
375
     * It's arguable if we actually should return success in this case, as
376
     * it allows the caller to set a template key, which is then ignored.
377
     * However, this is how the legacy methods (EVP_PKEY_METHOD) operate,
378
     * so we do this in the interest of backward compatibility.
379
     */
380
10.7k
    if (keymgmt->gen_set_template == NULL)
381
4.04k
        return 1;
382
6.74k
    return keymgmt->gen_set_template(genctx, templ);
383
10.7k
}
384
385
int evp_keymgmt_gen_set_params(const EVP_KEYMGMT *keymgmt, void *genctx,
386
    const OSSL_PARAM params[])
387
261k
{
388
261k
    if (keymgmt->gen_set_params == NULL)
389
0
        return 0;
390
261k
    return keymgmt->gen_set_params(genctx, params);
391
261k
}
392
393
const OSSL_PARAM *EVP_KEYMGMT_gen_settable_params(const EVP_KEYMGMT *keymgmt)
394
0
{
395
0
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
396
397
0
    if (keymgmt->gen_settable_params == NULL)
398
0
        return NULL;
399
0
    return keymgmt->gen_settable_params(NULL, provctx);
400
0
}
401
402
void *evp_keymgmt_gen(const EVP_KEYMGMT *keymgmt, void *genctx,
403
    OSSL_CALLBACK *cb, void *cbarg)
404
57.8k
{
405
57.8k
    if (keymgmt->gen == NULL)
406
0
        return NULL;
407
57.8k
    return keymgmt->gen(genctx, cb, cbarg);
408
57.8k
}
409
410
void evp_keymgmt_gen_cleanup(const EVP_KEYMGMT *keymgmt, void *genctx)
411
276k
{
412
276k
    if (keymgmt->gen_cleanup != NULL)
413
276k
        keymgmt->gen_cleanup(genctx);
414
276k
}
415
416
int evp_keymgmt_has_load(const EVP_KEYMGMT *keymgmt)
417
2.01M
{
418
2.01M
    return keymgmt != NULL && keymgmt->load != NULL;
419
2.01M
}
420
421
void *evp_keymgmt_load(const EVP_KEYMGMT *keymgmt,
422
    const void *objref, size_t objref_sz)
423
681k
{
424
681k
    if (evp_keymgmt_has_load(keymgmt))
425
681k
        return keymgmt->load(objref, objref_sz);
426
0
    return NULL;
427
681k
}
428
429
int evp_keymgmt_get_params(const EVP_KEYMGMT *keymgmt, void *keydata,
430
    OSSL_PARAM params[])
431
1.42M
{
432
1.42M
    if (keymgmt->get_params == NULL)
433
0
        return 1;
434
1.42M
    return keymgmt->get_params(keydata, params);
435
1.42M
}
436
437
const OSSL_PARAM *EVP_KEYMGMT_gettable_params(const EVP_KEYMGMT *keymgmt)
438
0
{
439
0
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
440
441
0
    if (keymgmt->gettable_params == NULL)
442
0
        return NULL;
443
0
    return keymgmt->gettable_params(provctx);
444
0
}
445
446
int evp_keymgmt_set_params(const EVP_KEYMGMT *keymgmt, void *keydata,
447
    const OSSL_PARAM params[])
448
43.8k
{
449
43.8k
    if (keymgmt->set_params == NULL)
450
0
        return 1;
451
43.8k
    return keymgmt->set_params(keydata, params);
452
43.8k
}
453
454
const OSSL_PARAM *EVP_KEYMGMT_settable_params(const EVP_KEYMGMT *keymgmt)
455
0
{
456
0
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
457
458
0
    if (keymgmt->settable_params == NULL)
459
0
        return NULL;
460
0
    return keymgmt->settable_params(provctx);
461
0
}
462
463
int evp_keymgmt_has(const EVP_KEYMGMT *keymgmt, void *keydata, int selection)
464
579k
{
465
    /* This is mandatory, no need to check for its presence */
466
579k
    return keymgmt->has(keydata, selection);
467
579k
}
468
469
int evp_keymgmt_validate(const EVP_KEYMGMT *keymgmt, void *keydata,
470
    int selection, int checktype)
471
138k
{
472
    /* We assume valid if the implementation doesn't have a function */
473
138k
    if (keymgmt->validate == NULL)
474
0
        return 1;
475
138k
    return keymgmt->validate(keydata, selection, checktype);
476
138k
}
477
478
int evp_keymgmt_match(const EVP_KEYMGMT *keymgmt,
479
    const void *keydata1, const void *keydata2,
480
    int selection)
481
329k
{
482
    /* We assume no match if the implementation doesn't have a function */
483
329k
    if (keymgmt->match == NULL)
484
0
        return 0;
485
329k
    return keymgmt->match(keydata1, keydata2, selection);
486
329k
}
487
488
int evp_keymgmt_import(const EVP_KEYMGMT *keymgmt, void *keydata,
489
    int selection, const OSSL_PARAM params[])
490
30.5k
{
491
30.5k
    if (keymgmt->import == NULL)
492
0
        return 0;
493
30.5k
    return keymgmt->import(keydata, selection, params);
494
30.5k
}
495
496
const OSSL_PARAM *evp_keymgmt_import_types(const EVP_KEYMGMT *keymgmt,
497
    int selection)
498
0
{
499
0
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
500
501
0
    if (keymgmt->import_types_ex != NULL)
502
0
        return keymgmt->import_types_ex(provctx, selection);
503
0
    if (keymgmt->import_types == NULL)
504
0
        return NULL;
505
0
    return keymgmt->import_types(selection);
506
0
}
507
508
int evp_keymgmt_export(const EVP_KEYMGMT *keymgmt, void *keydata,
509
    int selection, OSSL_CALLBACK *param_cb, void *cbarg)
510
223k
{
511
223k
    if (keymgmt->export == NULL)
512
0
        return 0;
513
223k
    return keymgmt->export(keydata, selection, param_cb, cbarg);
514
223k
}
515
516
const OSSL_PARAM *evp_keymgmt_export_types(const EVP_KEYMGMT *keymgmt,
517
    int selection)
518
0
{
519
0
    void *provctx = ossl_provider_ctx(EVP_KEYMGMT_get0_provider(keymgmt));
520
521
0
    if (keymgmt->export_types_ex != NULL)
522
0
        return keymgmt->export_types_ex(provctx, selection);
523
0
    if (keymgmt->export_types == NULL)
524
0
        return NULL;
525
0
    return keymgmt->export_types(selection);
526
0
}
527
528
void *evp_keymgmt_dup(const EVP_KEYMGMT *keymgmt, const void *keydata_from,
529
    int selection)
530
52.8k
{
531
    /* We assume no dup if the implementation doesn't have a function */
532
52.8k
    if (keymgmt->dup == NULL)
533
0
        return NULL;
534
52.8k
    return keymgmt->dup(keydata_from, selection);
535
52.8k
}