1/*
2 * Copyright 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{-
10use OpenSSL::paramnames qw(produce_param_decoder);
11-}
12
13#include <string.h>
14#include <openssl/core_dispatch.h>
15#include <openssl/core_names.h>
16#include <openssl/proverr.h>
17#include "crypto/types.h"
18#include "internal/cryptlib.h"
19#include "internal/skey.h"
20#include "prov/provider_ctx.h"
21#include "prov/providercommon.h"
22#include "prov/implementations.h"
23#include "prov/skeymgmt_lcl.h"
24
25void generic_free(void *keydata)
26{
27    PROV_SKEY *generic = keydata;
28
29    if (generic == NULL)
30        return;
31
32    OPENSSL_clear_free(generic->data, generic->length);
33    OPENSSL_free(generic);
34}
35
36{- produce_param_decoder('generic_skey_import',
37                         (['SKEY_PARAM_RAW_BYTES',  'raw_bytes',    'octet_string'],
38                         )); -}
39
40void *generic_import(void *provctx, int selection, const OSSL_PARAM params[])
41{
42    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
43    struct generic_skey_import_st p;
44    PROV_SKEY *generic = NULL;
45    int ok = 0;
46
47    if (!ossl_prov_is_running())
48        return NULL;
49
50    if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0)
51        return NULL;
52
53    if (!generic_skey_import_decoder(params, &p))
54        return NULL;
55
56    if (p.raw_bytes == NULL
57            || p.raw_bytes->data_type != OSSL_PARAM_OCTET_STRING)
58        return NULL;
59
60    generic = OPENSSL_zalloc(sizeof(PROV_SKEY));
61    if (generic == NULL)
62        return NULL;
63
64    generic->libctx = libctx;
65
66    generic->type = SKEY_TYPE_GENERIC;
67
68    if ((generic->data = OPENSSL_memdup(p.raw_bytes->data,
69                                        p.raw_bytes->data_size)) == NULL)
70        goto end;
71    generic->length = p.raw_bytes->data_size;
72    ok = 1;
73
74end:
75    if (ok == 0) {
76        generic_free(generic);
77        generic = NULL;
78    }
79    return generic;
80}
81
82const OSSL_PARAM *generic_imp_settable_params(void *provctx)
83{
84    return generic_skey_import_list;
85}
86
87int generic_export(void *keydata, int selection,
88                   OSSL_CALLBACK *param_callback, void *cbarg)
89{
90    PROV_SKEY *gen = keydata;
91    OSSL_PARAM params[2];
92
93    if (!ossl_prov_is_running() || gen == NULL)
94        return 0;
95
96    /* If we use generic SKEYMGMT as a "base class", we shouldn't check the type */
97    if ((selection & OSSL_SKEYMGMT_SELECT_SECRET_KEY) == 0)
98        return 0;
99
100    params[0] = OSSL_PARAM_construct_octet_string(OSSL_SKEY_PARAM_RAW_BYTES,
101                                                  gen->data, gen->length);
102    params[1] = OSSL_PARAM_construct_end();
103
104    return param_callback(params, cbarg);
105}
106
107const OSSL_DISPATCH ossl_generic_skeymgmt_functions[] = {
108    { OSSL_FUNC_SKEYMGMT_FREE, (void (*)(void))generic_free },
109    { OSSL_FUNC_SKEYMGMT_IMPORT, (void (*)(void))generic_import },
110    { OSSL_FUNC_SKEYMGMT_EXPORT, (void (*)(void))generic_export },
111    { OSSL_FUNC_SKEYMGMT_IMP_SETTABLE_PARAMS,
112      (void (*)(void))generic_imp_settable_params },
113    OSSL_DISPATCH_END
114};
115