aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_creds.c99
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_creds.h11
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c5
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;
}