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, ¤t))
! 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>