diff -rupN softhsm-1.1.3/src/lib/attribute.cpp softhsm-mod/src/lib/attribute.cpp --- softhsm-1.1.3/src/lib/attribute.cpp 2010-01-25 20:54:13.000000000 +0100 +++ softhsm-mod/src/lib/attribute.cpp 2010-02-17 10:42:11.000000000 +0100 @@ -43,6 +43,71 @@ #include using namespace Botan; + +CK_RV valAttributeCertificate(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { + + // Evaluate the template + for(CK_ULONG i = 0; i < ulCount; i++) { + if(pTemplate[i].pValue == NULL_PTR && pTemplate[i].ulValueLen > 0) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + switch(pTemplate[i].type) { + case CKA_CLASS: + if(pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS)) { + CK_OBJECT_CLASS oClass = *(CK_OBJECT_CLASS*)pTemplate[i].pValue; + if(oClass != CKO_CERTIFICATE) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + } else { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + break; + case CKA_CERTIFICATE_TYPE: + if(pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS)) { + CK_OBJECT_CLASS oType = *(CK_OBJECT_CLASS*)pTemplate[i].pValue; + if(oType != CKC_X_509) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + } else { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + break; + + case CKA_TOKEN: + case CKA_MODIFIABLE: + case CKA_LABEL: + case CKA_HASH_OF_SUBJECT_PUBLIC_KEY: + case CKA_HASH_OF_ISSUER_PUBLIC_KEY: + case CKA_JAVA_MIDP_SECURITY_DOMAIN: + case CKA_ID: + case CKA_SERIAL_NUMBER: + case CKA_ISSUER: + case CKA_SUBJECT: + if(pTemplate[i].ulValueLen == 0) { + // Variable length, we check that it is not empty + return CKR_ATTRIBUTE_VALUE_INVALID; + } + break; + case CKA_START_DATE: + case CKA_END_DATE: + if(pTemplate[i].ulValueLen != sizeof(CK_DATE) && + pTemplate[i].ulValueLen != 0) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + break; + case CKA_VALUE: + if(pTemplate[i].ulValueLen == 0) { + // Variable length, we check that it is not empty + return CKR_ATTRIBUTE_VALUE_INVALID; + } + break; + default: + // Invalid attribute + return CKR_ATTRIBUTE_TYPE_INVALID; + } + } + return CKR_OK; +} CK_RV valAttributePubRSA(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { BigInt bigN = BigInt(0); BigInt bigE = BigInt(0); diff -rupN softhsm-1.1.3/src/lib/attribute.h softhsm-mod/src/lib/attribute.h --- softhsm-1.1.3/src/lib/attribute.h 2010-01-25 20:54:14.000000000 +0100 +++ softhsm-mod/src/lib/attribute.h 2010-02-17 09:47:36.000000000 +0100 @@ -35,6 +35,7 @@ #include using namespace Botan; +CK_RV valAttributeCertificate(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV valAttributePubRSA(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_RV valAttributePrivRSA(RandomNumberGenerator *rng, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); diff -rupN softhsm-1.1.3/src/lib/SoftDatabase.cpp softhsm-mod/src/lib/SoftDatabase.cpp --- softhsm-1.1.3/src/lib/SoftDatabase.cpp 2010-01-25 20:54:14.000000000 +0100 +++ softhsm-mod/src/lib/SoftDatabase.cpp 2010-02-17 09:38:57.000000000 +0100 @@ -525,7 +525,113 @@ CK_OBJECT_HANDLE SoftDatabase::addRSAKey return objectID; } +/* Import Certificate */ +CK_OBJECT_HANDLE SoftDatabase::importPublicCert(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { + // Begin the transaction + int retVal = 0; + while((retVal = sqlite3_exec(db, "BEGIN IMMEDIATE;", NULL, NULL, NULL)) == SQLITE_BUSY) { + sched_yield(); + } + if(retVal != SQLITE_OK) { + return CK_INVALID_HANDLE; + } + + CHECK_DB_RESPONSE(sqlite3_step(insert_object_sql) != SQLITE_DONE); + CK_OBJECT_HANDLE objectID = sqlite3_last_insert_rowid(db); + sqlite3_reset(insert_object_sql); + + CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE; + + // Created by db handle. So we can remove the correct session objects in the future. + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_VENDOR_DEFINED, &db, sizeof(db)) != CKR_OK); + + // General information + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_LOCAL, &ckFalse, sizeof(ckFalse)) != CKR_OK); + + //CK_UTF8CHAR label [] = "Label"; + + // Default values, may be changed by the template. + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_CLASS, NULL_PTR, 0) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_CERTIFICATE_TYPE, NULL_PTR, 0) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_OWNER, NULL_PTR, 0) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_VALUE, NULL_PTR, 0) != CKR_OK); + + //CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_LABEL, label, sizeof(label)-1) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_LABEL, NULL_PTR, 0) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_PRIVATE, &ckFalse, sizeof(ckFalse)) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_ID, NULL_PTR, 0) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_SUBJECT, NULL_PTR, 0) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_MODIFIABLE, &ckTrue, sizeof(ckTrue)) != CKR_OK); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_TOKEN, &ckFalse, sizeof(ckFalse)) != CKR_OK); + + // Extract the attributes + for(CK_ULONG i = 0; i < ulCount; i++) { + switch(pTemplate[i].type) { + case CKA_CLASS: + DEBUG_MSG("importPublicCert", "We found a CKA_CLASS Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_CLASS, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_CERTIFICATE_TYPE: + DEBUG_MSG("importPublicCert", "We found a CKA_CERTIFICATE_TYPE Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_CERTIFICATE_TYPE, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_OWNER: + DEBUG_MSG("importPublicCert", "We found a CKA_OWNER Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_OWNER, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_TOKEN: + DEBUG_MSG("importPublicCert", "We found a CKA_TOKEN Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_TOKEN, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_MODIFIABLE: + DEBUG_MSG("importPublicCert", "We found a CKA_MODIFIABLE Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_MODIFIABLE, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_SUBJECT: + DEBUG_MSG("importPublicCert", "We found a CKA_SUBJECT Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_SUBJECT, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_VALUE: + DEBUG_MSG("importPublicCert", "We found a CKA_VALUE Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_VALUE, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_ID: + DEBUG_MSG("importPublicCert", "We found a CKA_ID Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_ID, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_LABEL: + DEBUG_MSG("importPublicCert", "We found a CKA_LABEL Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_LABEL, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + case CKA_APPLICATION: + DEBUG_MSG("importPublicCert", "We found a CKA_APPLICATION Attribute"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, CKA_APPLICATION, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + default: + DEBUG_MSG("importPublicCert", "We found an unidentified CKA_XXX Attribute, defaulting"); + CHECK_DB_RESPONSE(this->saveAttribute(objectID, pTemplate[i].type, pTemplate[i].pValue, + pTemplate[i].ulValueLen) != CKR_OK); + break; + } + } + + + while(sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL) == SQLITE_BUSY) { + sched_yield(); + } + return objectID; +} // Import an external public key. The template has been validated. CK_OBJECT_HANDLE SoftDatabase::importPublicKey(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { diff -rupN softhsm-1.1.3/src/lib/SoftDatabase.h softhsm-mod/src/lib/SoftDatabase.h --- softhsm-1.1.3/src/lib/SoftDatabase.h 2010-01-25 20:54:13.000000000 +0100 +++ softhsm-mod/src/lib/SoftDatabase.h 2010-02-17 09:38:57.000000000 +0100 @@ -74,6 +74,7 @@ class SoftDatabase { CK_ULONG ulPublicKeyAttributeCount); CK_OBJECT_HANDLE addRSAKeyPriv(RSA_PrivateKey *rsaKey, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount); + CK_OBJECT_HANDLE importPublicCert(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_OBJECT_HANDLE importPublicKey(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); CK_OBJECT_HANDLE importPrivateKey(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); void destroySessObj(); diff -rupN softhsm-1.1.3/src/lib/SoftHSMInternal.cpp softhsm-mod/src/lib/SoftHSMInternal.cpp --- softhsm-1.1.3/src/lib/SoftHSMInternal.cpp 2010-01-25 20:54:14.000000000 +0100 +++ softhsm-mod/src/lib/SoftHSMInternal.cpp 2010-02-17 09:45:03.000000000 +0100 @@ -689,13 +689,18 @@ CK_RV SoftHSMInternal::createObject(CK_S CK_OBJECT_HANDLE oHandle; switch(oClass) { + case CKO_CERTIFICATE: + rv = valAttributeCertificate(pTemplate, ulCount); + CHECK_DEBUG_RETURN(rv != CKR_OK, "C_CreateObject", "Problem with object template", rv); + oHandle = session->db->importPublicCert(pTemplate, ulCount); + break; + case CKO_PUBLIC_KEY: if(keyType == CKK_RSA) { rv = valAttributePubRSA(pTemplate, ulCount); CHECK_DEBUG_RETURN(rv != CKR_OK, "C_CreateObject", "Problem with object template", rv); oHandle = session->db->importPublicKey(pTemplate, ulCount); } else { - DEBUG_MSG("C_CreateObject", "The key type is not supported"); return CKR_ATTRIBUTE_VALUE_INVALID; } break;