2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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>.
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
16 #include "pkcs11_creds.h"
19 #include <utils/linked_list.h>
21 typedef struct private_pkcs11_creds_t private_pkcs11_creds_t
;
24 * Private data of an pkcs11_creds_t object.
26 struct private_pkcs11_creds_t
{
29 * Public pkcs11_creds_t interface.
31 pkcs11_creds_t
public;
36 pkcs11_library_t
*lib
;
44 * List of trusted certificates
46 linked_list_t
*trusted
;
49 * List of untrusted certificates
51 linked_list_t
*untrusted
;
55 * Find certificates, optionally trusted
57 static void find_certificates(private_pkcs11_creds_t
*this,
58 CK_SESSION_HANDLE session
)
60 CK_OBJECT_CLASS
class = CKO_CERTIFICATE
;
61 CK_CERTIFICATE_TYPE type
= CKC_X_509
;
62 CK_BBOOL trusted
= TRUE
;
63 CK_ATTRIBUTE tmpl
[] = {
64 {CKA_CLASS
, &class, sizeof(class)},
65 {CKA_CERTIFICATE_TYPE
, &type
, sizeof(type
)},
67 CK_OBJECT_HANDLE object
;
68 CK_ATTRIBUTE attr
[] = {
71 {CKA_TRUSTED
, &trusted
, sizeof(trusted
)}
73 enumerator_t
*enumerator
;
81 int count
= countof(attr
);
83 /* store result in a temporary list, avoid recursive operation */
84 raw
= linked_list_create();
85 /* do not use trusted argument if not supported */
86 if (!(this->lib
->get_features(this->lib
) & PKCS11_TRUSTED_CERTS
))
90 enumerator
= this->lib
->create_object_enumerator(this->lib
,
91 session
, tmpl
, countof(tmpl
), attr
, count
);
92 while (enumerator
->enumerate(enumerator
, &object
))
94 entry
= malloc(sizeof(*entry
));
95 entry
->value
= chunk_clone(
96 chunk_create(attr
[0].pValue
, attr
[0].ulValueLen
));
97 entry
->label
= chunk_clone(
98 chunk_create(attr
[1].pValue
, attr
[1].ulValueLen
));
99 entry
->trusted
= trusted
;
100 raw
->insert_last(raw
, entry
);
102 enumerator
->destroy(enumerator
);
104 while (raw
->remove_first(raw
, (void**)&entry
) == SUCCESS
)
106 cert
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509
,
107 BUILD_BLOB_ASN1_DER
, entry
->value
,
111 DBG1(DBG_CFG
, " loaded %strusted cert '%.*s'",
112 entry
->trusted ?
"" : "un", entry
->label
.len
, entry
->label
.ptr
);
113 /* trusted certificates are also returned as untrusted */
114 this->untrusted
->insert_last(this->untrusted
, cert
);
117 this->trusted
->insert_last(this->trusted
, cert
->get_ref(cert
));
122 DBG1(DBG_CFG
, " loading cert '%.*s' failed",
123 entry
->label
.len
, entry
->label
.ptr
);
125 free(entry
->value
.ptr
);
126 free(entry
->label
.ptr
);
133 * Load in the certificates from the token
135 static bool load_certificates(private_pkcs11_creds_t
*this)
137 CK_SESSION_HANDLE session
;
140 rv
= this->lib
->f
->C_OpenSession(this->slot
, CKF_SERIAL_SESSION
,
141 NULL
, NULL
, &session
);
144 DBG1(DBG_CFG
, "opening session failed: %N", ck_rv_names
, rv
);
148 find_certificates(this, session
);
150 this->lib
->f
->C_CloseSession(session
);
155 * filter function for certs enumerator
157 static bool certs_filter(identification_t
*id
,
158 certificate_t
**in
, certificate_t
**out
)
160 public_key_t
*public;
161 certificate_t
*cert
= *in
;
163 if (id
== NULL
|| cert
->has_subject(cert
, id
))
168 public = cert
->get_public_key(cert
);
171 if (public->has_fingerprint(public, id
->get_encoding(id
)))
173 public->destroy(public);
177 public->destroy(public);
182 METHOD(credential_set_t
, create_cert_enumerator
, enumerator_t
*,
183 private_pkcs11_creds_t
*this, certificate_type_t cert
, key_type_t key
,
184 identification_t
*id
, bool trusted
)
188 if (cert
!= CERT_X509
&& cert
!= CERT_ANY
)
194 inner
= this->trusted
->create_enumerator(this->trusted
);
198 inner
= this->untrusted
->create_enumerator(this->untrusted
);
200 return enumerator_create_filter(inner
, (void*)certs_filter
, id
, NULL
);
203 METHOD(pkcs11_creds_t
, get_library
, pkcs11_library_t
*,
204 private_pkcs11_creds_t
*this)
209 METHOD(pkcs11_creds_t
, get_slot
, CK_SLOT_ID
,
210 private_pkcs11_creds_t
*this)
215 METHOD(pkcs11_creds_t
, destroy
, void,
216 private_pkcs11_creds_t
*this)
218 this->trusted
->destroy_offset(this->trusted
,
219 offsetof(certificate_t
, destroy
));
220 this->untrusted
->destroy_offset(this->untrusted
,
221 offsetof(certificate_t
, destroy
));
228 pkcs11_creds_t
*pkcs11_creds_create(pkcs11_library_t
*p11
, CK_SLOT_ID slot
)
230 private_pkcs11_creds_t
*this;
235 .create_shared_enumerator
= (void*)enumerator_create_empty
,
236 .create_private_enumerator
= (void*)enumerator_create_empty
,
237 .create_cert_enumerator
= _create_cert_enumerator
,
238 .create_cdp_enumerator
= (void*)enumerator_create_empty
,
239 .cache_cert
= (void*)nop
,
241 .get_library
= _get_library
,
242 .get_slot
= _get_slot
,
247 .trusted
= linked_list_create(),
248 .untrusted
= linked_list_create(),
251 if (!load_certificates(this))
257 return &this->public;