Implemented public key encryption/private key decryption in PKCS#11
authorMartin Willi <martin@revosec.ch>
Wed, 11 Aug 2010 10:12:37 +0000 (12:12 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 11 Aug 2010 10:12:37 +0000 (12:12 +0200)
src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h
src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c

index 52a9e09..e51d0aa 100644 (file)
@@ -89,7 +89,7 @@ METHOD(private_key_t, get_keysize, int,
 /**
  * See header.
  */
-CK_MECHANISM_PTR pkcs11_scheme_to_mechanism(signature_scheme_t scheme)
+CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme)
 {
        static struct {
                signature_scheme_t scheme;
@@ -115,6 +115,30 @@ CK_MECHANISM_PTR pkcs11_scheme_to_mechanism(signature_scheme_t scheme)
 }
 
 /**
+ * See header.
+ */
+CK_MECHANISM_PTR pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme)
+{
+       static struct {
+               encryption_scheme_t scheme;
+               CK_MECHANISM mechanism;
+       } mappings[] = {
+               {ENCRYPT_RSA_PKCS1,                     {CKM_RSA_PKCS,                          NULL, 0}},
+               {ENCRYPT_RSA_OAEP_SHA1,         {CKM_RSA_PKCS_OAEP,                     NULL, 0}},
+       };
+       int i;
+
+       for (i = 0; i < countof(mappings); i++)
+       {
+               if (mappings[i].scheme == scheme)
+               {
+                       return &mappings[i].mechanism;
+               }
+       }
+       return NULL;
+}
+
+/**
  * Reauthenticate to do a signature
  */
 static bool reauth(private_pkcs11_private_key_t *this)
@@ -159,7 +183,7 @@ METHOD(private_key_t, sign, bool,
        CK_ULONG len;
        CK_RV rv;
 
-       mechanism = pkcs11_scheme_to_mechanism(scheme);
+       mechanism = pkcs11_signature_scheme_to_mech(scheme);
        if (!mechanism)
        {
                DBG1(DBG_LIB, "signature scheme %N not supported",
@@ -194,9 +218,44 @@ METHOD(private_key_t, sign, bool,
 
 METHOD(private_key_t, decrypt, bool,
        private_pkcs11_private_key_t *this, encryption_scheme_t scheme,
-       chunk_t crypto, chunk_t *plain)
+       chunk_t crypt, chunk_t *plain)
 {
-       return FALSE;
+       CK_MECHANISM_PTR mechanism;
+       CK_BYTE_PTR buf;
+       CK_ULONG len;
+       CK_RV rv;
+
+       mechanism = pkcs11_encryption_scheme_to_mech(scheme);
+       if (!mechanism)
+       {
+               DBG1(DBG_LIB, "encryption scheme %N not supported",
+                        encryption_scheme_names, scheme);
+               return FALSE;
+       }
+       this->mutex->lock(this->mutex);
+       rv = this->lib->f->C_DecryptInit(this->session, mechanism, this->object);
+       if (this->reauth && !reauth(this))
+       {
+               return FALSE;
+       }
+       if (rv != CKR_OK)
+       {
+               this->mutex->unlock(this->mutex);
+               DBG1(DBG_LIB, "C_DecryptInit() failed: %N", ck_rv_names, rv);
+               return FALSE;
+       }
+       len = (get_keysize(this) + 7) / 8;
+       buf = malloc(len);
+       rv = this->lib->f->C_Decrypt(this->session, crypt.ptr, crypt.len, buf, &len);
+       this->mutex->unlock(this->mutex);
+       if (rv != CKR_OK)
+       {
+               DBG1(DBG_LIB, "C_Decrypt() failed: %N", ck_rv_names, rv);
+               free(buf);
+               return FALSE;
+       }
+       *plain = chunk_create(buf, len);
+       return TRUE;
 }
 
 METHOD(private_key_t, get_public_key, public_key_t*,
index 921a027..428913f 100644 (file)
@@ -53,6 +53,11 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args);
 /**
  * Get the Cryptoki mechanism for a signature scheme.
  */
-CK_MECHANISM_PTR pkcs11_scheme_to_mechanism(signature_scheme_t scheme);
+CK_MECHANISM_PTR pkcs11_signature_scheme_to_mech(signature_scheme_t scheme);
+
+/**
+ * Get the Cryptoki mechanism for a encryption scheme.
+ */
+CK_MECHANISM_PTR pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme);
 
 #endif /** PKCS11_PRIVATE_KEY_H_ @}*/
index affd8ca..8d32d9a 100644 (file)
@@ -81,6 +81,12 @@ METHOD(public_key_t, get_type, key_type_t,
        return this->type;
 }
 
+METHOD(public_key_t, get_keysize, int,
+       private_pkcs11_public_key_t *this)
+{
+       return this->k * 8;
+}
+
 METHOD(public_key_t, verify, bool,
        private_pkcs11_public_key_t *this, signature_scheme_t scheme,
        chunk_t data, chunk_t sig)
@@ -88,7 +94,7 @@ METHOD(public_key_t, verify, bool,
        CK_MECHANISM_PTR mechanism;
        CK_RV rv;
 
-       mechanism = pkcs11_scheme_to_mechanism(scheme);
+       mechanism = pkcs11_signature_scheme_to_mech(scheme);
        if (!mechanism)
        {
                DBG1(DBG_LIB, "signature scheme %N not supported",
@@ -120,15 +126,40 @@ METHOD(public_key_t, verify, bool,
 
 METHOD(public_key_t, encrypt, bool,
        private_pkcs11_public_key_t *this, encryption_scheme_t scheme,
-       chunk_t plain, chunk_t *crypto)
+       chunk_t plain, chunk_t *crypt)
 {
-       return FALSE;
-}
+       CK_MECHANISM_PTR mechanism;
+       CK_BYTE_PTR buf;
+       CK_ULONG len;
+       CK_RV rv;
 
-METHOD(public_key_t, get_keysize, int,
-       private_pkcs11_public_key_t *this)
-{
-       return this->k * 8;
+       mechanism = pkcs11_encryption_scheme_to_mech(scheme);
+       if (!mechanism)
+       {
+               DBG1(DBG_LIB, "encryption scheme %N not supported",
+                        encryption_scheme_names, scheme);
+               return FALSE;
+       }
+       this->mutex->lock(this->mutex);
+       rv = this->lib->f->C_EncryptInit(this->session, mechanism, this->object);
+       if (rv != CKR_OK)
+       {
+               this->mutex->unlock(this->mutex);
+               DBG1(DBG_LIB, "C_EncryptInit() failed: %N", ck_rv_names, rv);
+               return FALSE;
+       }
+       len = (get_keysize(this) + 7) / 8;
+       buf = malloc(len);
+       rv = this->lib->f->C_Encrypt(this->session, plain.ptr, plain.len, buf, &len);
+       this->mutex->unlock(this->mutex);
+       if (rv != CKR_OK)
+       {
+               DBG1(DBG_LIB, "C_Encrypt() failed: %N", ck_rv_names, rv);
+               free(buf);
+               return FALSE;
+       }
+       *crypt = chunk_create(buf, len);
+       return TRUE;
 }
 
 /**