Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "pkcs11_creds.h"
                     17: #include "pkcs11_manager.h"
                     18: 
                     19: #include <utils/debug.h>
                     20: #include <collections/linked_list.h>
                     21: 
                     22: typedef struct private_pkcs11_creds_t private_pkcs11_creds_t;
                     23: 
                     24: /**
                     25:  * Private data of an pkcs11_creds_t object.
                     26:  */
                     27: struct private_pkcs11_creds_t {
                     28: 
                     29:        /**
                     30:         * Public pkcs11_creds_t interface.
                     31:         */
                     32:        pkcs11_creds_t public;
                     33: 
                     34:        /**
                     35:         * PKCS# library
                     36:         */
                     37:        pkcs11_library_t *lib;
                     38: 
                     39:        /**
                     40:         * Token slot
                     41:         */
                     42:        CK_SLOT_ID slot;
                     43: 
                     44:        /**
                     45:         * List of trusted certificates
                     46:         */
                     47:        linked_list_t *trusted;
                     48: 
                     49:        /**
                     50:         * List of untrusted certificates
                     51:         */
                     52:        linked_list_t *untrusted;
                     53: };
                     54: 
                     55: /**
                     56:  * Find certificates, optionally trusted
                     57:  */
                     58: static void find_certificates(private_pkcs11_creds_t *this,
                     59:                                                          CK_SESSION_HANDLE session)
                     60: {
                     61:        CK_OBJECT_CLASS class = CKO_CERTIFICATE;
                     62:        CK_CERTIFICATE_TYPE type = CKC_X_509;
                     63:        CK_BBOOL trusted = TRUE;
                     64:        CK_ATTRIBUTE tmpl[] = {
                     65:                {CKA_CLASS, &class, sizeof(class)},
                     66:                {CKA_CERTIFICATE_TYPE, &type, sizeof(type)},
                     67:        };
                     68:        CK_OBJECT_HANDLE object;
                     69:        CK_ATTRIBUTE attr[] = {
                     70:                {CKA_VALUE, NULL, 0},
                     71:                {CKA_LABEL, NULL, 0},
                     72:                {CKA_TRUSTED, &trusted, sizeof(trusted)}
                     73:        };
                     74:        enumerator_t *enumerator;
                     75:        linked_list_t *raw;
                     76:        certificate_t *cert;
                     77:        struct {
                     78:                chunk_t value;
                     79:                chunk_t label;
                     80:                bool trusted;
                     81:        } *entry;
                     82:        int count = countof(attr);
                     83: 
                     84:        /* store result in a temporary list, avoid recursive operation */
                     85:        raw = linked_list_create();
                     86:        /* do not use trusted argument if not supported */
                     87:        if (!(this->lib->get_features(this->lib) & PKCS11_TRUSTED_CERTS))
                     88:        {
                     89:                count--;
                     90:        }
                     91:        enumerator = this->lib->create_object_enumerator(this->lib,
                     92:                                                                        session, tmpl, countof(tmpl), attr, count);
                     93:        while (enumerator->enumerate(enumerator, &object))
                     94:        {
                     95:                entry = malloc(sizeof(*entry));
                     96:                entry->value = chunk_clone(
                     97:                                                        chunk_create(attr[0].pValue, attr[0].ulValueLen));
                     98:                entry->label = chunk_clone(
                     99:                                                        chunk_create(attr[1].pValue, attr[1].ulValueLen));
                    100:                entry->trusted = trusted;
                    101:                raw->insert_last(raw, entry);
                    102:        }
                    103:        enumerator->destroy(enumerator);
                    104: 
                    105:        while (raw->remove_first(raw, (void**)&entry) == SUCCESS)
                    106:        {
                    107:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                    108:                                                        BUILD_BLOB_ASN1_DER, entry->value,
                    109:                                                        BUILD_END);
                    110:                if (cert)
                    111:                {
                    112:                        DBG1(DBG_CFG, "    loaded %strusted cert '%.*s'",
                    113:                                 entry->trusted ? "" : "un", (int)entry->label.len,
                    114:                                 entry->label.ptr);
                    115:                        /* trusted certificates are also returned as untrusted */
                    116:                        this->untrusted->insert_last(this->untrusted, cert);
                    117:                        if (entry->trusted)
                    118:                        {
                    119:                                this->trusted->insert_last(this->trusted, cert->get_ref(cert));
                    120:                        }
                    121:                }
                    122:                else
                    123:                {
                    124:                        DBG1(DBG_CFG, "    loading cert '%.*s' failed",
                    125:                                (int)entry->label.len, entry->label.ptr);
                    126:                }
                    127:                free(entry->value.ptr);
                    128:                free(entry->label.ptr);
                    129:                free(entry);
                    130:        }
                    131:        raw->destroy(raw);
                    132: }
                    133: 
                    134: /**
                    135:  * Load in the certificates from the token
                    136:  */
                    137: static bool load_certificates(private_pkcs11_creds_t *this)
                    138: {
                    139:        CK_SESSION_HANDLE session;
                    140:        CK_RV rv;
                    141: 
                    142:        rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION,
                    143:                                                                         NULL, NULL, &session);
                    144:        if (rv != CKR_OK)
                    145:        {
                    146:                DBG1(DBG_CFG, "opening session failed: %N", ck_rv_names, rv);
                    147:                return FALSE;
                    148:        }
                    149: 
                    150:        find_certificates(this, session);
                    151: 
                    152:        this->lib->f->C_CloseSession(session);
                    153:        return TRUE;
                    154: }
                    155: 
                    156: CALLBACK(certs_filter, bool,
                    157:        identification_t *id, enumerator_t *orig, va_list args)
                    158: {
                    159:        public_key_t *public;
                    160:        certificate_t *cert, **out;
                    161: 
                    162:        VA_ARGS_VGET(args, out);
                    163: 
                    164:        while (orig->enumerate(orig, &cert))
                    165:        {
                    166:                if (id == NULL || cert->has_subject(cert, id))
                    167:                {
                    168:                        *out = cert;
                    169:                        return TRUE;
                    170:                }
                    171:                public = cert->get_public_key(cert);
                    172:                if (public)
                    173:                {
                    174:                        if (public->has_fingerprint(public, id->get_encoding(id)))
                    175:                        {
                    176:                                public->destroy(public);
                    177:                                *out = cert;
                    178:                                return TRUE;
                    179:                        }
                    180:                        public->destroy(public);
                    181:                }
                    182:        }
                    183:        return FALSE;
                    184: }
                    185: 
                    186: METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
                    187:        private_pkcs11_creds_t *this, certificate_type_t cert, key_type_t key,
                    188:        identification_t *id, bool trusted)
                    189: {
                    190:        enumerator_t *inner;
                    191: 
                    192:        if (cert != CERT_X509 && cert != CERT_ANY)
                    193:        {
                    194:                return NULL;
                    195:        }
                    196:        if (trusted)
                    197:        {
                    198:                inner = this->trusted->create_enumerator(this->trusted);
                    199:        }
                    200:        else
                    201:        {
                    202:                inner = this->untrusted->create_enumerator(this->untrusted);
                    203:        }
                    204:        return enumerator_create_filter(inner, certs_filter, id, NULL);
                    205: }
                    206: 
                    207: METHOD(pkcs11_creds_t, get_library, pkcs11_library_t*,
                    208:        private_pkcs11_creds_t *this)
                    209: {
                    210:        return this->lib;
                    211: }
                    212: 
                    213: METHOD(pkcs11_creds_t, get_slot, CK_SLOT_ID,
                    214:        private_pkcs11_creds_t *this)
                    215: {
                    216:        return this->slot;
                    217: }
                    218: 
                    219: METHOD(pkcs11_creds_t, destroy, void,
                    220:        private_pkcs11_creds_t *this)
                    221: {
                    222:        this->trusted->destroy_offset(this->trusted,
                    223:                                                                offsetof(certificate_t, destroy));
                    224:        this->untrusted->destroy_offset(this->untrusted,
                    225:                                                                offsetof(certificate_t, destroy));
                    226:        free(this);
                    227: }
                    228: 
                    229: /**
                    230:  * See header
                    231:  */
                    232: pkcs11_creds_t *pkcs11_creds_create(pkcs11_library_t *p11, CK_SLOT_ID slot)
                    233: {
                    234:        private_pkcs11_creds_t *this;
                    235: 
                    236:        INIT(this,
                    237:                .public = {
                    238:                        .set = {
                    239:                                .create_shared_enumerator = (void*)enumerator_create_empty,
                    240:                                .create_private_enumerator = (void*)enumerator_create_empty,
                    241:                                .create_cert_enumerator = _create_cert_enumerator,
                    242:                                .create_cdp_enumerator  = (void*)enumerator_create_empty,
                    243:                                .cache_cert = (void*)nop,
                    244:                        },
                    245:                        .get_library = _get_library,
                    246:                        .get_slot = _get_slot,
                    247:                        .destroy = _destroy,
                    248:                },
                    249:                .lib = p11,
                    250:                .slot = slot,
                    251:                .trusted = linked_list_create(),
                    252:                .untrusted = linked_list_create(),
                    253:        );
                    254: 
                    255:        if (!load_certificates(this))
                    256:        {
                    257:                destroy(this);
                    258:                return NULL;
                    259:        }
                    260: 
                    261:        return &this->public;
                    262: }
                    263: 
                    264: /**
                    265:  * See header.
                    266:  */
                    267: certificate_t *pkcs11_creds_load(certificate_type_t type, va_list args)
                    268: {
                    269:        chunk_t keyid = chunk_empty, data = chunk_empty;
                    270:        enumerator_t *enumerator, *certs;
                    271:        pkcs11_manager_t *manager;
                    272:        pkcs11_library_t *p11;
                    273:        certificate_t *cert = NULL;
                    274:        CK_SLOT_ID current, slot = -1;
                    275:        char *module = NULL;
                    276: 
                    277:        while (TRUE)
                    278:        {
                    279:                switch (va_arg(args, builder_part_t))
                    280:                {
                    281:                        case BUILD_PKCS11_KEYID:
                    282:                                keyid = va_arg(args, chunk_t);
                    283:                                continue;
                    284:                        case BUILD_PKCS11_SLOT:
                    285:                                slot = va_arg(args, int);
                    286:                                continue;
                    287:                        case BUILD_PKCS11_MODULE:
                    288:                                module = va_arg(args, char*);
                    289:                                continue;
                    290:                        case BUILD_END:
                    291:                                break;
                    292:                        default:
                    293:                                return NULL;
                    294:                }
                    295:                break;
                    296:        }
                    297:        if (!keyid.len)
                    298:        {
                    299:                return NULL;
                    300:        }
                    301: 
                    302:        manager = lib->get(lib, "pkcs11-manager");
                    303:        if (!manager)
                    304:        {
                    305:                return NULL;
                    306:        }
                    307:        enumerator = manager->create_token_enumerator(manager);
                    308:        while (enumerator->enumerate(enumerator, &p11, &current))
                    309:        {
                    310:                CK_OBJECT_CLASS class = CKO_CERTIFICATE;
                    311:                CK_CERTIFICATE_TYPE ck_type = CKC_X_509;
                    312:                CK_ATTRIBUTE tmpl[] = {
                    313:                        {CKA_CLASS, &class, sizeof(class)},
                    314:                        {CKA_CERTIFICATE_TYPE, &ck_type, sizeof(ck_type)},
                    315:                        {CKA_ID, keyid.ptr, keyid.len},
                    316:                };
                    317:                CK_ATTRIBUTE attr[] = {
                    318:                        {CKA_VALUE, NULL, 0},
                    319:                };
                    320:                CK_OBJECT_HANDLE object;
                    321:                CK_SESSION_HANDLE session;
                    322:                CK_RV rv;
                    323: 
                    324:                if (slot != -1 && slot != current)
                    325:                {
                    326:                        continue;
                    327:                }
                    328:                if (module && !streq(module, p11->get_name(p11)))
                    329:                {
                    330:                        continue;
                    331:                }
                    332: 
                    333:                rv = p11->f->C_OpenSession(current, CKF_SERIAL_SESSION, NULL, NULL,
                    334:                                                                   &session);
                    335:                if (rv != CKR_OK)
                    336:                {
                    337:                        DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
                    338:                        continue;
                    339:                }
                    340:                certs = p11->create_object_enumerator(p11, session,
                    341:                                                                        tmpl, countof(tmpl), attr, countof(attr));
                    342:                if (certs->enumerate(certs, &object))
                    343:                {
                    344:                        data = chunk_clone(chunk_create(attr[0].pValue, attr[0].ulValueLen));
                    345:                }
                    346:                certs->destroy(certs);
                    347:                p11->f->C_CloseSession(session);
                    348: 
                    349:                if (data.ptr)
                    350:                {
                    351:                        break;
                    352:                }
                    353:        }
                    354:        enumerator->destroy(enumerator);
                    355: 
                    356:        if (data.ptr)
                    357:        {
                    358:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                    359:                                                                  BUILD_BLOB_ASN1_DER, data, BUILD_END);
                    360:                free(data.ptr);
                    361:                if (!cert)
                    362:                {
                    363:                        DBG1(DBG_CFG, "parsing PKCS#11 certificate %#B failed", &keyid);
                    364:                }
                    365:        }
                    366:        else
                    367:        {
                    368:                DBG1(DBG_CFG, "PKCS#11 certificate %#B not found", &keyid);
                    369:        }
                    370:        return cert;
                    371: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>