Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c, revision 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>