Skip to content

Commit

Permalink
Do not refresh object store before fetching object.
Browse files Browse the repository at this point in the history
Before this commit the object store for a file token was always refreshed by reading
the file of the token every time an object of the token was fetched.
Now the HSM may be configured not to refresh when fetching an object. But the
refresh will still be done after an application gets a handle for an object.

The reason for this change is that the CPU time consumed by the reading may not
be negligible for some HW.

It is only the objects store on file that are affected by this feature. If DB is
used refreshing will always be done since the is then no difference in CPU usage.
  • Loading branch information
Lars Silvén authored and larssilven committed Dec 15, 2024
1 parent 4be49e3 commit 3465c40
Show file tree
Hide file tree
Showing 22 changed files with 381 additions and 124 deletions.
46 changes: 24 additions & 22 deletions src/lib/SoftHSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,8 @@ CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
// Load the handle manager
handleManager = new HandleManager();

doRefresh = Configuration::i()->getBool("objectstore.readrefresh", true);

// Set the state to initialised
isInitialised = true;

Expand Down Expand Up @@ -1610,7 +1612,7 @@ CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject

// Check the object handle.
OSObject *object = (OSObject *)handleManager->getObject(hObject);
if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (object == NULL_PTR || !object->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL wasOnToken = object->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL wasPrivate = object->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -1779,7 +1781,7 @@ CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObj

// Check the object handle.
OSObject *object = (OSObject *)handleManager->getObject(hObject);
if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (object == NULL_PTR || !object->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -1827,7 +1829,7 @@ CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObj

// Check the object handle.
OSObject *object = (OSObject *)handleManager->getObject(hObject);
if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (object == NULL_PTR || !object->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

*pulSize = CK_UNAVAILABLE_INFORMATION;

Expand All @@ -1851,7 +1853,7 @@ CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE

// Check the object handle.
OSObject *object = (OSObject *)handleManager->getObject(hObject);
if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (object == NULL_PTR || !object->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -1898,7 +1900,7 @@ CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE

// Check the object handle.
OSObject *object = (OSObject *)handleManager->getObject(hObject);
if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (object == NULL_PTR || !object->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -2168,7 +2170,7 @@ CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -2416,7 +2418,7 @@ CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMec

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -2897,7 +2899,7 @@ CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -3146,7 +3148,7 @@ CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMec

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -3797,7 +3799,7 @@ CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hObject);
if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_KEY_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -3948,7 +3950,7 @@ CK_RV SoftHSM::MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechani

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -4100,7 +4102,7 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -4926,7 +4928,7 @@ CK_RV SoftHSM::MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMecha

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -5078,7 +5080,7 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -6514,7 +6516,7 @@ CK_RV SoftHSM::C_WrapKey

// Check the wrapping key handle.
OSObject *wrapKey = (OSObject *)handleManager->getObject(hWrappingKey);
if (wrapKey == NULL_PTR || !wrapKey->isValid()) return CKR_WRAPPING_KEY_HANDLE_INVALID;
if (wrapKey == NULL_PTR || !wrapKey->isValid(doRefresh)) return CKR_WRAPPING_KEY_HANDLE_INVALID;

CK_BBOOL isWrapKeyOnToken = wrapKey->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -6556,7 +6558,7 @@ CK_RV SoftHSM::C_WrapKey

// Check the to be wrapped key handle.
OSObject *key = (OSObject *)handleManager->getObject(hKey);
if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_KEY_HANDLE_INVALID;

CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -6982,7 +6984,7 @@ CK_RV SoftHSM::C_UnwrapKey

// Check the unwrapping key handle.
OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
if (unwrapKey == NULL_PTR || !unwrapKey->isValid(doRefresh)) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;

CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -7282,7 +7284,7 @@ CK_RV SoftHSM::C_DeriveKey

// Check the key handle.
OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (key == NULL_PTR || !key->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
Expand Down Expand Up @@ -10388,7 +10390,7 @@ CK_RV SoftHSM::deriveDH

// Get the base key handle
OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
if (baseKey == NULL || !baseKey->isValid())
if (baseKey == NULL || !baseKey->isValid(doRefresh))
return CKR_KEY_HANDLE_INVALID;

// Get the DH algorithm handler
Expand Down Expand Up @@ -10720,7 +10722,7 @@ CK_RV SoftHSM::deriveECDH

// Get the base key handle
OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
if (baseKey == NULL || !baseKey->isValid())
if (baseKey == NULL || !baseKey->isValid(doRefresh))
return CKR_KEY_HANDLE_INVALID;

// Get the ECDH algorithm handler
Expand Down Expand Up @@ -11074,7 +11076,7 @@ CK_RV SoftHSM::deriveEDDSA

// Get the base key handle
OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
if (baseKey == NULL || !baseKey->isValid())
if (baseKey == NULL || !baseKey->isValid(doRefresh))
return CKR_KEY_HANDLE_INVALID;

// Get the EDDSA algorithm handler
Expand Down Expand Up @@ -11600,7 +11602,7 @@ CK_RV SoftHSM::deriveSymmetric

// Check the key handle
OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
if (baseKey == NULL_PTR || !baseKey->isValid(doRefresh)) return CKR_OBJECT_HANDLE_INVALID;

// Get the data
ByteString secretValue;
Expand Down
2 changes: 2 additions & 0 deletions src/lib/SoftHSM.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ class SoftHSM
// Is the SoftHSM PKCS #11 library initialised?
bool isInitialised;
bool isRemovable;
// Do refresh of all objects from storage before validating.
bool doRefresh;

SessionObjectStore* sessionObjectStore;
ObjectStore* objectStore;
Expand Down
1 change: 1 addition & 0 deletions src/lib/common/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const struct config Configuration::valid_config[] = {
{ "slots.removable", CONFIG_TYPE_BOOL },
{ "slots.mechanisms", CONFIG_TYPE_STRING },
{ "library.reset_on_fork", CONFIG_TYPE_BOOL },
{ "objectstore.readrefresh", CONFIG_TYPE_BOOL },
{ "", CONFIG_TYPE_UNSUPPORTED }
};

Expand Down
25 changes: 25 additions & 0 deletions src/lib/common/softhsm2.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,31 @@ library.reset_on_fork = true
.fi
.RE
.LP
.SH OBJECTSTORE.READREFRESH
If set to false and if 'objectstore.backend = file', then this will affect
the refreshing of the object store.
Before using an object that is not changed, no files will be read.
.LP
Depending of what kind of HW that is used setting 'false' may improve the
performance of the HSM.
.LP
But the drawback is that if one processes is using an object handle from a
token for multiple function calls then this process may still use the old
unmodified or deleted object even if it is changed or deleted. Another
process may have called C_DestroyObject or C_SetAttributeValue. But every
time a process gets a new handle for an object the objectstore of this
process is updated for all objects even if this property is false.
.LP
If 'objectstore.backend = db' then the value of this property is ignored.
.LP
Default is true.
.LP
.RS
.nf
objectstore.readrefresh = false
.fi
.RE
.LP
.SH ENVIRONMENT
.TP
SOFTHSM2_CONF
Expand Down
3 changes: 3 additions & 0 deletions src/lib/common/softhsm2.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ slots.mechanisms = ALL

# If the library should reset the state on fork
library.reset_on_fork = false

# Set to false if there should be no update of a token objects each time it is used.
objectstore.readrefresh = true
2 changes: 1 addition & 1 deletion src/lib/object_store/DBObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1364,7 +1364,7 @@ bool DBObject::deleteAttribute(CK_ATTRIBUTE_TYPE type)
}

// The validity state of the object
bool DBObject::isValid()
bool DBObject::isValid(const bool doRefresh __attribute__((unused)))
{
MutexLocker lock(_mutex);

Expand Down
2 changes: 1 addition & 1 deletion src/lib/object_store/DBObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class DBObject : public OSObject
virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type);

// The validity state of the object
virtual bool isValid();
virtual bool isValid(bool doRefresh);

// Start an attribute set transaction; this method is used when - for
// example - a key is generated and all its attributes need to be
Expand Down
2 changes: 1 addition & 1 deletion src/lib/object_store/DBToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ OSObject *DBToken::createObject()
return NULL;
}

if (!newObject->isValid())
if (!newObject->isValid(true))
{
newObject->abortTransaction();
delete newObject;
Expand Down
3 changes: 2 additions & 1 deletion src/lib/object_store/OSObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class OSObject
virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type) = 0;

// The validity state of the object
virtual bool isValid() = 0;
// If doRefresh==true then update the object from the storage before validating.
virtual bool isValid(bool doRefresh=true) = 0;

// Start an attribute set transaction; this method is used when - for
// example - a key is generated and all its attributes need to be
Expand Down
15 changes: 10 additions & 5 deletions src/lib/object_store/OSToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ bool OSToken::setSOPIN(const ByteString& soPINBlob)
// Get the SO PIN
bool OSToken::getSOPIN(ByteString& soPINBlob)
{
if (!valid || !tokenObject->isValid())
// this is done so rarely so will not impact the performance to refresh.
if (!valid || !tokenObject->isValid(true))
{
return false;
}
Expand Down Expand Up @@ -223,7 +224,8 @@ bool OSToken::setUserPIN(ByteString userPINBlob)
// Get the user PIN
bool OSToken::getUserPIN(ByteString& userPINBlob)
{
if (!valid || !tokenObject->isValid())
// this is done so rarely so will not impact the performance to refresh.
if (!valid || !tokenObject->isValid(true))
{
return false;
}
Expand All @@ -243,7 +245,8 @@ bool OSToken::getUserPIN(ByteString& userPINBlob)
// Retrieve the token label
bool OSToken::getTokenLabel(ByteString& label)
{
if (!valid || !tokenObject->isValid())
// this is done so rarely so will not impact the performance to refresh.
if (!valid || !tokenObject->isValid(true))
{
return false;
}
Expand All @@ -263,7 +266,8 @@ bool OSToken::getTokenLabel(ByteString& label)
// Retrieve the token serial
bool OSToken::getTokenSerial(ByteString& serial)
{
if (!valid || !tokenObject->isValid())
// this is done so rarely so will not impact the performance to refresh.
if (!valid || !tokenObject->isValid(true))
{
return false;
}
Expand All @@ -283,7 +287,8 @@ bool OSToken::getTokenSerial(ByteString& serial)
// Get the token flags
bool OSToken::getTokenFlags(CK_ULONG& flags)
{
if (!valid || !tokenObject->isValid())
// this is done so rarely so will not impact the performance to refresh.
if (!valid || !tokenObject->isValid(true))
{
return false;
}
Expand Down
10 changes: 6 additions & 4 deletions src/lib/object_store/ObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,11 +262,13 @@ bool ObjectFile::deleteAttribute(CK_ATTRIBUTE_TYPE type)
return valid;
}

// The validity state of the object (refresh from disk as a side effect)
bool ObjectFile::isValid()
// The validity state of the object (may refresh from disk as a side effect)
bool ObjectFile::isValid(const bool doRefresh)
{
refresh();

if(doRefresh)
{
refresh();
}
return valid;
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/object_store/ObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ObjectFile : public OSObject
virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type);

// The validity state of the object (refresh from disk as a side effect)
virtual bool isValid();
virtual bool isValid(bool doRefresh);

// Invalidate the object file externally; this method is normally
// only called by the OSToken class in case an object file has
Expand Down
3 changes: 2 additions & 1 deletion src/lib/object_store/SessionObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ bool SessionObject::deleteAttribute(CK_ATTRIBUTE_TYPE type)
}

// The validity state of the object
bool SessionObject::isValid()
// the doRefresh parameter has no meaning for this implementation since noting is stored on disk.
bool SessionObject::isValid(const bool /*doRefresh*/)
{
return valid;
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib/object_store/SessionObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ class SessionObject : public OSObject
virtual bool deleteAttribute(CK_ATTRIBUTE_TYPE type);

// The validity state of the object
virtual bool isValid();
// doRefresh has no meaning since this is a session object.
virtual bool isValid(bool doRefresh=true);

bool hasSlotID(CK_SLOT_ID inSlotID);

Expand Down
Loading

0 comments on commit 3465c40

Please sign in to comment.