]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Add a builder to load specific pkcs11 certificates by keyid
authorMartin Willi <martin@revosec.ch>
Mon, 15 Oct 2012 15:53:21 +0000 (17:53 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 24 Oct 2012 11:07:52 +0000 (13:07 +0200)
src/libstrongswan/plugins/pkcs11/pkcs11_creds.c
src/libstrongswan/plugins/pkcs11/pkcs11_creds.h
src/libstrongswan/plugins/pkcs11/pkcs11_plugin.c

index 7536ce1d3ed720d83b0a4b43d32496d5f3d864dd..a3aa99a6a86c585f9e97986544dfc4c11415799a 100644 (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;
+}
index c40a8dea6b9eabcf25c556b667c4397538e9b16e..5deb258be54fad0809182eeeef14f977432db637 100644 (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_ @}*/
index b88ba630dc97e7fd1780fbeeb6f26ee412e26d37..31cfa81ddb758f9e8936a0c70a9c29cbfa96aed8 100644 (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;
 }