Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2011 Tobias Brunner
3: * HSR 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 <utils/debug.h>
23: #include <collections/linked_list.h>
24: #include <threading/mutex.h>
25: #include <threading/rwlock.h>
26:
27: #include "pkcs11_manager.h"
28: #include "pkcs11_creds.h"
29: #include "pkcs11_private_key.h"
30: #include "pkcs11_public_key.h"
31: #include "pkcs11_hasher.h"
32: #include "pkcs11_rng.h"
33: #include "pkcs11_dh.h"
34:
35: typedef struct private_pkcs11_plugin_t private_pkcs11_plugin_t;
36:
37: /**
38: * private data of pkcs11_plugin
39: */
40: struct private_pkcs11_plugin_t {
41:
42: /**
43: * public functions
44: */
45: pkcs11_plugin_t public;
46:
47: /**
48: * PKCS#11 library/slot manager
49: */
50: pkcs11_manager_t *manager;
51:
52: /**
53: * List of credential sets, pkcs11_creds_t
54: */
55: linked_list_t *creds;
56:
57: /**
58: * mutex to lock list
59: */
60: mutex_t *mutex;
61:
62: /**
63: * TRUE if events from tokens are to be handled
64: */
65: bool handle_events;
66:
67: /**
68: * Lock for the above flag
69: */
70: rwlock_t *handle_events_lock;
71: };
72:
73: /**
74: * Token event callback function
75: */
76: static void token_event_cb(private_pkcs11_plugin_t *this, pkcs11_library_t *p11,
77: CK_SLOT_ID slot, bool add)
78: {
79: enumerator_t *enumerator;
80: pkcs11_creds_t *creds, *found = NULL;
81:
82: this->handle_events_lock->read_lock(this->handle_events_lock);
83: if (add && this->handle_events)
84: {
85: if (lib->settings->get_bool(lib->settings,
86: "%s.plugins.pkcs11.modules.%s.load_certs",
87: TRUE, lib->ns, p11->get_name(p11)))
88: {
89: creds = pkcs11_creds_create(p11, slot);
90: if (creds)
91: {
92: this->mutex->lock(this->mutex);
93: this->creds->insert_last(this->creds, creds);
94: this->mutex->unlock(this->mutex);
95: lib->credmgr->add_set(lib->credmgr, &creds->set);
96: }
97: }
98: }
99: else if (this->handle_events)
100: {
101: this->mutex->lock(this->mutex);
102: enumerator = this->creds->create_enumerator(this->creds);
103: while (enumerator->enumerate(enumerator, &creds))
104: {
105: if (creds->get_library(creds) == p11 &&
106: creds->get_slot(creds) == slot)
107: {
108: found = creds;
109: this->creds->remove_at(this->creds, enumerator);
110: break;
111: }
112: }
113: enumerator->destroy(enumerator);
114: this->mutex->unlock(this->mutex);
115:
116: if (found)
117: {
118: lib->credmgr->remove_set(lib->credmgr, &found->set);
119: found->destroy(found);
120: /* flush the cache after a token is gone */
121: lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
122: }
123: }
124: this->handle_events_lock->unlock(this->handle_events_lock);
125: }
126:
127: METHOD(plugin_t, get_name, char*,
128: private_pkcs11_plugin_t *this)
129: {
130: return "pkcs11";
131: }
132:
133: /**
134: * Load/unload certificates from tokens.
135: */
136: static bool handle_certs(private_pkcs11_plugin_t *this,
137: plugin_feature_t *feature, bool reg, void *data)
138: {
139: this->handle_events_lock->write_lock(this->handle_events_lock);
140: this->handle_events = reg;
141: this->handle_events_lock->unlock(this->handle_events_lock);
142:
143: if (reg)
144: {
145: enumerator_t *enumerator;
146: pkcs11_library_t *p11;
147: CK_SLOT_ID slot;
148:
149: enumerator = this->manager->create_token_enumerator(this->manager);
150: while (enumerator->enumerate(enumerator, &p11, &slot))
151: {
152: token_event_cb(this, p11, slot, TRUE);
153: }
154: enumerator->destroy(enumerator);
155:
156: lib->creds->add_builder(lib->creds, CRED_CERTIFICATE,
157: CERT_X509, FALSE, (void*)pkcs11_creds_load);
158: }
159: else
160: {
161: pkcs11_creds_t *creds;
162:
163: while (this->creds->remove_last(this->creds, (void**)&creds) == SUCCESS)
164: {
165: lib->credmgr->remove_set(lib->credmgr, &creds->set);
166: creds->destroy(creds);
167: }
168:
169: lib->creds->remove_builder(lib->creds, (void*)pkcs11_creds_load);
170: }
171: return TRUE;
172: }
173:
174: METHOD(plugin_t, reload, bool,
175: private_pkcs11_plugin_t *this)
176: {
177: if (lib->settings->get_bool(lib->settings, "%s.plugins.pkcs11.reload_certs",
178: FALSE, lib->ns))
179: {
180: DBG1(DBG_CFG, "reloading certificates from PKCS#11 tokens");
181: handle_certs(this, NULL, FALSE, NULL);
182: handle_certs(this, NULL, TRUE, NULL);
183: return TRUE;
184: }
185: return FALSE;
186: }
187:
188: METHOD(plugin_t, get_features, int,
189: private_pkcs11_plugin_t *this, plugin_feature_t *features[])
190: {
191: static plugin_feature_t f_hash[] = {
192: PLUGIN_REGISTER(HASHER, pkcs11_hasher_create),
193: PLUGIN_PROVIDE(HASHER, HASH_MD2),
194: PLUGIN_PROVIDE(HASHER, HASH_MD5),
195: PLUGIN_PROVIDE(HASHER, HASH_SHA1),
196: PLUGIN_PROVIDE(HASHER, HASH_SHA256),
197: PLUGIN_PROVIDE(HASHER, HASH_SHA384),
198: PLUGIN_PROVIDE(HASHER, HASH_SHA512),
199: };
200: static plugin_feature_t f_dh[] = {
201: PLUGIN_REGISTER(DH, pkcs11_dh_create),
202: PLUGIN_PROVIDE(DH, MODP_2048_BIT),
203: PLUGIN_PROVIDE(DH, MODP_2048_224),
204: PLUGIN_PROVIDE(DH, MODP_2048_256),
205: PLUGIN_PROVIDE(DH, MODP_1536_BIT),
206: PLUGIN_PROVIDE(DH, MODP_3072_BIT),
207: PLUGIN_PROVIDE(DH, MODP_4096_BIT),
208: PLUGIN_PROVIDE(DH, MODP_6144_BIT),
209: PLUGIN_PROVIDE(DH, MODP_8192_BIT),
210: PLUGIN_PROVIDE(DH, MODP_1024_BIT),
211: PLUGIN_PROVIDE(DH, MODP_1024_160),
212: PLUGIN_PROVIDE(DH, MODP_768_BIT),
213: PLUGIN_PROVIDE(DH, MODP_CUSTOM),
214: };
215: static plugin_feature_t f_ecdh[] = {
216: PLUGIN_REGISTER(DH, pkcs11_dh_create),
217: PLUGIN_PROVIDE(DH, ECP_192_BIT),
218: PLUGIN_PROVIDE(DH, ECP_224_BIT),
219: PLUGIN_PROVIDE(DH, ECP_256_BIT),
220: PLUGIN_PROVIDE(DH, ECP_384_BIT),
221: PLUGIN_PROVIDE(DH, ECP_521_BIT),
222: };
223: static plugin_feature_t f_rng[] = {
224: PLUGIN_REGISTER(RNG, pkcs11_rng_create),
225: PLUGIN_PROVIDE(RNG, RNG_STRONG),
226: PLUGIN_PROVIDE(RNG, RNG_TRUE),
227: };
228: static plugin_feature_t f_privkey[] = {
229: PLUGIN_REGISTER(PRIVKEY, pkcs11_private_key_connect, FALSE),
230: PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
231: };
232: static plugin_feature_t f_pubkey[] = {
233: PLUGIN_REGISTER(PUBKEY, pkcs11_public_key_load, TRUE),
234: PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
235: PLUGIN_PROVIDE(PUBKEY, KEY_ECDSA),
236: };
237: static plugin_feature_t f_manager[] = {
238: PLUGIN_CALLBACK((plugin_feature_callback_t)handle_certs, NULL),
239: PLUGIN_PROVIDE(CUSTOM, "pkcs11-certs"),
240: PLUGIN_DEPENDS(CERT_DECODE, CERT_X509),
241: };
242: static plugin_feature_t f[countof(f_hash) + countof(f_dh) + countof(f_rng) +
243: countof(f_ecdh) + countof(f_privkey) +
244: countof(f_pubkey) + countof(f_manager)] = {};
245: static int count = 0;
246:
247: if (!count)
248: { /* initialize only once */
249: bool use_ecc = lib->settings->get_bool(lib->settings,
250: "%s.plugins.pkcs11.use_ecc", FALSE, lib->ns);
251: plugin_features_add(f, f_manager, countof(f_manager), &count);
252: /* private key handling for EC keys is not disabled by use_ecc */
253: plugin_features_add(f, f_privkey, countof(f_privkey), &count);
254: if (lib->settings->get_bool(lib->settings,
255: "%s.plugins.pkcs11.use_pubkey", FALSE, lib->ns))
256: {
257: plugin_features_add(f, f_pubkey, countof(f_pubkey) - (use_ecc ? 0 : 1),
258: &count);
259: }
260: if (lib->settings->get_bool(lib->settings,
261: "%s.plugins.pkcs11.use_hasher", FALSE, lib->ns))
262: {
263: plugin_features_add(f, f_hash, countof(f_hash), &count);
264: }
265: if (lib->settings->get_bool(lib->settings,
266: "%s.plugins.pkcs11.use_rng", FALSE, lib->ns))
267: {
268: plugin_features_add(f, f_rng, countof(f_rng), &count);
269: }
270: if (lib->settings->get_bool(lib->settings,
271: "%s.plugins.pkcs11.use_dh", FALSE, lib->ns))
272: {
273: plugin_features_add(f, f_dh, countof(f_dh), &count);
274: if (use_ecc)
275: {
276: plugin_features_add(f, f_ecdh, countof(f_ecdh), &count);
277: }
278: }
279: }
280: *features = f;
281: return count;
282: }
283:
284: METHOD(plugin_t, destroy, void,
285: private_pkcs11_plugin_t *this)
286: {
287: lib->set(lib, "pkcs11-manager", NULL);
288: this->manager->destroy(this->manager);
289: this->creds->destroy(this->creds);
290: this->mutex->destroy(this->mutex);
291: this->handle_events_lock->destroy(this->handle_events_lock);
292: free(this);
293: }
294:
295: /*
296: * see header file
297: */
298: plugin_t *pkcs11_plugin_create()
299: {
300: private_pkcs11_plugin_t *this;
301:
302: INIT(this,
303: .public = {
304: .plugin = {
305: .get_name = _get_name,
306: .get_features = _get_features,
307: .reload = _reload,
308: .destroy = _destroy,
309: },
310: },
311: .creds = linked_list_create(),
312: .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
313: .handle_events_lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
314: );
315:
316: this->manager = pkcs11_manager_create((void*)token_event_cb, this);
317: lib->set(lib, "pkcs11-manager", this->manager);
318:
319: return &this->public.plugin;
320: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>