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_util_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_util_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 if (!ossl_assert(i
< OSSL_NELEM(pk
->pkeys
)))
141 evp_keymgmt_util_cache_pkey(pk
, i
, keymgmt
, provdata
, want_domainparams
);
146 void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY
*pk
)
152 i
< OSSL_NELEM(pk
->pkeys
) && pk
->pkeys
[i
].keymgmt
!= NULL
;
154 EVP_KEYMGMT
*keymgmt
= pk
->pkeys
[i
].keymgmt
;
155 void *provdata
= pk
->pkeys
[i
].provdata
;
157 pk
->pkeys
[i
].keymgmt
= NULL
;
158 pk
->pkeys
[i
].provdata
= NULL
;
159 if (pk
->pkeys
[i
].domainparams
)
160 evp_keymgmt_freedomparams(keymgmt
, provdata
);
162 evp_keymgmt_freekey(keymgmt
, provdata
);
163 EVP_KEYMGMT_free(keymgmt
);
168 pk
->cache
.security_bits
= 0;
172 void evp_keymgmt_util_cache_pkey(EVP_PKEY
*pk
, size_t index
,
173 EVP_KEYMGMT
*keymgmt
, void *provdata
,
176 if (provdata
!= NULL
) {
177 EVP_KEYMGMT_up_ref(keymgmt
);
178 pk
->pkeys
[index
].keymgmt
= keymgmt
;
179 pk
->pkeys
[index
].provdata
= provdata
;
180 pk
->pkeys
[index
].domainparams
= domainparams
;
183 * Cache information about the domain parameters or key. Only needed
184 * for the "original" provider side key.
186 * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
191 int security_bits
= 0;
193 OSSL_PARAM params
[4];
195 params
[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS
, &bits
);
196 params
[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS
,
198 params
[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE
,
200 params
[3] = OSSL_PARAM_construct_end();
202 ? evp_keymgmt_get_domparam_params(keymgmt
, provdata
, params
)
203 : evp_keymgmt_get_key_params(keymgmt
, provdata
, params
);
205 pk
->cache
.size
= size
;
206 pk
->cache
.bits
= bits
;
207 pk
->cache
.security_bits
= security_bits
;
213 void *evp_keymgmt_util_fromdata(EVP_PKEY
*target
, EVP_KEYMGMT
*keymgmt
,
214 const OSSL_PARAM params
[], int domainparams
)
216 void *provdata
= domainparams
217 ? evp_keymgmt_importdomparams(keymgmt
, params
)
218 : evp_keymgmt_importkey(keymgmt
, params
);
220 evp_keymgmt_util_clear_pkey_cache(target
);
221 evp_keymgmt_util_cache_pkey(target
, 0, keymgmt
, provdata
, domainparams
);