2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include "internal/cryptlib.h"
11 #include "internal/nelem.h"
12 #include "crypto/evp.h"
13 #include "crypto/asn1.h"
14 #include "internal/core.h"
15 #include "internal/provider.h"
16 #include "evp_local.h"
18 struct import_data_st
{
20 void *(*importfn
)(void *provctx
, const OSSL_PARAM params
[]);
26 static int try_import(const OSSL_PARAM params
[], void *arg
)
28 struct import_data_st
*data
= arg
;
30 data
->provdata
= data
->importfn(data
->provctx
, params
);
31 return data
->provdata
!= NULL
;
34 void *evp_keymgmt_export_to_provider(EVP_PKEY
*pk
, EVP_KEYMGMT
*keymgmt
,
35 int want_domainparams
)
37 void *provdata
= NULL
;
41 * If there is an underlying legacy key and it has changed, invalidate
42 * the cache of provider keys.
44 if (pk
->pkey
.ptr
!= NULL
) {
46 * If there is no dirty counter, this key can't be used with
49 if (pk
->ameth
->dirty_cnt
== NULL
)
52 if (pk
->ameth
->dirty_cnt(pk
) != pk
->dirty_cnt_copy
)
53 evp_keymgmt_clear_pkey_cache(pk
);
57 * See if we have exported to this provider already.
58 * If we have, return immediately.
61 i
< OSSL_NELEM(pk
->pkeys
) && pk
->pkeys
[i
].keymgmt
!= NULL
;
63 if (keymgmt
== pk
->pkeys
[i
].keymgmt
64 && want_domainparams
== pk
->pkeys
[i
].domainparams
)
65 return pk
->pkeys
[i
].provdata
;
68 if (pk
->pkey
.ptr
!= NULL
) {
69 /* There is a legacy key, try to export that one to the provider */
71 /* If the legacy key doesn't have an export function, give up */
72 if (pk
->ameth
->export_to
== NULL
)
75 /* Otherwise, simply use it. */
76 provdata
= pk
->ameth
->export_to(pk
, keymgmt
, want_domainparams
);
78 /* Synchronize the dirty count, but only if we exported successfully */
80 pk
->dirty_cnt_copy
= pk
->ameth
->dirty_cnt(pk
);
84 * Here, there is no legacy key, so we look at the already cached
85 * provider keys, and import from the first that supports it
86 * (i.e. use its export function), and export the imported data to
90 /* Setup for the export callback */
91 struct import_data_st import_data
;
93 import_data
.importfn
=
94 want_domainparams
? keymgmt
->importdomparams
: keymgmt
->importkey
;
95 import_data
.provdata
= NULL
;
98 * If the given keymgmt doesn't have an import function, give up
100 if (import_data
.importfn
== NULL
)
103 for (j
= 0; j
< i
&& pk
->pkeys
[j
].keymgmt
!= NULL
; j
++) {
104 int (*exportfn
)(void *provctx
, OSSL_CALLBACK
*cb
, void *cbarg
) =
106 ? pk
->pkeys
[j
].keymgmt
->exportdomparams
107 : pk
->pkeys
[j
].keymgmt
->exportkey
;
109 if (exportfn
!= NULL
) {
110 import_data
.provctx
=
111 ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
114 * The export function calls the callback (try_import), which
115 * does the import for us.
116 * Even though we got a success return, we double check that
117 * we actually got something, just in case some implementation
118 * forgets to check the return value.
121 if (exportfn(pk
->pkeys
[j
].provdata
, &try_import
, &import_data
)
122 && (provdata
= import_data
.provdata
) != NULL
)
129 * TODO(3.0) Right now, we assume we have ample space. We will
130 * have to think about a cache aging scheme, though, if |i| indexes
133 j
= ossl_assert(i
< OSSL_NELEM(pk
->pkeys
));
135 if (provdata
!= NULL
) {
136 EVP_KEYMGMT_up_ref(keymgmt
);
137 pk
->pkeys
[i
].keymgmt
= keymgmt
;
138 pk
->pkeys
[i
].provdata
= provdata
;
139 pk
->pkeys
[i
].domainparams
= want_domainparams
;
145 void evp_keymgmt_clear_pkey_cache(EVP_PKEY
*pk
)
151 i
< OSSL_NELEM(pk
->pkeys
) && pk
->pkeys
[i
].keymgmt
!= NULL
;
153 EVP_KEYMGMT
*keymgmt
= pk
->pkeys
[i
].keymgmt
;
154 void *provdata
= pk
->pkeys
[i
].provdata
;
156 pk
->pkeys
[i
].keymgmt
= NULL
;
157 pk
->pkeys
[i
].provdata
= NULL
;
158 if (pk
->pkeys
[i
].domainparams
)
159 keymgmt
->freedomparams(provdata
);
161 keymgmt
->freekey(provdata
);
162 EVP_KEYMGMT_free(keymgmt
);
167 void *evp_keymgmt_fromdata(EVP_PKEY
*target
, EVP_KEYMGMT
*keymgmt
,
168 const OSSL_PARAM params
[], int domainparams
)
170 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
171 void *provdata
= domainparams
172 ? keymgmt
->importdomparams(provctx
, params
)
173 : keymgmt
->importkey(provctx
, params
);
175 evp_keymgmt_clear_pkey_cache(target
);
176 if (provdata
!= NULL
) {
177 EVP_KEYMGMT_up_ref(keymgmt
);
178 target
->pkeys
[0].keymgmt
= keymgmt
;
179 target
->pkeys
[0].provdata
= provdata
;
180 target
->pkeys
[0].domainparams
= domainparams
;
186 /* internal functions */
187 /* TODO(3.0) decide if these should be public or internal */
188 void *evp_keymgmt_importdomparams(const EVP_KEYMGMT
*keymgmt
,
189 const OSSL_PARAM params
[])
191 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
193 return keymgmt
->importdomparams(provctx
, params
);
196 void *evp_keymgmt_gendomparams(const EVP_KEYMGMT
*keymgmt
,
197 const OSSL_PARAM params
[])
199 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
201 return keymgmt
->gendomparams(provctx
, params
);
204 void evp_keymgmt_freedomparams(const EVP_KEYMGMT
*keymgmt
,
207 keymgmt
->freedomparams(provdomparams
);
210 int evp_keymgmt_exportdomparams(const EVP_KEYMGMT
*keymgmt
,
212 OSSL_CALLBACK
*param_cb
, void *cbarg
)
214 return keymgmt
->exportdomparams(provdomparams
, param_cb
, cbarg
);
217 const OSSL_PARAM
*evp_keymgmt_importdomparam_types(const EVP_KEYMGMT
*keymgmt
)
219 return keymgmt
->importdomparam_types();
223 * TODO(v3.0) investigate if we need this function. 'openssl provider' may
226 const OSSL_PARAM
*evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT
*keymgmt
)
228 return keymgmt
->exportdomparam_types();
232 void *evp_keymgmt_importkey(const EVP_KEYMGMT
*keymgmt
,
233 const OSSL_PARAM params
[])
235 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
237 return keymgmt
->importkey(provctx
, params
);
240 void *evp_keymgmt_genkey(const EVP_KEYMGMT
*keymgmt
, void *domparams
,
241 const OSSL_PARAM params
[])
243 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
245 return keymgmt
->genkey(provctx
, domparams
, params
);
248 void *evp_keymgmt_loadkey(const EVP_KEYMGMT
*keymgmt
,
249 void *id
, size_t idlen
)
251 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
253 return keymgmt
->loadkey(provctx
, id
, idlen
);
256 void evp_keymgmt_freekey(const EVP_KEYMGMT
*keymgmt
, void *provkey
)
258 keymgmt
->freekey(provkey
);
261 int evp_keymgmt_exportkey(const EVP_KEYMGMT
*keymgmt
, void *provkey
,
262 OSSL_CALLBACK
*param_cb
, void *cbarg
)
264 return keymgmt
->exportkey(provkey
, param_cb
, cbarg
);
267 const OSSL_PARAM
*evp_keymgmt_importkey_types(const EVP_KEYMGMT
*keymgmt
)
269 return keymgmt
->importkey_types();
273 * TODO(v3.0) investigate if we need this function. 'openssl provider' may
276 const OSSL_PARAM
*evp_keymgmt_exportkey_types(const EVP_KEYMGMT
*keymgmt
)
278 return keymgmt
->exportkey_types();