52f0242fb844c597efdc05ba4c8427ac281e3d00
[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 * Add a set of features
117 */
118 static inline void add_features(plugin_feature_t *f, plugin_feature_t *n,
119 int count, int *pos)
120 {
121 int i;
122 for (i = 0; i < count; i++)
123 {
124 f[(*pos)++] = n[i];
125 }
126 }
127
128 METHOD(plugin_t, get_features, int,
129 private_pkcs11_plugin_t *this, plugin_feature_t *features[])
130 {
131 static plugin_feature_t f_hash[] = {
132 PLUGIN_REGISTER(HASHER, pkcs11_hasher_create),
133 PLUGIN_PROVIDE(HASHER, HASH_MD2),
134 PLUGIN_PROVIDE(HASHER, HASH_MD5),
135 PLUGIN_PROVIDE(HASHER, HASH_SHA1),
136 PLUGIN_PROVIDE(HASHER, HASH_SHA256),
137 PLUGIN_PROVIDE(HASHER, HASH_SHA384),
138 PLUGIN_PROVIDE(HASHER, HASH_SHA512),
139 };
140 static plugin_feature_t f_dh[] = {
141 PLUGIN_REGISTER(DH, pkcs11_dh_create),
142 PLUGIN_PROVIDE(DH, MODP_2048_BIT),
143 PLUGIN_PROVIDE(DH, MODP_2048_224),
144 PLUGIN_PROVIDE(DH, MODP_2048_256),
145 PLUGIN_PROVIDE(DH, MODP_1536_BIT),
146 PLUGIN_PROVIDE(DH, MODP_3072_BIT),
147 PLUGIN_PROVIDE(DH, MODP_4096_BIT),
148 PLUGIN_PROVIDE(DH, MODP_6144_BIT),
149 PLUGIN_PROVIDE(DH, MODP_8192_BIT),
150 PLUGIN_PROVIDE(DH, MODP_1024_BIT),
151 PLUGIN_PROVIDE(DH, MODP_1024_160),
152 PLUGIN_PROVIDE(DH, MODP_768_BIT),
153 PLUGIN_PROVIDE(DH, MODP_CUSTOM),
154 };
155 static plugin_feature_t f_rng[] = {
156 PLUGIN_REGISTER(RNG, pkcs11_rng_create),
157 PLUGIN_PROVIDE(RNG, RNG_STRONG),
158 PLUGIN_PROVIDE(RNG, RNG_TRUE),
159 };
160 static plugin_feature_t f_key[] = {
161 PLUGIN_REGISTER(PRIVKEY, pkcs11_private_key_connect, FALSE),
162 PLUGIN_PROVIDE(PRIVKEY, KEY_ANY),
163 PLUGIN_REGISTER(PUBKEY, pkcs11_public_key_load, TRUE),
164 PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
165 };
166 static plugin_feature_t f_ecdh[] = {
167 PLUGIN_REGISTER(DH, pkcs11_dh_create),
168 PLUGIN_PROVIDE(DH, ECP_192_BIT),
169 PLUGIN_PROVIDE(DH, ECP_224_BIT),
170 PLUGIN_PROVIDE(DH, ECP_256_BIT),
171 PLUGIN_PROVIDE(DH, ECP_384_BIT),
172 PLUGIN_PROVIDE(DH, ECP_521_BIT),
173 };
174 static plugin_feature_t f[countof(f_hash) + countof(f_dh) + countof(f_rng) +
175 countof(f_key) + countof(f_ecdh)] = {};
176 static int count = 0;
177
178 if (!count)
179 { /* initialize only once */
180 bool use_ecc = lib->settings->get_bool(lib->settings,
181 "libstrongswan.plugins.pkcs11.use_ecc", FALSE);
182
183 add_features(f, f_key, countof(f_key), &count);
184 if (lib->settings->get_bool(lib->settings,
185 "libstrongswan.plugins.pkcs11.use_hasher", FALSE))
186 {
187 add_features(f, f_hash, countof(f_hash), &count);
188 }
189 if (lib->settings->get_bool(lib->settings,
190 "libstrongswan.plugins.pkcs11.use_rng", FALSE))
191 {
192 add_features(f, f_rng, countof(f_rng), &count);
193 }
194 if (lib->settings->get_bool(lib->settings,
195 "libstrongswan.plugins.pkcs11.use_dh", FALSE))
196 {
197 add_features(f, f_dh, countof(f_dh), &count);
198 if (use_ecc)
199 {
200 add_features(f, f_ecdh, countof(f_ecdh), &count);
201 }
202 }
203 }
204 *features = f;
205 return count;
206 }
207
208 METHOD(plugin_t, destroy, void,
209 private_pkcs11_plugin_t *this)
210 {
211 pkcs11_creds_t *creds;
212
213 while (this->creds->remove_last(this->creds, (void**)&creds) == SUCCESS)
214 {
215 lib->credmgr->remove_set(lib->credmgr, &creds->set);
216 creds->destroy(creds);
217 }
218 this->creds->destroy(this->creds);
219 lib->set(lib, "pkcs11-manager", NULL);
220 this->manager->destroy(this->manager);
221 this->mutex->destroy(this->mutex);
222 free(this);
223 }
224
225 /*
226 * see header file
227 */
228 plugin_t *pkcs11_plugin_create()
229 {
230 private_pkcs11_plugin_t *this;
231 enumerator_t *enumerator;
232 pkcs11_library_t *p11;
233 CK_SLOT_ID slot;
234
235 INIT(this,
236 .public = {
237 .plugin = {
238 .get_name = _get_name,
239 .get_features = _get_features,
240 .destroy = _destroy,
241 },
242 },
243 .creds = linked_list_create(),
244 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
245 );
246
247 this->manager = pkcs11_manager_create((void*)token_event_cb, this);
248
249 lib->set(lib, "pkcs11-manager", this->manager);
250
251 enumerator = this->manager->create_token_enumerator(this->manager);
252 while (enumerator->enumerate(enumerator, &p11, &slot))
253 {
254 token_event_cb(this, p11, slot, TRUE);
255 }
256 enumerator->destroy(enumerator);
257
258 return &this->public.plugin;
259 }