From 82372499da316d0532cb3a6a2e1655d5d93b0fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hlavat=C3=BD?= Date: Thu, 26 Mar 2020 15:17:18 +0100 Subject: [PATCH 1/4] CopyObject: Add warning on inconsistent nextAttributeType behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps to debug backends. Signed-off-by: Ondřej Hlavatý --- src/lib/SoftHSM.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/SoftHSM.cpp b/src/lib/SoftHSM.cpp index 54f9089f..6ec74b96 100644 --- a/src/lib/SoftHSM.cpp +++ b/src/lib/SoftHSM.cpp @@ -1684,6 +1684,7 @@ CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject { if (!object->attributeExists(attrType)) { + WARNING_MSG("Attribute 0x%lx does not exist even though it was reported as next."); rv = CKR_FUNCTION_FAILED; break; } From beb482d1f0838d67d65038b9dd08275f7c01572f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hlavat=C3=BD?= Date: Thu, 26 Mar 2020 15:17:19 +0100 Subject: [PATCH 2/4] DB: Create attributes view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This view can be used to look up attributes. Signed-off-by: Ondřej Hlavatý --- src/lib/object_store/DBObject.cpp | 39 +++++++++++++++++++++++++++++++ src/lib/object_store/DBObject.h | 3 +++ src/lib/object_store/DBToken.cpp | 4 ++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/lib/object_store/DBObject.cpp b/src/lib/object_store/DBObject.cpp index a2941734..660c46ad 100644 --- a/src/lib/object_store/DBObject.cpp +++ b/src/lib/object_store/DBObject.cpp @@ -202,6 +202,37 @@ bool DBObject::createTables() return true; } +// update schema to support new features with dbs from previous versions. +bool DBObject::migrateTables() +{ + MutexLocker lock(_mutex); + + if (_connection == NULL) + { + ERROR_MSG("Object is not connected to the database."); + return false; + } + + // attributes + DB::Statement cr_attrs = _connection->prepare( + "create view if not exists attributes as " + "select object_id, type from attribute_array " + "union all select object_id, type from attribute_binary " + "union all select object_id, type from attribute_boolean " + "union all select object_id, type from attribute_datetime " + "union all select object_id, type from attribute_integer " + "union all select object_id, type from attribute_real " + "union all select object_id, type from attribute_text" + ); + if (!_connection->execute(cr_attrs)) + { + ERROR_MSG("Failed to create \"attributes\" view"); + return false; + } + + return true; +} + bool DBObject::dropTables() { MutexLocker lock(_mutex); @@ -212,6 +243,14 @@ bool DBObject::dropTables() return false; } + // attributes + DB::Statement dr_attrs = _connection->prepare("drop view attributes"); + if (!_connection->execute(dr_attrs)) + { + ERROR_MSG("Failed to drop \"attributes\" view"); + return false; + } + // Create the tables inside the database DB::Statement dr_object = _connection->prepare("drop table object"); if (!_connection->execute(dr_object)) diff --git a/src/lib/object_store/DBObject.h b/src/lib/object_store/DBObject.h index 4dc1249f..5a81c254 100644 --- a/src/lib/object_store/DBObject.h +++ b/src/lib/object_store/DBObject.h @@ -62,6 +62,9 @@ class DBObject : public OSObject // create tables to support storage of attributes for the object. bool createTables(); + // update schema to support new features with dbs from previous versions. + bool migrateTables(); + // drop tables that support storage of attributes for the object. bool dropTables(); diff --git a/src/lib/object_store/DBToken.cpp b/src/lib/object_store/DBToken.cpp index 53b91f47..498eb58e 100644 --- a/src/lib/object_store/DBToken.cpp +++ b/src/lib/object_store/DBToken.cpp @@ -122,7 +122,7 @@ DBToken::DBToken(const std::string &baseDir, const std::string &tokenName, int u // First create the tables that support storage of object attributes and then insert the object containing // the token info into the database. - if (!tokenObject.createTables() || !tokenObject.insert() || tokenObject.objectId()!=DBTOKEN_OBJECT_TOKENINFO) + if (!tokenObject.createTables() || !tokenObject.migrateTables() || !tokenObject.insert() || tokenObject.objectId()!=DBTOKEN_OBJECT_TOKENINFO) { tokenObject.dropConnection(); @@ -211,7 +211,7 @@ DBToken::DBToken(const std::string &baseDir, const std::string &tokenName, int u DBObject tokenObject(_connection); // First find the token obect that indicates the token is properly initialized. - if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO)) + if (!tokenObject.find(DBTOKEN_OBJECT_TOKENINFO) || !tokenObject.migrateTables()) { tokenObject.dropConnection(); From 4fc483a87041ff881f5928a3e48ae0709a88bc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hlavat=C3=BD?= Date: Thu, 26 Mar 2020 15:17:20 +0100 Subject: [PATCH 3/4] DB: Implement DBObject::nextAttributeType MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses previously added view to select the attribute with lowest id larger than the last one. Signed-off-by: Ondřej Hlavatý --- src/lib/object_store/DBObject.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/lib/object_store/DBObject.cpp b/src/lib/object_store/DBObject.cpp index 660c46ad..eb51c70b 100644 --- a/src/lib/object_store/DBObject.cpp +++ b/src/lib/object_store/DBObject.cpp @@ -1121,7 +1121,7 @@ ByteString DBObject::getByteStringValue(CK_ATTRIBUTE_TYPE type) } } -CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE) +CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE last) { MutexLocker lock(_mutex); @@ -1136,8 +1136,21 @@ CK_ATTRIBUTE_TYPE DBObject::nextAttributeType(CK_ATTRIBUTE_TYPE) return false; } - // FIXME: implement for C_CopyObject - return CKA_CLASS; + DB::Statement stmt = _connection->prepare("select MIN(type) from attributes where object_id=%lld and type>%ld", _objectId, last); + + if (!stmt.isValid()) + { + WARNING_MSG("Failed to prepare next attribute query"); + return CKA_CLASS; + } + + DB::Result result = _connection->perform(stmt); + if (!result.isValid()) + { + return CKA_CLASS; + } + + return result.getULongLong(1); } // Set the specified attribute From e8d542e0183d019fb4834784b22b40a52b403f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hlavat=C3=BD?= Date: Thu, 26 Mar 2020 15:17:22 +0100 Subject: [PATCH 4/4] DB: Add missing attribute types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are commonly present and missing them causes inconsistent behavior - attributes can be stored successfully but not retrieved later. Signed-off-by: Ondřej Hlavatý --- src/lib/object_store/DBObject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/object_store/DBObject.cpp b/src/lib/object_store/DBObject.cpp index eb51c70b..fb3cce6f 100644 --- a/src/lib/object_store/DBObject.cpp +++ b/src/lib/object_store/DBObject.cpp @@ -489,6 +489,7 @@ static AttributeKind attributeKind(CK_ATTRIBUTE_TYPE type) case CKA_EXPONENT_1: return akBinary; case CKA_EXPONENT_2: return akBinary; case CKA_COEFFICIENT: return akBinary; + case CKA_PUBLIC_KEY_INFO: return akBinary; case CKA_PRIME: return akBinary; case CKA_SUBPRIME: return akBinary; case CKA_BASE: return akBinary; @@ -503,6 +504,7 @@ static AttributeKind attributeKind(CK_ATTRIBUTE_TYPE type) case CKA_KEY_GEN_MECHANISM: return akInteger; case CKA_MODIFIABLE: return akBoolean; case CKA_COPYABLE: return akBoolean; + case CKA_DESTROYABLE: return akBoolean; case CKA_ECDSA_PARAMS: return akBinary; case CKA_EC_POINT: return akBinary; case CKA_SECONDARY_AUTH: return akBoolean;