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 <openssl/core_names.h>
11 #include "internal/cryptlib.h"
12 #include "internal/nelem.h"
13 #include "crypto/evp.h"
14 #include "crypto/asn1.h"
15 #include "internal/core.h"
16 #include "internal/provider.h"
17 #include "evp_local.h"
19 struct import_data_st
{
21 void *(*importfn
)(const EVP_KEYMGMT
*keymgmt
, const OSSL_PARAM params
[]);
27 static int try_import(const OSSL_PARAM params
[], void *arg
)
29 struct import_data_st
*data
= arg
;
31 data
->provdata
= data
->importfn(data
->provctx
, params
);
32 return data
->provdata
!= NULL
;
35 void *evp_keymgmt_export_to_provider(EVP_PKEY
*pk
, EVP_KEYMGMT
*keymgmt
,
36 int want_domainparams
)
38 void *provdata
= NULL
;
42 * If there is an underlying legacy key and it has changed, invalidate
43 * the cache of provider keys.
45 if (pk
->pkey
.ptr
!= NULL
) {
47 * If there is no dirty counter, this key can't be used with
50 if (pk
->ameth
->dirty_cnt
== NULL
)
53 if (pk
->ameth
->dirty_cnt(pk
) != pk
->dirty_cnt_copy
)
54 evp_keymgmt_clear_pkey_cache(pk
);
58 * See if we have exported to this provider already.
59 * If we have, return immediately.
62 i
< OSSL_NELEM(pk
->pkeys
) && pk
->pkeys
[i
].keymgmt
!= NULL
;
64 if (keymgmt
== pk
->pkeys
[i
].keymgmt
65 && want_domainparams
== pk
->pkeys
[i
].domainparams
)
66 return pk
->pkeys
[i
].provdata
;
69 if (pk
->pkey
.ptr
!= NULL
) {
70 /* There is a legacy key, try to export that one to the provider */
72 /* If the legacy key doesn't have an export function, give up */
73 if (pk
->ameth
->export_to
== NULL
)
76 /* Otherwise, simply use it. */
77 provdata
= pk
->ameth
->export_to(pk
, keymgmt
, want_domainparams
);
79 /* Synchronize the dirty count, but only if we exported successfully */
81 pk
->dirty_cnt_copy
= pk
->ameth
->dirty_cnt(pk
);
85 * Here, there is no legacy key, so we look at the already cached
86 * provider keys, and import from the first that supports it
87 * (i.e. use its export function), and export the imported data to
91 /* Setup for the export callback */
92 struct import_data_st import_data
;
94 import_data
.importfn
=
96 ? evp_keymgmt_importdomparams
97 : evp_keymgmt_importkey
;
98 import_data
.provdata
= NULL
;
101 * If the given keymgmt doesn't have an import function, give up
103 if (import_data
.importfn
== NULL
)
106 for (j
= 0; j
< i
&& pk
->pkeys
[j
].keymgmt
!= NULL
; j
++) {
107 int (*exportfn
)(const EVP_KEYMGMT
*keymgmt
, void *provdata
,
108 OSSL_CALLBACK
*cb
, void *cbarg
) =
110 ? evp_keymgmt_exportdomparams
111 : evp_keymgmt_exportkey
;
113 if (exportfn
!= NULL
) {
114 import_data
.provctx
=
115 ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
118 * The export function calls the callback (try_import), which
119 * does the import for us.
120 * Even though we got a success return, we double check that
121 * we actually got something, just in case some implementation
122 * forgets to check the return value.
125 if (exportfn(pk
->pkeys
[j
].keymgmt
, pk
->pkeys
[j
].provdata
,
126 &try_import
, &import_data
)
127 && (provdata
= import_data
.provdata
) != NULL
)
134 * TODO(3.0) Right now, we assume we have ample space. We will
135 * have to think about a cache aging scheme, though, if |i| indexes
138 j
= ossl_assert(i
< OSSL_NELEM(pk
->pkeys
));
140 evp_keymgmt_cache_pkey(pk
, i
, keymgmt
, provdata
, 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 evp_keymgmt_freedomparams(keymgmt
, provdata
);
161 evp_keymgmt_freekey(keymgmt
, provdata
);
162 EVP_KEYMGMT_free(keymgmt
);
167 pk
->cache
.security_bits
= 0;
171 void evp_keymgmt_cache_pkey(EVP_PKEY
*pk
, size_t index
, EVP_KEYMGMT
*keymgmt
,
172 void *provdata
, int domainparams
)
174 if (provdata
!= NULL
) {
175 EVP_KEYMGMT_up_ref(keymgmt
);
176 pk
->pkeys
[index
].keymgmt
= keymgmt
;
177 pk
->pkeys
[index
].provdata
= provdata
;
178 pk
->pkeys
[index
].domainparams
= domainparams
;
181 * Cache information about the domain parameters or key. Only needed
182 * for the "original" provider side key.
184 * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
189 int security_bits
= 0;
191 OSSL_PARAM params
[4];
193 params
[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS
, &bits
);
194 params
[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS
,
196 params
[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE
, &size
);
197 params
[3] = OSSL_PARAM_construct_end();
199 ? evp_keymgmt_get_domparam_params(keymgmt
, provdata
, params
)
200 : evp_keymgmt_get_key_params(keymgmt
, provdata
, params
);
202 pk
->cache
.size
= size
;
203 pk
->cache
.bits
= bits
;
204 pk
->cache
.security_bits
= security_bits
;
210 void *evp_keymgmt_fromdata(EVP_PKEY
*target
, EVP_KEYMGMT
*keymgmt
,
211 const OSSL_PARAM params
[], int domainparams
)
213 void *provdata
= domainparams
214 ? evp_keymgmt_importdomparams(keymgmt
, params
)
215 : evp_keymgmt_importkey(keymgmt
, params
);
217 evp_keymgmt_clear_pkey_cache(target
);
218 evp_keymgmt_cache_pkey(target
, 0, keymgmt
, provdata
, domainparams
);
223 /* internal functions */
224 /* TODO(3.0) decide if these should be public or internal */
225 void *evp_keymgmt_importdomparams(const EVP_KEYMGMT
*keymgmt
,
226 const OSSL_PARAM params
[])
228 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
230 return keymgmt
->importdomparams(provctx
, params
);
233 void *evp_keymgmt_gendomparams(const EVP_KEYMGMT
*keymgmt
,
234 const OSSL_PARAM params
[])
236 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
238 return keymgmt
->gendomparams(provctx
, params
);
241 void evp_keymgmt_freedomparams(const EVP_KEYMGMT
*keymgmt
,
244 keymgmt
->freedomparams(provdomparams
);
247 int evp_keymgmt_exportdomparams(const EVP_KEYMGMT
*keymgmt
,
249 OSSL_CALLBACK
*param_cb
, void *cbarg
)
251 return keymgmt
->exportdomparams(provdomparams
, param_cb
, cbarg
);
254 const OSSL_PARAM
*evp_keymgmt_importdomparam_types(const EVP_KEYMGMT
*keymgmt
)
256 return keymgmt
->importdomparam_types();
260 * TODO(v3.0) investigate if we need this function. 'openssl provider' may
263 const OSSL_PARAM
*evp_keymgmt_exportdomparam_types(const EVP_KEYMGMT
*keymgmt
)
265 return keymgmt
->exportdomparam_types();
268 int evp_keymgmt_get_domparam_params(const EVP_KEYMGMT
*keymgmt
,
269 void *provdomparams
, OSSL_PARAM params
[])
271 if (keymgmt
->get_domparam_params
== NULL
)
273 return keymgmt
->get_domparam_params(provdomparams
, params
);
277 evp_keymgmt_gettable_domparam_params(const EVP_KEYMGMT
*keymgmt
)
279 if (keymgmt
->gettable_domparam_params
== NULL
)
281 return keymgmt
->gettable_domparam_params();
285 void *evp_keymgmt_importkey(const EVP_KEYMGMT
*keymgmt
,
286 const OSSL_PARAM params
[])
288 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
290 return keymgmt
->importkey(provctx
, params
);
293 void *evp_keymgmt_genkey(const EVP_KEYMGMT
*keymgmt
, void *domparams
,
294 const OSSL_PARAM params
[])
296 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
298 return keymgmt
->genkey(provctx
, domparams
, params
);
301 void *evp_keymgmt_loadkey(const EVP_KEYMGMT
*keymgmt
,
302 void *id
, size_t idlen
)
304 void *provctx
= ossl_provider_ctx(EVP_KEYMGMT_provider(keymgmt
));
306 return keymgmt
->loadkey(provctx
, id
, idlen
);
309 void evp_keymgmt_freekey(const EVP_KEYMGMT
*keymgmt
, void *provkey
)
311 keymgmt
->freekey(provkey
);
314 int evp_keymgmt_exportkey(const EVP_KEYMGMT
*keymgmt
, void *provkey
,
315 OSSL_CALLBACK
*param_cb
, void *cbarg
)
317 return keymgmt
->exportkey(provkey
, param_cb
, cbarg
);
320 const OSSL_PARAM
*evp_keymgmt_importkey_types(const EVP_KEYMGMT
*keymgmt
)
322 return keymgmt
->importkey_types();
326 * TODO(v3.0) investigate if we need this function. 'openssl provider' may
329 const OSSL_PARAM
*evp_keymgmt_exportkey_types(const EVP_KEYMGMT
*keymgmt
)
331 return keymgmt
->exportkey_types();
334 int evp_keymgmt_get_key_params(const EVP_KEYMGMT
*keymgmt
,
335 void *provkey
, OSSL_PARAM params
[])
337 if (keymgmt
->get_key_params
== NULL
)
339 return keymgmt
->get_key_params(provkey
, params
);
342 const OSSL_PARAM
*evp_keymgmt_gettable_key_params(const EVP_KEYMGMT
*keymgmt
)
344 if (keymgmt
->gettable_key_params
== NULL
)
346 return keymgmt
->gettable_key_params();
349 int evp_keymgmt_validate_domparams(const EVP_KEYMGMT
*keymgmt
, void *provkey
)
351 /* if domainparams are not supported - then pass */
352 if (keymgmt
->validatedomparams
== NULL
)
354 return keymgmt
->validatedomparams(provkey
);
357 int evp_keymgmt_validate_public(const EVP_KEYMGMT
*keymgmt
, void *provkey
)
359 return keymgmt
->validatepublic(provkey
);
362 int evp_keymgmt_validate_private(const EVP_KEYMGMT
*keymgmt
, void *provkey
)
364 return keymgmt
->validateprivate(provkey
);
367 int evp_keymgmt_validate_pairwise(const EVP_KEYMGMT
*keymgmt
, void *provkey
)
369 return keymgmt
->validatepairwise(provkey
);