pkcs11: Instead of a mutex use a new session to do multipart operations.
This commit is contained in:
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2011 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2010 Martin Willi
|
* Copyright (C) 2010 Martin Willi
|
||||||
* Copyright (C) 2010 revosec AG
|
* Copyright (C) 2010 revosec AG
|
||||||
*
|
*
|
||||||
@@ -19,7 +22,6 @@
|
|||||||
#include "pkcs11_manager.h"
|
#include "pkcs11_manager.h"
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <threading/mutex.h>
|
|
||||||
|
|
||||||
typedef struct private_pkcs11_private_key_t private_pkcs11_private_key_t;
|
typedef struct private_pkcs11_private_key_t private_pkcs11_private_key_t;
|
||||||
|
|
||||||
@@ -38,16 +40,16 @@ struct private_pkcs11_private_key_t {
|
|||||||
*/
|
*/
|
||||||
pkcs11_library_t *lib;
|
pkcs11_library_t *lib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slot the token is in
|
||||||
|
*/
|
||||||
|
CK_SLOT_ID slot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Token session
|
* Token session
|
||||||
*/
|
*/
|
||||||
CK_SESSION_HANDLE session;
|
CK_SESSION_HANDLE session;
|
||||||
|
|
||||||
/**
|
|
||||||
* Mutex to lock session
|
|
||||||
*/
|
|
||||||
mutex_t *mutex;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key object on the token
|
* Key object on the token
|
||||||
*/
|
*/
|
||||||
@@ -141,7 +143,8 @@ CK_MECHANISM_PTR pkcs11_encryption_scheme_to_mech(encryption_scheme_t scheme)
|
|||||||
/**
|
/**
|
||||||
* Reauthenticate to do a signature
|
* Reauthenticate to do a signature
|
||||||
*/
|
*/
|
||||||
static bool reauth(private_pkcs11_private_key_t *this)
|
static bool reauth(private_pkcs11_private_key_t *this,
|
||||||
|
CK_SESSION_HANDLE session)
|
||||||
{
|
{
|
||||||
enumerator_t *enumerator;
|
enumerator_t *enumerator;
|
||||||
shared_key_t *shared;
|
shared_key_t *shared;
|
||||||
@@ -155,7 +158,7 @@ static bool reauth(private_pkcs11_private_key_t *this)
|
|||||||
{
|
{
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
pin = shared->get_key(shared);
|
pin = shared->get_key(shared);
|
||||||
rv = this->lib->f->C_Login(this->session, CKU_CONTEXT_SPECIFIC,
|
rv = this->lib->f->C_Login(session, CKU_CONTEXT_SPECIFIC,
|
||||||
pin.ptr, pin.len);
|
pin.ptr, pin.len);
|
||||||
if (rv == CKR_OK)
|
if (rv == CKR_OK)
|
||||||
{
|
{
|
||||||
@@ -179,6 +182,7 @@ METHOD(private_key_t, sign, bool,
|
|||||||
chunk_t data, chunk_t *signature)
|
chunk_t data, chunk_t *signature)
|
||||||
{
|
{
|
||||||
CK_MECHANISM_PTR mechanism;
|
CK_MECHANISM_PTR mechanism;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
CK_BYTE_PTR buf;
|
CK_BYTE_PTR buf;
|
||||||
CK_ULONG len;
|
CK_ULONG len;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
@@ -190,22 +194,29 @@ METHOD(private_key_t, sign, bool,
|
|||||||
signature_scheme_names, scheme);
|
signature_scheme_names, scheme);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
this->mutex->lock(this->mutex);
|
rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, NULL, NULL,
|
||||||
rv = this->lib->f->C_SignInit(this->session, mechanism, this->object);
|
&session);
|
||||||
if (this->reauth && !reauth(this))
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
rv = this->lib->f->C_SignInit(session, mechanism, this->object);
|
||||||
|
if (this->reauth && !reauth(this, session))
|
||||||
|
{
|
||||||
|
this->lib->f->C_CloseSession(session);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
this->mutex->unlock(this->mutex);
|
this->lib->f->C_CloseSession(session);
|
||||||
DBG1(DBG_LIB, "C_SignInit() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_SignInit() failed: %N", ck_rv_names, rv);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
len = (get_keysize(this) + 7) / 8;
|
len = (get_keysize(this) + 7) / 8;
|
||||||
buf = malloc(len);
|
buf = malloc(len);
|
||||||
rv = this->lib->f->C_Sign(this->session, data.ptr, data.len, buf, &len);
|
rv = this->lib->f->C_Sign(session, data.ptr, data.len, buf, &len);
|
||||||
this->mutex->unlock(this->mutex);
|
this->lib->f->C_CloseSession(session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "C_Sign() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_Sign() failed: %N", ck_rv_names, rv);
|
||||||
@@ -221,6 +232,7 @@ METHOD(private_key_t, decrypt, bool,
|
|||||||
chunk_t crypt, chunk_t *plain)
|
chunk_t crypt, chunk_t *plain)
|
||||||
{
|
{
|
||||||
CK_MECHANISM_PTR mechanism;
|
CK_MECHANISM_PTR mechanism;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
CK_BYTE_PTR buf;
|
CK_BYTE_PTR buf;
|
||||||
CK_ULONG len;
|
CK_ULONG len;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
@@ -232,22 +244,29 @@ METHOD(private_key_t, decrypt, bool,
|
|||||||
encryption_scheme_names, scheme);
|
encryption_scheme_names, scheme);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
this->mutex->lock(this->mutex);
|
rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, NULL, NULL,
|
||||||
rv = this->lib->f->C_DecryptInit(this->session, mechanism, this->object);
|
&session);
|
||||||
if (this->reauth && !reauth(this))
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
|
DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
rv = this->lib->f->C_DecryptInit(session, mechanism, this->object);
|
||||||
|
if (this->reauth && !reauth(this, session))
|
||||||
|
{
|
||||||
|
this->lib->f->C_CloseSession(session);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
this->mutex->unlock(this->mutex);
|
this->lib->f->C_CloseSession(session);
|
||||||
DBG1(DBG_LIB, "C_DecryptInit() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_DecryptInit() failed: %N", ck_rv_names, rv);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
len = (get_keysize(this) + 7) / 8;
|
len = (get_keysize(this) + 7) / 8;
|
||||||
buf = malloc(len);
|
buf = malloc(len);
|
||||||
rv = this->lib->f->C_Decrypt(this->session, crypt.ptr, crypt.len, buf, &len);
|
rv = this->lib->f->C_Decrypt(session, crypt.ptr, crypt.len, buf, &len);
|
||||||
this->mutex->unlock(this->mutex);
|
this->lib->f->C_CloseSession(session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "C_Decrypt() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_Decrypt() failed: %N", ck_rv_names, rv);
|
||||||
@@ -294,7 +313,6 @@ METHOD(private_key_t, destroy, void,
|
|||||||
{
|
{
|
||||||
this->pubkey->destroy(this->pubkey);
|
this->pubkey->destroy(this->pubkey);
|
||||||
}
|
}
|
||||||
this->mutex->destroy(this->mutex);
|
|
||||||
this->keyid->destroy(this->keyid);
|
this->keyid->destroy(this->keyid);
|
||||||
this->lib->f->C_CloseSession(this->session);
|
this->lib->f->C_CloseSession(this->session);
|
||||||
free(this);
|
free(this);
|
||||||
@@ -587,7 +605,7 @@ pkcs11_private_key_t *pkcs11_private_key_connect(key_type_t type, va_list args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
|
this->slot = slot;
|
||||||
this->keyid = identification_create_from_encoding(ID_KEY_ID, keyid);
|
this->keyid = identification_create_from_encoding(ID_KEY_ID, keyid);
|
||||||
|
|
||||||
if (!login(this, slot))
|
if (!login(this, slot))
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2011 Tobias Brunner
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
* Copyright (C) 2010 Martin Willi
|
* Copyright (C) 2010 Martin Willi
|
||||||
* Copyright (C) 2010 revosec AG
|
* Copyright (C) 2010 revosec AG
|
||||||
*
|
*
|
||||||
@@ -20,7 +23,6 @@
|
|||||||
#include "pkcs11_manager.h"
|
#include "pkcs11_manager.h"
|
||||||
|
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <threading/mutex.h>
|
|
||||||
|
|
||||||
typedef struct private_pkcs11_public_key_t private_pkcs11_public_key_t;
|
typedef struct private_pkcs11_public_key_t private_pkcs11_public_key_t;
|
||||||
|
|
||||||
@@ -64,11 +66,6 @@ struct private_pkcs11_public_key_t {
|
|||||||
*/
|
*/
|
||||||
CK_OBJECT_HANDLE object;
|
CK_OBJECT_HANDLE object;
|
||||||
|
|
||||||
/**
|
|
||||||
* Mutex to lock session
|
|
||||||
*/
|
|
||||||
mutex_t *mutex;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* References to this key
|
* References to this key
|
||||||
*/
|
*/
|
||||||
@@ -92,6 +89,7 @@ METHOD(public_key_t, verify, bool,
|
|||||||
chunk_t data, chunk_t sig)
|
chunk_t data, chunk_t sig)
|
||||||
{
|
{
|
||||||
CK_MECHANISM_PTR mechanism;
|
CK_MECHANISM_PTR mechanism;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
|
|
||||||
mechanism = pkcs11_signature_scheme_to_mech(scheme);
|
mechanism = pkcs11_signature_scheme_to_mech(scheme);
|
||||||
@@ -105,17 +103,22 @@ METHOD(public_key_t, verify, bool,
|
|||||||
{ /* trim leading zero byte in sig */
|
{ /* trim leading zero byte in sig */
|
||||||
sig = chunk_skip(sig, 1);
|
sig = chunk_skip(sig, 1);
|
||||||
}
|
}
|
||||||
this->mutex->lock(this->mutex);
|
rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, NULL, NULL,
|
||||||
rv = this->lib->f->C_VerifyInit(this->session, mechanism, this->object);
|
&session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
this->mutex->unlock(this->mutex);
|
DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
rv = this->lib->f->C_VerifyInit(session, mechanism, this->object);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
{
|
||||||
|
this->lib->f->C_CloseSession(session);
|
||||||
DBG1(DBG_LIB, "C_VerifyInit() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_VerifyInit() failed: %N", ck_rv_names, rv);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
rv = this->lib->f->C_Verify(this->session, data.ptr, data.len,
|
rv = this->lib->f->C_Verify(session, data.ptr, data.len, sig.ptr, sig.len);
|
||||||
sig.ptr, sig.len);
|
this->lib->f->C_CloseSession(session);
|
||||||
this->mutex->unlock(this->mutex);
|
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "C_Verify() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_Verify() failed: %N", ck_rv_names, rv);
|
||||||
@@ -129,6 +132,7 @@ METHOD(public_key_t, encrypt, bool,
|
|||||||
chunk_t plain, chunk_t *crypt)
|
chunk_t plain, chunk_t *crypt)
|
||||||
{
|
{
|
||||||
CK_MECHANISM_PTR mechanism;
|
CK_MECHANISM_PTR mechanism;
|
||||||
|
CK_SESSION_HANDLE session;
|
||||||
CK_BYTE_PTR buf;
|
CK_BYTE_PTR buf;
|
||||||
CK_ULONG len;
|
CK_ULONG len;
|
||||||
CK_RV rv;
|
CK_RV rv;
|
||||||
@@ -140,18 +144,24 @@ METHOD(public_key_t, encrypt, bool,
|
|||||||
encryption_scheme_names, scheme);
|
encryption_scheme_names, scheme);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
this->mutex->lock(this->mutex);
|
rv = this->lib->f->C_OpenSession(this->slot, CKF_SERIAL_SESSION, NULL, NULL,
|
||||||
rv = this->lib->f->C_EncryptInit(this->session, mechanism, this->object);
|
&session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
this->mutex->unlock(this->mutex);
|
DBG1(DBG_CFG, "opening PKCS#11 session failed: %N", ck_rv_names, rv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
rv = this->lib->f->C_EncryptInit(session, mechanism, this->object);
|
||||||
|
if (rv != CKR_OK)
|
||||||
|
{
|
||||||
|
this->lib->f->C_CloseSession(session);
|
||||||
DBG1(DBG_LIB, "C_EncryptInit() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_EncryptInit() failed: %N", ck_rv_names, rv);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
len = (get_keysize(this) + 7) / 8;
|
len = (get_keysize(this) + 7) / 8;
|
||||||
buf = malloc(len);
|
buf = malloc(len);
|
||||||
rv = this->lib->f->C_Encrypt(this->session, plain.ptr, plain.len, buf, &len);
|
rv = this->lib->f->C_Encrypt(session, plain.ptr, plain.len, buf, &len);
|
||||||
this->mutex->unlock(this->mutex);
|
this->lib->f->C_CloseSession(session);
|
||||||
if (rv != CKR_OK)
|
if (rv != CKR_OK)
|
||||||
{
|
{
|
||||||
DBG1(DBG_LIB, "C_Encrypt() failed: %N", ck_rv_names, rv);
|
DBG1(DBG_LIB, "C_Encrypt() failed: %N", ck_rv_names, rv);
|
||||||
@@ -243,7 +253,6 @@ METHOD(public_key_t, destroy, void,
|
|||||||
{
|
{
|
||||||
lib->encoding->clear_cache(lib->encoding, this);
|
lib->encoding->clear_cache(lib->encoding, this);
|
||||||
this->lib->f->C_CloseSession(this->session);
|
this->lib->f->C_CloseSession(this->session);
|
||||||
this->mutex->destroy(this->mutex);
|
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,7 +287,6 @@ static private_pkcs11_public_key_t *create(key_type_t type, size_t k,
|
|||||||
.slot = slot,
|
.slot = slot,
|
||||||
.session = session,
|
.session = session,
|
||||||
.object = object,
|
.object = object,
|
||||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
|
||||||
.ref = 1,
|
.ref = 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user