aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2010-08-11 12:12:37 +0200
committerMartin Willi <martin@revosec.ch>2010-08-11 12:12:37 +0200
commit01e4f5f32f81972cbab0e0dc0564cd74d6ce800e (patch)
tree258d4edf9dab308cbb02997202cb9059a71a2f0a /src/libstrongswan
parentaea735ef63b809d5c50e058f164cea362fe3893c (diff)
downloadstrongswan-01e4f5f32f81972cbab0e0dc0564cd74d6ce800e.tar.bz2
strongswan-01e4f5f32f81972cbab0e0dc0564cd74d6ce800e.tar.xz
Implemented public key encryption/private key decryption in PKCS#11
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c67
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h7
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c47
3 files changed, 108 insertions, 13 deletions
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
index 52a9e09c2..e51d0aae4 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c
@@ -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*,
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h
index 921a02732..428913f0a 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.h
@@ -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_ @}*/
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
index affd8cafc..8d32d9a3f 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
@@ -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;
}
/**