Add a builder to load specific pkcs11 certificates by keyid

This commit is contained in:
Martin Willi 2012-10-15 17:53:21 +02:00
parent ffe42fa405
commit fbd3863571
3 changed files with 115 additions and 0 deletions

View File

@ -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;
}

View File

@ -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_ @}*/

View File

@ -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;
}