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>