diff options
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_creds.c | 99 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_creds.h | 11 | ||||
-rw-r--r-- | src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c | 5 |
3 files changed, 115 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c index 7536ce1d3..a3aa99a6a 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.c @@ -14,6 +14,7 @@ */ #include "pkcs11_creds.h" +#include "pkcs11_manager.h" #include <debug.h> #include <utils/linked_list.h> @@ -257,3 +258,101 @@ pkcs11_creds_t *pkcs11_creds_create(pkcs11_library_t *p11, CK_SLOT_ID slot) return &this->public; } + +/** + * See header. + */ +certificate_t *pkcs11_creds_load(certificate_type_t type, va_list args) +{ + chunk_t keyid = chunk_empty, data = chunk_empty; + enumerator_t *enumerator, *certs; + pkcs11_manager_t *manager; + pkcs11_library_t *p11; + certificate_t *cert = NULL; + CK_SLOT_ID slot; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_PKCS11_KEYID: + keyid = va_arg(args, chunk_t); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (!keyid.len) + { + return NULL; + } + + manager = lib->get(lib, "pkcs11-manager"); + if (!manager) + { + return NULL; + } + enumerator = manager->create_token_enumerator(manager); + while (enumerator->enumerate(enumerator, &p11, &slot)) + { + CK_OBJECT_CLASS class = CKO_CERTIFICATE; + CK_CERTIFICATE_TYPE type = CKC_X_509; + CK_ATTRIBUTE tmpl[] = { + {CKA_CLASS, &class, sizeof(class)}, + {CKA_CERTIFICATE_TYPE, &type, sizeof(type)}, + {CKA_ID, keyid.ptr, keyid.len}, + }; + CK_ATTRIBUTE attr[] = { + {CKA_VALUE, NULL, 0}, + }; + CK_OBJECT_HANDLE object; + CK_SESSION_HANDLE session; + CK_RV rv; + + rv = p11->f->C_OpenSession(slot, CKF_SERIAL_SESSION, NULL, NULL, + &session); + if (rv != CKR_OK) + { + DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv); + continue; + } + certs = p11->create_object_enumerator(p11, session, + tmpl, countof(tmpl), attr, countof(attr)); + if (certs->enumerate(certs, &object)) + { + data = chunk_clone(chunk_create(attr[0].pValue, attr[0].ulValueLen)); + } + certs->destroy(certs); + p11->f->C_CloseSession(session); + + if (data.ptr) + { + break; + } + } + enumerator->destroy(enumerator); + + if (data.ptr) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB_ASN1_DER, data, BUILD_END); + free(data.ptr); + if (cert) + { + DBG1(DBG_CFG, "loaded PKCS#11 certificate '%Y'", + cert->get_subject(cert)); + } + else + { + DBG1(DBG_CFG, "parsing PKCS#11 certificate %#B failed", &keyid); + } + } + else + { + DBG1(DBG_CFG, "PKCS#11 certificate %#B not found", &keyid); + } + return cert; +} diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h index c40a8dea6..5deb258be 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_creds.h @@ -65,4 +65,15 @@ struct pkcs11_creds_t { */ pkcs11_creds_t *pkcs11_creds_create(pkcs11_library_t *p11, CK_SLOT_ID slot); +/** + * Load a specific certificate from a token. + * + * Accepts a BUILD_PKCS11_KEYID as the only argument. + * + * @param type certificate type, must be CERT_X509 + * @param args variable argument list, containing BUILD_PKCS11_KEYID. + * @return loaded certificate, or NULL on failure + */ +certificate_t *pkcs11_creds_load(certificate_type_t type, va_list args); + #endif /** PKCS11_CREDS_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c index b88ba630d..31cfa81dd 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c @@ -147,6 +147,9 @@ static bool handle_certs(private_pkcs11_plugin_t *this, token_event_cb(this, p11, slot, TRUE); } enumerator->destroy(enumerator); + + lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, + CERT_X509, FALSE, (void*)pkcs11_creds_load); } else { @@ -157,6 +160,8 @@ static bool handle_certs(private_pkcs11_plugin_t *this, lib->credmgr->remove_set(lib->credmgr, &creds->set); creds->destroy(creds); } + + lib->creds->remove_builder(lib->creds, (void*)pkcs11_creds_load); } return TRUE; } |