pkcs11: Use callback registration for pkcs11-manager.
[strongswan.git] / src / libstrongswan / plugins / pkcs11 / pkcs11_plugin.c
1 /*
2 * Copyright (C) 2011 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "pkcs11_plugin.h"
20
21 #include <library.h>
22 #include <debug.h>
23 #include <utils/linked_list.h>
24 #include <threading/mutex.h>
25
26 #include "pkcs11_manager.h"
27 #include "pkcs11_creds.h"
28 #include "pkcs11_private_key.h"
29 #include "pkcs11_public_key.h"
30 #include "pkcs11_hasher.h"
31 #include "pkcs11_rng.h"
32 #include "pkcs11_dh.h"
33
34 typedef struct private_pkcs11_plugin_t private_pkcs11_plugin_t;
35
36 /**
37 * private data of pkcs11_plugin
38 */
39 struct private_pkcs11_plugin_t {
40
41 /**
42 * public functions
43 */
44 pkcs11_plugin_t public;
45
46 /**
47 * PKCS#11 library/slot manager
48 */
49 pkcs11_manager_t *manager;
50
51 /**
52 * List of credential sets, pkcs11_creds_t
53 */
54 linked_list_t *creds;
55
56 /**
57 * mutex to lock list
58 */
59 mutex_t *mutex;
60 };
61
62 /**
63 * Token event callback function
64 */
65 static void token_event_cb(private_pkcs11_plugin_t *this, pkcs11_library_t *p11,
66 CK_SLOT_ID slot, bool add)
67 {
68 enumerator_t *enumerator;
69 pkcs11_creds_t *creds, *found = NULL;;
70
71 if (add)
72 {
73 creds = pkcs11_creds_create(p11, slot);
74 if (creds)
75 {
76 this->mutex->lock(this->mutex);
77 this->creds->insert_last(this->creds, creds);
78 this->mutex->unlock(this->mutex);
79 lib->credmgr->add_set(lib->credmgr, &creds->set);
80 }
81 }
82 else
83 {
84 this->mutex->lock(this->mutex);
85 enumerator = this->creds->create_enumerator(this->creds);
86 while (enumerator->enumerate(enumerator, &creds))
87 {
88 if (creds->get_library(creds) == p11 &&
89 creds->get_slot(creds) == slot)
90 {
91 found = creds;
92 this->creds->remove_at(this->creds, enumerator);
93 break;
94 }
95 }
96 enumerator->destroy(enumerator);
97 this->mutex->unlock(this->mutex);
98
99 if (found)
100 {
101 lib->credmgr->remove_set(lib->credmgr, &found->set);
102 found->destroy(found);
103 /* flush the cache after a token is gone */
104 lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
105 }
106 }
107 }
108
109 METHOD(plugin_t, get_name, char*,
110 private_pkcs11_plugin_t *this)
111 {
112 return "pkcs11";
113 }
114
115 /**
116 * Register/unregister PKCS#11 manager.
117 */
118 static bool register_manager(private_pkcs11_plugin_t *this,
119 plugin_feature_t *feature, bool reg, void *data)
120 {
121 if (reg)
122 {
123 enumerator_t *enumerator;
124 pkcs11_library_t *p11;
125 CK_SLOT_ID slot;
126
127 this->manager = pkcs11_manager_create((void*)token_event_cb, this);
128 lib->set(lib, "pkcs11-manager", this->manager);
129
130 enumerator = this->manager->create_token_enumerator(this->manager);
131 while (enumerator->enumerate(enumerator, &p11, &slot))
132 {
133 token_event_cb(this, p11, slot, TRUE);
134 }
135 enumerator->destroy(enumerator);
136 }
137 else
138 {
139 pkcs11_creds_t *creds;
140
141 while (this->creds->remove_last(this->creds, (void**)&creds) == SUCCESS)
142 {
143 lib->credmgr->remove_set(lib->credmgr, &creds->set);
144 creds->destroy(creds);
145 }
146
147 lib->set(lib, "pkcs11-manager", NULL);
148 this->manager->destroy(this->manager);
149 }
150 return TRUE;
151 }
152
153 /**
154 * Add a set of features
155 */
156 static inline void add_features(plugin_feature_t *f, plugin_feature_t *n,
157 int count, int *pos)
158 {
159 int i;
160 for (i = 0; i < count; i++)
161 {
162 f[(*pos)++] = n[i];
163 }
164 }
165
166 METHOD(plugin_t, get_features, int,
167 private_pkcs11_plugin_t *this, plugin_feature_t *features[])
168 {
169 static plugin_feature_t f_hash[] = {
170 PLUGIN_REGISTER(HASHER, pkcs11_hasher_create),
171 PLUGIN_PROVIDE(HASHER, HASH_MD2),
172 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
173 PLUGIN_PROVIDE(HASHER, HASH_MD5),
174 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
175 PLUGIN_PROVIDE(HASHER, HASH_SHA1),
176 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
177 PLUGIN_PROVIDE(HASHER, HASH_SHA256),
178 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
179 PLUGIN_PROVIDE(HASHER, HASH_SHA384),
180 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
181 PLUGIN_PROVIDE(HASHER, HASH_SHA512),
182 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
183 };
184 static plugin_feature_t f_dh[] = {
185 PLUGIN_REGISTER(DH, pkcs11_dh_create),
186 PLUGIN_PROVIDE(DH, MODP_2048_BIT),
187 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
188 PLUGIN_PROVIDE(DH, MODP_2048_224),
189 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
190 PLUGIN_PROVIDE(DH, MODP_2048_256),
191 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
192 PLUGIN_PROVIDE(DH, MODP_1536_BIT),
193 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
194 PLUGIN_PROVIDE(DH, MODP_3072_BIT),
195 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
196 PLUGIN_PROVIDE(DH, MODP_4096_BIT),
197 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
198 PLUGIN_PROVIDE(DH, MODP_6144_BIT),
199 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
200 PLUGIN_PROVIDE(DH, MODP_8192_BIT),
201 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
202 PLUGIN_PROVIDE(DH, MODP_1024_BIT),
203 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
204 PLUGIN_PROVIDE(DH, MODP_1024_160),
205 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
206 PLUGIN_PROVIDE(DH, MODP_768_BIT),
207 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
208 PLUGIN_PROVIDE(DH, MODP_CUSTOM),
209 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
210 };
211 static plugin_feature_t f_rng[] = {
212 PLUGIN_REGISTER(RNG, pkcs11_rng_create),
213 PLUGIN_PROVIDE(RNG, RNG_STRONG),
214 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
215 PLUGIN_PROVIDE(RNG, RNG_TRUE),
216 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
217 };
218 static plugin_feature_t f_key[] = {
219 PLUGIN_REGISTER(PRIVKEY, pkcs11_private_key_connect, FALSE),
220 PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
221 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
222 PLUGIN_REGISTER(PUBKEY, pkcs11_public_key_load, TRUE),
223 PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
224 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
225 };
226 static plugin_feature_t f_ecdh[] = {
227 PLUGIN_REGISTER(DH, pkcs11_dh_create),
228 PLUGIN_PROVIDE(DH, ECP_192_BIT),
229 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
230 PLUGIN_PROVIDE(DH, ECP_224_BIT),
231 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
232 PLUGIN_PROVIDE(DH, ECP_256_BIT),
233 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
234 PLUGIN_PROVIDE(DH, ECP_384_BIT),
235 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
236 PLUGIN_PROVIDE(DH, ECP_521_BIT),
237 PLUGIN_DEPENDS(CUSTOM, "pkcs11-manager"),
238 };
239 static plugin_feature_t f_manager[] = {
240 PLUGIN_CALLBACK(register_manager, NULL),
241 PLUGIN_PROVIDE(CUSTOM, "pkcs11-manager"),
242 PLUGIN_DEPENDS(CERT_DECODE, CERT_X509),
243 };
244 static plugin_feature_t f[countof(f_hash) + countof(f_dh) + countof(f_rng) +
245 countof(f_key) + countof(f_ecdh) +
246 countof(f_manager)] = {};
247 static int count = 0;
248
249 if (!count)
250 { /* initialize only once */
251 bool use_ecc = lib->settings->get_bool(lib->settings,
252 "libstrongswan.plugins.pkcs11.use_ecc", FALSE);
253 add_features(f, f_manager, countof(f_manager), &count);
254 add_features(f, f_key, countof(f_key), &count);
255 if (lib->settings->get_bool(lib->settings,
256 "libstrongswan.plugins.pkcs11.use_hasher", FALSE))
257 {
258 add_features(f, f_hash, countof(f_hash), &count);
259 }
260 if (lib->settings->get_bool(lib->settings,
261 "libstrongswan.plugins.pkcs11.use_rng", FALSE))
262 {
263 add_features(f, f_rng, countof(f_rng), &count);
264 }
265 if (lib->settings->get_bool(lib->settings,
266 "libstrongswan.plugins.pkcs11.use_dh", FALSE))
267 {
268 add_features(f, f_dh, countof(f_dh), &count);
269 if (use_ecc)
270 {
271 add_features(f, f_ecdh, countof(f_ecdh), &count);
272 }
273 }
274 }
275 *features = f;
276 return count;
277 }
278
279 METHOD(plugin_t, destroy, void,
280 private_pkcs11_plugin_t *this)
281 {
282 this->creds->destroy(this->creds);
283 this->mutex->destroy(this->mutex);
284 free(this);
285 }
286
287 /*
288 * see header file
289 */
290 plugin_t *pkcs11_plugin_create()
291 {
292 private_pkcs11_plugin_t *this;
293
294 INIT(this,
295 .public = {
296 .plugin = {
297 .get_name = _get_name,
298 .get_features = _get_features,
299 .destroy = _destroy,
300 },
301 },
302 .creds = linked_list_create(),
303 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
304 );
305
306 return &this->public.plugin;
307 }