Return to pkcs11_plugin.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / pkcs11 |
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: }