]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
If no pkcs11 public key for a private key found, search for a certificate
authorMartin Willi <martin@revosec.ch>
Mon, 15 Oct 2012 12:05:14 +0000 (14:05 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 24 Oct 2012 11:07:52 +0000 (13:07 +0200)
src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c

index 4f74f183632827c78ab9784e2d33d4173b161322..f48ea7994cdc6ea189300248567a092d956efe26 100644 (file)
@@ -571,6 +571,50 @@ static bool login(private_pkcs11_private_key_t *this, int slot)
        return success;
 }
 
+/**
+ * Get a public key from a certificate with a given key ID.
+ */
+static public_key_t* find_pubkey_in_certs(private_pkcs11_private_key_t *this,
+                                                                                 chunk_t keyid)
+{
+       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_OBJECT_HANDLE object;
+       CK_ATTRIBUTE attr[] = {
+               {CKA_VALUE, NULL, 0},
+       };
+       enumerator_t *enumerator;
+       chunk_t data = chunk_empty;
+       public_key_t *key = NULL;
+       certificate_t *cert;
+
+       enumerator = this->lib->create_object_enumerator(this->lib, this->session,
+                                                                       tmpl, countof(tmpl), attr, countof(attr));
+       if (enumerator->enumerate(enumerator, &object))
+       {
+               data = chunk_clone(chunk_create(attr[0].pValue, attr[0].ulValueLen));
+       }
+       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)
+               {
+                       key = cert->get_public_key(cert);
+                       cert->destroy(cert);
+               }
+       }
+       return key;
+}
+
 /**
  * See header.
  */
@@ -673,12 +717,17 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args)
                return NULL;
        }
 
-       this->pubkey = pkcs11_public_key_connect(this->lib, slot, this->type,
-                                                                                        keyid);
+       this->pubkey = pkcs11_public_key_connect(this->lib, slot, this->type, keyid);
        if (!this->pubkey)
        {
-               destroy(this);
-               return NULL;
+               this->pubkey = find_pubkey_in_certs(this, keyid);
+               if (!this->pubkey)
+               {
+                       DBG1(DBG_CFG, "no public key or certificate found for private key "
+                                "on '%s':%d", module, slot);
+                       destroy(this);
+                       return NULL;
+               }
        }
 
        return &this->public;