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
{
26 static int try_import(const OSSL_PARAM params
[], void *arg
)
28 struct import_data_st
*data
= arg
;
30 return evp_keymgmt_import(data
->keymgmt
, data
->keydata
, data
->selection
,
34 void *evp_keymgmt_util_export_to_provider(EVP_PKEY
*pk
, EVP_KEYMGMT
*keymgmt
)
40 * If there is an underlying legacy key and it has changed, invalidate
41 * the cache of provider keys.
43 if (pk
->pkey
.ptr
!= NULL
) {
45 * If there is no dirty counter, this key can't be used with
48 if (pk
->ameth
->dirty_cnt
== NULL
)
51 if (pk
->ameth
->dirty_cnt(pk
) != pk
->dirty_cnt_copy
)
52 evp_keymgmt_util_clear_pkey_cache(pk
);
56 * See if we have exported to this provider already.
57 * If we have, return immediately.
60 i
< OSSL_NELEM(pk
->pkeys
) && pk
->pkeys
[i
].keymgmt
!= NULL
;
62 if (keymgmt
== pk
->pkeys
[i
].keymgmt
)
63 return pk
->pkeys
[i
].keydata
;
66 if ((keydata
= evp_keymgmt_newdata(keymgmt
)) == NULL
)
69 if (pk
->pkey
.ptr
!= NULL
) {
70 /* There is a legacy key, try to export that one to the provider */
73 * If the legacy key doesn't have an export function or the export
74 * function fails, give up
76 if (pk
->ameth
->export_to
== NULL
77 || !pk
->ameth
->export_to(pk
, keydata
, keymgmt
)) {
78 evp_keymgmt_freedata(keymgmt
, keydata
);
82 /* Synchronize the dirty count */
83 pk
->dirty_cnt_copy
= pk
->ameth
->dirty_cnt(pk
);
86 * Here, there is no legacy key, so we look at the already cached
87 * provider keys, and import from the first that supports it
88 * (i.e. use its export function), and export the imported data to
92 /* Setup for the export callback */
93 struct import_data_st import_data
;
95 import_data
.keydata
= keydata
;
96 import_data
.keymgmt
= keymgmt
;
97 import_data
.selection
= OSSL_KEYMGMT_SELECT_ALL
;
99 for (j
= 0; j
< i
&& pk
->pkeys
[j
].keymgmt
!= NULL
; j
++) {
100 EVP_KEYMGMT
*exp_keymgmt
= pk
->pkeys
[i
].keymgmt
;
101 void *exp_keydata
= pk
->pkeys
[i
].keydata
;
104 * TODO(3.0) consider an evp_keymgmt_export() return value that
105 * indicates that the method is unsupported.
107 if (exp_keymgmt
->export
== NULL
)
111 * The export function calls the callback (try_import), which
112 * does the import for us. If successful, we're done.
114 if (evp_keymgmt_export(exp_keymgmt
, exp_keydata
,
115 OSSL_KEYMGMT_SELECT_ALL
,
116 &try_import
, &import_data
))
119 /* If there was an error, bail out */
120 evp_keymgmt_freedata(keymgmt
, keydata
);
126 * TODO(3.0) Right now, we assume we have ample space. We will
127 * have to think about a cache aging scheme, though, if |i| indexes
130 if (!ossl_assert(i
< OSSL_NELEM(pk
->pkeys
)))
133 evp_keymgmt_util_cache_pkey(pk
, i
, keymgmt
, keydata
);
138 void evp_keymgmt_util_clear_pkey_cache(EVP_PKEY
*pk
)
144 i
< OSSL_NELEM(pk
->pkeys
) && pk
->pkeys
[i
].keymgmt
!= NULL
;
146 EVP_KEYMGMT
*keymgmt
= pk
->pkeys
[i
].keymgmt
;
147 void *keydata
= pk
->pkeys
[i
].keydata
;
149 pk
->pkeys
[i
].keymgmt
= NULL
;
150 pk
->pkeys
[i
].keydata
= NULL
;
151 evp_keymgmt_freedata(keymgmt
, keydata
);
152 EVP_KEYMGMT_free(keymgmt
);
157 pk
->cache
.security_bits
= 0;
161 void evp_keymgmt_util_cache_pkey(EVP_PKEY
*pk
, size_t index
,
162 EVP_KEYMGMT
*keymgmt
, void *keydata
)
164 if (keydata
!= NULL
) {
165 EVP_KEYMGMT_up_ref(keymgmt
);
166 pk
->pkeys
[index
].keydata
= keydata
;
167 pk
->pkeys
[index
].keymgmt
= keymgmt
;
170 * Cache information about the key object. Only needed for the
171 * "original" provider side key.
173 * This services functions like EVP_PKEY_size, EVP_PKEY_bits, etc
177 int security_bits
= 0;
179 OSSL_PARAM params
[4];
181 params
[0] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_BITS
, &bits
);
182 params
[1] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_SECURITY_BITS
,
184 params
[2] = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_MAX_SIZE
,
186 params
[3] = OSSL_PARAM_construct_end();
187 if (evp_keymgmt_get_params(keymgmt
, keydata
, params
)) {
188 pk
->cache
.size
= size
;
189 pk
->cache
.bits
= bits
;
190 pk
->cache
.security_bits
= security_bits
;
196 void *evp_keymgmt_util_fromdata(EVP_PKEY
*target
, EVP_KEYMGMT
*keymgmt
,
197 int selection
, const OSSL_PARAM params
[])
199 void *keydata
= evp_keymgmt_newdata(keymgmt
);
201 if (keydata
!= NULL
) {
202 if (!evp_keymgmt_import(keymgmt
, keydata
, selection
, params
)) {
203 evp_keymgmt_freedata(keymgmt
, keydata
);
208 evp_keymgmt_util_clear_pkey_cache(target
);
209 evp_keymgmt_util_cache_pkey(target
, 0, keymgmt
, keydata
);