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, ¤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>