X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmanager%2Fservice%2Fckm-logic.cpp;h=7b1ef9630edb2788a06a425fbe89f0596d90ced1;hb=b4b2310fa8c7dc6089131a83195a17a07d7e6850;hp=e8e7f0c2414b03557c710ac89bdedd54693922ea;hpb=ea43f2088832df7a4bdda3714bc595b14d46af2c;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index e8e7f0c..7b1ef96 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -29,11 +29,18 @@ #include #include #include +#include +#include +#include -#include +#include namespace { -const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs"; +const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs"; +const char * const INIT_VALUES_DIR = "/opt/data/ckm/initial_values/"; +const char * const INIT_VALUES_XSD = "/usr/share/ckm/initial_values.xsd"; +const char * const INIT_VALUES_FILE_SUFFIX = ".xml"; +const char * const SYSTEM_DB_PASSWD = "cAtRugU7"; bool isLabelValid(const CKM::Label &label) { // TODO: copy code from libprivilege control (for check smack label) @@ -47,16 +54,54 @@ bool isNameValid(const CKM::Name &name) { return false; return true; } - } // anonymous namespace namespace CKM { +const uid_t CKMLogic::SYSTEM_DB_UID = 0; + CKMLogic::CKMLogic() { CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR); m_accessControl.updateCCMode(); + + // make initial file list + std::vector filesToParse; + DIR *dp = opendir(INIT_VALUES_DIR); + if(dp) + { + struct dirent *entry; + while ((entry = readdir(dp))) + { + std::string filename = std::string(entry->d_name); + + // check if XML file + std::string lowercaseFilename = filename; + std::transform(lowercaseFilename.begin(), lowercaseFilename.end(), lowercaseFilename.begin(), ::tolower); + if(lowercaseFilename.find(INIT_VALUES_FILE_SUFFIX) == std::string::npos) + continue; + + filesToParse.push_back(std::string(INIT_VALUES_DIR) + filename); + } + closedir(dp); + } + + // parse + for(const auto & file : filesToParse) + { + InitialValues::InitialValuesFile xmlFile(file.c_str(), *this); + int rc = xmlFile.Validate(INIT_VALUES_XSD); + if(rc == XML::Parser::PARSE_SUCCESS) + { + rc = xmlFile.Parse(); + if(rc != XML::Parser::PARSE_SUCCESS) + LogError("invalid initial values file: " << file << ", parsing code: " << rc); + } + else + LogError("invalid initial values file: " << file << ", validation code: " << rc); + unlink(file.c_str()); + } } CKMLogic::~CKMLogic(){} @@ -83,30 +128,36 @@ void CKMLogic::saveDKEKFile(uid_t user, const Password &password) { fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password)); } -RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) { - int retCode = CKM_API_SUCCESS; +int CKMLogic::unlockDatabase(uid_t user, const Password & password) +{ + if (0 switch to system DB + if ( !m_accessControl.isSystemService(cred) ) + { + if (0 == m_userDataMap.count(cred.clientUid)) + ThrowMsg(Exception::DatabaseLocked, "database with UID: " << cred.clientUid << " locked"); + + if (0 != incoming_label.compare(LABEL_SYSTEM_DB)) + return m_userDataMap[cred.clientUid]; + } + + // system database selected, modify the label + if (CKM_API_SUCCESS != unlockSystemDB() ) + ThrowMsg(Exception::DatabaseLocked, "can not unlock system database"); + return m_userDataMap[SYSTEM_DB_UID]; +} + +RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) +{ + int retCode = CKM_API_SUCCESS; + + if( !m_accessControl.isSystemService(user) ) + { + retCode = unlockDatabase(user, password); + } + else + { + // do not allow lock/unlock operations for system users + retCode = CKM_API_ERROR_INPUT_PARAM; } return MessageBuffer::Serialize(retCode).Pop(); @@ -141,10 +232,18 @@ RawBuffer CKMLogic::updateCCMode() { return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop(); } -RawBuffer CKMLogic::lockUserKey(uid_t user) { +RawBuffer CKMLogic::lockUserKey(uid_t user) +{ int retCode = CKM_API_SUCCESS; - // TODO try catch for all errors that should be supported by error code - m_userDataMap.erase(user); + if( !m_accessControl.isSystemService(user) ) + { + m_userDataMap.erase(user); + } + else + { + // do not allow lock/unlock operations for system users + retCode = CKM_API_ERROR_INPUT_PARAM; + } return MessageBuffer::Serialize(retCode).Pop(); @@ -152,7 +251,10 @@ RawBuffer CKMLogic::lockUserKey(uid_t user) { RawBuffer CKMLogic::removeUserData(uid_t user) { int retCode = CKM_API_SUCCESS; - // TODO try catch for all errors that should be supported by error code + + if (m_accessControl.isSystemService(user)) + user = SYSTEM_DB_UID; + m_userDataMap.erase(user); FileSystem fs(user); @@ -161,15 +263,29 @@ RawBuffer CKMLogic::removeUserData(uid_t user) { return MessageBuffer::Serialize(retCode).Pop(); } +int CKMLogic::changeUserPasswordHelper(uid_t user, + const Password &oldPassword, + const Password &newPassword) +{ + // do not allow to change system database password + if( m_accessControl.isSystemService(user) ) + return CKM_API_ERROR_INPUT_PARAM; + + loadDKEKFile(user, oldPassword); + saveDKEKFile(user, newPassword); + + return CKM_API_SUCCESS; +} + RawBuffer CKMLogic::changeUserPassword( uid_t user, const Password &oldPassword, const Password &newPassword) { int retCode = CKM_API_SUCCESS; - try { - loadDKEKFile(user, oldPassword); - saveDKEKFile(user, newPassword); + try + { + retCode = changeUserPasswordHelper(user, oldPassword, newPassword); } catch (const KeyProvider::Exception::PassWordError &e) { LogError("Incorrect Password " << e.GetMessage()); retCode = CKM_API_ERROR_AUTHENTICATION_FAILED; @@ -187,22 +303,36 @@ RawBuffer CKMLogic::changeUserPassword( return MessageBuffer::Serialize(retCode).Pop(); } -RawBuffer CKMLogic::resetUserPassword( +int CKMLogic::resetUserPasswordHelper( uid_t user, const Password &newPassword) { + // do not allow to reset system database password + if( m_accessControl.isSystemService(user) ) + return CKM_API_ERROR_INPUT_PARAM; + int retCode = CKM_API_SUCCESS; + if (0 == m_userDataMap.count(user)) + { + // Check if key exists. If exists we must return error + FileSystem fs(user); + auto wrappedDKEKMain = fs.getDKEK(); + if (!wrappedDKEKMain.empty()) + retCode = CKM_API_ERROR_BAD_REQUEST; + } else { + saveDKEKFile(user, newPassword); + } + + return retCode; +} +RawBuffer CKMLogic::resetUserPassword( + uid_t user, + const Password &newPassword) +{ + int retCode = CKM_API_SUCCESS; try { - if (0 == m_userDataMap.count(user)) { - // Check if key exists. If exists we must return error - FileSystem fs(user); - auto wrappedDKEKMain = fs.getDKEK(); - if (!wrappedDKEKMain.empty()) - retCode = CKM_API_ERROR_BAD_REQUEST; - } else { - saveDKEKFile(user, newPassword); - } + retCode = resetUserPasswordHelper(user, newPassword); } catch (const FileSystem::Exception::Base &e) { LogError("Error in FileSystem " << e.GetMessage()); retCode = CKM_API_ERROR_FILE_SYSTEM; @@ -229,6 +359,7 @@ RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) { fs.addRemovedApp(smackLabel); } else { auto &handle = m_userDataMap[userId]; + handle.crypto.removeKey(smackLabel); handle.database.deleteKey(smackLabel); } } @@ -264,33 +395,33 @@ int CKMLogic::checkSaveConditions( } // check if allowed to save using ownerLabel - int access_ec = m_accessControl.canSave(ownerLabel, cred.smackLabel); - if(access_ec != CKM_API_SUCCESS) + int access_ec = m_accessControl.canSave(cred, ownerLabel); + if( access_ec != CKM_API_SUCCESS) { LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel); return access_ec; } // check if not a duplicate - if( handler.database.isNameLabelPresent(name, cred.smackLabel) ) + if( handler.database.isNameLabelPresent(name, ownerLabel)) return CKM_API_ERROR_DB_ALIAS_EXISTS; // encryption section - if (!handler.crypto.haveKey(cred.smackLabel)) { + if (!handler.crypto.haveKey(ownerLabel)) + { RawBuffer got_key; - auto key_optional = handler.database.getKey(cred.smackLabel); + auto key_optional = handler.database.getKey(ownerLabel); if(!key_optional) { - LogDebug("No Key in database found. Generating new one for label: " - << cred.smackLabel); - got_key = handler.keyProvider.generateDEK(cred.smackLabel); - handler.database.saveKey(cred.smackLabel, got_key); + LogDebug("No Key in database found. Generating new one for label: " << ownerLabel); + got_key = handler.keyProvider.generateDEK(ownerLabel); + handler.database.saveKey(ownerLabel, got_key); } else { LogDebug("Key from DB"); got_key = *key_optional; } got_key = handler.keyProvider.getPureDEK(got_key); - handler.crypto.pushKey(cred.smackLabel, got_key); + handler.crypto.pushKey(ownerLabel, got_key); } return CKM_API_SUCCESS; @@ -304,8 +435,8 @@ DB::Row CKMLogic::createEncryptedRow( const RawBuffer &data, const Policy &policy) const { - DB::Row row = { name, label, policy.extractable, dataType, DBCMAlgType::NONE, - 0, RawBuffer(), static_cast(data.size()), data, RawBuffer() }; + DB::Row row(name, label, static_cast(policy.extractable), dataType, data, static_cast(data.size())); + row.backendId = m_decider.chooseCryptoBackend(dataType, policy.extractable); // do not encrypt data with password during cc_mode on if(m_accessControl.isCCMode()) { @@ -316,7 +447,15 @@ DB::Row CKMLogic::createEncryptedRow( return row; } -int CKMLogic::verifyBinaryData(DataType dataType, const RawBuffer &input_data) const +int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const +{ + RawBuffer dummy; + return toBinaryData(dataType, input_data, dummy); +} + +int CKMLogic::toBinaryData(DataType dataType, + const RawBuffer &input_data, + RawBuffer &output_data) const { // verify the data integrity if (dataType.isKey()) @@ -327,6 +466,7 @@ int CKMLogic::verifyBinaryData(DataType dataType, const RawBuffer &input_data) c LogError("provided binary data is not valid key data"); return CKM_API_ERROR_INPUT_PARAM; } + output_data = output_key->getDER(); } else if (dataType.isCertificate() || dataType.isChainCert()) { @@ -336,53 +476,67 @@ int CKMLogic::verifyBinaryData(DataType dataType, const RawBuffer &input_data) c LogError("provided binary data is not valid certificate data"); return CKM_API_ERROR_INPUT_PARAM; } + output_data = cert->getDER(); } + else + output_data = input_data; // TODO: add here BINARY_DATA verification, i.e: max size etc. return CKM_API_SUCCESS; } -RawBuffer CKMLogic::saveData( +int CKMLogic::verifyAndSaveDataHelper( const Credentials &cred, - int commandId, const Name &name, const Label &label, const RawBuffer &data, DataType dataType, const PolicySerializable &policy) { - int retCode; - if (0 == m_userDataMap.count(cred.uid)) - retCode = CKM_API_ERROR_DB_LOCKED; - else - { - try { - // check if data is correct - retCode = verifyBinaryData(dataType, data); - if(retCode == CKM_API_SUCCESS) - { - retCode = saveDataHelper(cred, name, label, dataType, data, policy); - } - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const CryptoLogic::Exception::Base &e) { - LogError("CryptoLogic failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const DB::Crypto::Exception::InternalError &e) { - LogError("DB::Crypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (const DB::Crypto::Exception::TransactionError &e) { - LogError("DB::Crypto transaction failed with message " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (const FileSystem::Exception::Base &e) { - LogError("Error in FileSystem " << e.GetMessage()); - retCode = CKM_API_ERROR_FILE_SYSTEM; - } catch (const CKM::Exception &e) { - LogError("CKM::Exception: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; + int retCode = CKM_API_ERROR_UNKNOWN; + + try { + // check if data is correct + RawBuffer binaryData; + retCode = toBinaryData(dataType, data, binaryData); + if(retCode == CKM_API_SUCCESS) + { + retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy); } + } catch (const KeyProvider::Exception::Base &e) { + LogError("KeyProvider failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const CryptoLogic::Exception::Base &e) { + LogError("CryptoLogic failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const DB::Crypto::Exception::InternalError &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const DB::Crypto::Exception::TransactionError &e) { + LogError("DB::Crypto transaction failed with message " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const FileSystem::Exception::Base &e) { + LogError("Error in FileSystem " << e.GetMessage()); + retCode = CKM_API_ERROR_FILE_SYSTEM; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; } + return retCode; +} +RawBuffer CKMLogic::saveData( + const Credentials &cred, + int commandId, + const Name &name, + const Label &label, + const RawBuffer &data, + DataType dataType, + const PolicySerializable &policy) +{ + int retCode = verifyAndSaveDataHelper(cred, name, label, data, dataType, policy); auto response = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE), commandId, retCode, @@ -444,29 +598,24 @@ RawBuffer CKMLogic::savePKCS12( const PolicySerializable &keyPolicy, const PolicySerializable &certPolicy) { - int retCode; - if (0 == m_userDataMap.count(cred.uid)) - retCode = CKM_API_ERROR_DB_LOCKED; - else - { - try { - retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy); - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const CryptoLogic::Exception::Base &e) { - LogError("CryptoLogic failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const DB::Crypto::Exception::InternalError &e) { - LogError("DB::Crypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (const DB::Crypto::Exception::TransactionError &e) { - LogError("DB::Crypto transaction failed with message " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (const CKM::Exception &e) { - LogError("CKM::Exception: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } + int retCode = CKM_API_ERROR_UNKNOWN; + try { + retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy); + } catch (const KeyProvider::Exception::Base &e) { + LogError("KeyProvider failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const CryptoLogic::Exception::Base &e) { + LogError("CryptoLogic failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const DB::Crypto::Exception::InternalError &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const DB::Crypto::Exception::TransactionError &e) { + LogError("DB::Crypto transaction failed with message " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; } auto response = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE_PKCS12), @@ -479,30 +628,31 @@ RawBuffer CKMLogic::savePKCS12( int CKMLogic::removeDataHelper( const Credentials &cred, const Name &name, - const Label &ownerLabel) + const Label &label) { - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; + auto &handler = selectDatabase(cred, label); + // use client label if not explicitly provided + const Label &ownerLabel = label.empty() ? cred.smackLabel : label; if (!isNameValid(name) || !isLabelValid(ownerLabel)) { LogError("Invalid label or name format"); return CKM_API_ERROR_INPUT_PARAM; } - auto &database = m_userDataMap[cred.uid].database; - DB::Crypto::Transaction transaction(&database); + DB::Crypto::Transaction transaction(&handler.database); // read and check permissions PermissionMaskOptional permissionRowOpt = - database.getPermissionRow(name, ownerLabel, cred.smackLabel); - int access_ec = m_accessControl.canDelete(PermissionForLabel(cred.smackLabel, permissionRowOpt)); - if(access_ec != CKM_API_SUCCESS) + handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel); + int retCode = m_accessControl.canDelete(cred, + PermissionForLabel(cred.smackLabel, permissionRowOpt)); + if(retCode != CKM_API_SUCCESS) { - LogWarning("access control check result: " << access_ec); - return access_ec; + LogWarning("access control check result: " << retCode); + return retCode; } - auto erased = database.deleteRow(name, ownerLabel); + auto erased = handler.database.deleteRow(name, ownerLabel); // check if the data existed or not if(erased) transaction.commit(); @@ -520,13 +670,19 @@ RawBuffer CKMLogic::removeData( const Name &name, const Label &label) { - int retCode; - Try { - // use client label if not explicitly provided - const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + int retCode = CKM_API_ERROR_UNKNOWN; - retCode = removeDataHelper(cred, name, ownerLabel); - } Catch (CKM::Exception) { + try + { + retCode = removeDataHelper(cred, name, label); + } + catch (const CKMLogic::Exception::DatabaseLocked &e) + { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; + } + catch (const CKM::Exception &) + { LogError("Error in deleting row!"); retCode = CKM_API_ERROR_DB_ERROR; } @@ -588,18 +744,18 @@ int CKMLogic::readMultiRow(const Name &name, { // read all key types database.getRows(name, - ownerLabel, - DataType::DB_CHAIN_FIRST, - DataType::DB_CHAIN_LAST, - output); + ownerLabel, + DataType::DB_CHAIN_FIRST, + DataType::DB_CHAIN_LAST, + output); } else { // read anything else database.getRows(name, - ownerLabel, - dataType, - output); + ownerLabel, + dataType, + output); } if(!output.size()) { @@ -610,7 +766,8 @@ int CKMLogic::readMultiRow(const Name &name, return CKM_API_SUCCESS; } -int CKMLogic::checkDataPermissionsHelper(const Name &name, +int CKMLogic::checkDataPermissionsHelper(const Credentials &cred, + const Name &name, const Label &ownerLabel, const Label &accessorLabel, const DB::Row &row, @@ -621,8 +778,8 @@ int CKMLogic::checkDataPermissionsHelper(const Name &name, database.getPermissionRow(name, ownerLabel, accessorLabel); if(exportFlag) - return m_accessControl.canExport(row, PermissionForLabel(accessorLabel, permissionRowOpt)); - return m_accessControl.canRead(PermissionForLabel(accessorLabel, permissionRowOpt)); + return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt)); + return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt)); } int CKMLogic::readDataHelper( @@ -634,8 +791,7 @@ int CKMLogic::readDataHelper( const Password &password, DB::RowVector &rows) { - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; + auto &handler = selectDatabase(cred, label); // use client label if not explicitly provided const Label &ownerLabel = label.empty() ? cred.smackLabel : label; @@ -643,21 +799,19 @@ int CKMLogic::readDataHelper( if (!isNameValid(name) || !isLabelValid(ownerLabel)) return CKM_API_ERROR_INPUT_PARAM; - auto &handler = m_userDataMap[cred.uid]; - // read rows DB::Crypto::Transaction transaction(&handler.database); - int ec = readMultiRow(name, ownerLabel, dataType, handler.database, rows); - if(CKM_API_SUCCESS != ec) - return ec; + int retCode = readMultiRow(name, ownerLabel, dataType, handler.database, rows); + if(CKM_API_SUCCESS != retCode) + return retCode; // all read rows belong to the same owner DB::Row & firstRow = rows.at(0); // check access rights - ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database); - if(CKM_API_SUCCESS != ec) - return ec; + retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database); + if(CKM_API_SUCCESS != retCode) + return retCode; // decrypt row if (!handler.crypto.haveKey(firstRow.ownerLabel)) { @@ -686,8 +840,7 @@ int CKMLogic::readDataHelper( const Password &password, DB::Row &row) { - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; + auto &handler = selectDatabase(cred, label); // use client label if not explicitly provided const Label &ownerLabel = label.empty() ? cred.smackLabel : label; @@ -695,19 +848,16 @@ int CKMLogic::readDataHelper( if (!isNameValid(name) || !isLabelValid(ownerLabel)) return CKM_API_ERROR_INPUT_PARAM; - auto &handler = m_userDataMap[cred.uid]; - // read row DB::Crypto::Transaction transaction(&handler.database); - int ec = readSingleRow(name, ownerLabel, dataType, handler.database, row); - if(CKM_API_SUCCESS != ec) - return ec; - + int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row); + if(CKM_API_SUCCESS != retCode) + return retCode; // check access rights - ec = checkDataPermissionsHelper(name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database); - if(CKM_API_SUCCESS != ec) - return ec; + retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database); + if(CKM_API_SUCCESS != retCode) + return retCode; // decrypt row if (!handler.crypto.haveKey(row.ownerLabel)) { @@ -751,6 +901,9 @@ RawBuffer CKMLogic::getData( } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; } catch (const CKM::Exception &e) { LogError("CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; @@ -819,9 +972,9 @@ RawBuffer CKMLogic::getPKCS12( const Password &keyPassword, const Password &certPassword) { - int retCode; - PKCS12Serializable output; + int retCode = CKM_API_ERROR_UNKNOWN; + PKCS12Serializable output; try { KeyShPtr privKey; CertificateShPtr cert; @@ -844,6 +997,9 @@ RawBuffer CKMLogic::getPKCS12( } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; } catch (const CKM::Exception &e) { LogError("CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; @@ -856,39 +1012,84 @@ RawBuffer CKMLogic::getPKCS12( return response.Pop(); } -RawBuffer CKMLogic::getDataList( - const Credentials &cred, - int commandId, - DataType dataType) +int CKMLogic::getDataListHelper(const Credentials &cred, + const DataType dataType, + LabelNameVector &labelNameVector) { - int retCode = CKM_API_SUCCESS; - LabelNameVector labelNameVector; - - if (0 < m_userDataMap.count(cred.uid)) { - auto &database = m_userDataMap[cred.uid].database; + int retCode = CKM_API_ERROR_DB_LOCKED; + if (0 < m_userDataMap.count(cred.clientUid)) + { + auto &database = m_userDataMap[cred.clientUid].database; Try { + LabelNameVector tmpVector; if (dataType.isKey()) { // list all key types database.listNames(cred.smackLabel, - labelNameVector, + tmpVector, DataType::DB_KEY_FIRST, DataType::DB_KEY_LAST); } else { // list anything else database.listNames(cred.smackLabel, - labelNameVector, + tmpVector, dataType); } + labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end()); + retCode = CKM_API_SUCCESS; } Catch (CKM::Exception) { LogError("Failed to get names"); retCode = CKM_API_ERROR_DB_ERROR; } - } else { - retCode = CKM_API_ERROR_DB_LOCKED; } + return retCode; +} +RawBuffer CKMLogic::getDataList( + const Credentials &cred, + int commandId, + DataType dataType) +{ + LabelNameVector systemVector; + LabelNameVector userVector; + LabelNameVector labelNameVector; + + int retCode = unlockSystemDB(); + if (CKM_API_SUCCESS == retCode) + { + // system database + if (m_accessControl.isSystemService(cred)) + { + // lookup system DB + retCode = getDataListHelper(Credentials(SYSTEM_DB_UID, + LABEL_SYSTEM_DB), + dataType, + systemVector); + } + else + { + // user - lookup system, then client DB + retCode = getDataListHelper(Credentials(SYSTEM_DB_UID, + cred.smackLabel), + dataType, + systemVector); + + // private database + if(retCode == CKM_API_SUCCESS) + { + retCode = getDataListHelper(cred, + dataType, + userVector); + } + } + } + + if(retCode == CKM_API_SUCCESS) + { + labelNameVector.insert(labelNameVector.end(), systemVector.begin(), systemVector.end()); + labelNameVector.insert(labelNameVector.end(), userVector.begin(), userVector.end()); + } auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET_LIST), commandId, retCode, @@ -905,10 +1106,12 @@ int CKMLogic::saveDataHelper( const RawBuffer &data, const PolicySerializable &policy) { - auto &handler = m_userDataMap[cred.uid]; + auto &handler = selectDatabase(cred, label); // use client label if not explicitly provided const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0) + return CKM_API_ERROR_INPUT_PARAM; // check if save is possible DB::Crypto::Transaction transaction(&handler.database); @@ -932,10 +1135,12 @@ int CKMLogic::saveDataHelper( const PolicySerializable &keyPolicy, const PolicySerializable &certPolicy) { - auto &handler = m_userDataMap[cred.uid]; + auto &handler = selectDatabase(cred, label); // use client label if not explicitly provided const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0) + return CKM_API_ERROR_INPUT_PARAM; // check if save is possible DB::Crypto::Transaction transaction(&handler.database); @@ -968,46 +1173,48 @@ int CKMLogic::createKeyPairHelper( const PolicySerializable &policyPrivate, const PolicySerializable &policyPublic) { - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; - - KeyImpl prv, pub; - int retCode; + CryptoAlgorithm keyGenAlgorithm; switch(key_type) { case KeyType::KEY_RSA_PUBLIC: case KeyType::KEY_RSA_PRIVATE: - retCode = Crypto::SW::CryptoService::createKeyPairRSA(additional_param, prv, pub); + keyGenAlgorithm.addParam(ParamName::ALGO_TYPE, AlgoType::RSA_GEN); + keyGenAlgorithm.addParam(ParamName::GEN_KEY_LEN, additional_param); break; case KeyType::KEY_DSA_PUBLIC: case KeyType::KEY_DSA_PRIVATE: - retCode = Crypto::SW::CryptoService::createKeyPairDSA(additional_param, prv, pub); + keyGenAlgorithm.addParam(ParamName::ALGO_TYPE, AlgoType::DSA_GEN); + keyGenAlgorithm.addParam(ParamName::GEN_KEY_LEN, additional_param); break; case KeyType::KEY_ECDSA_PUBLIC: case KeyType::KEY_ECDSA_PRIVATE: - retCode = Crypto::SW::CryptoService::createKeyPairECDSA(static_cast(additional_param), prv, pub); + keyGenAlgorithm.addParam(ParamName::ALGO_TYPE, AlgoType::ECDSA_GEN); + keyGenAlgorithm.addParam(ParamName::GEN_EC, additional_param); break; default: + LogError("Invalid key_type for asymetric key generation: " << (int)key_type); return CKM_API_ERROR_INPUT_PARAM; } - if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode) - { - LogDebug("CryptoService error with code: " << retCode); - return CKM_API_ERROR_SERVER_ERROR; // TODO error code - } + auto &handlerPriv = selectDatabase(cred, labelPrivate); + auto &handlerPub = selectDatabase(cred, labelPublic); - auto &database = m_userDataMap[cred.uid].database; - DB::Crypto::Transaction transaction(&database); + bool exportable = policyPrivate.extractable || policyPublic.extractable; + TokenPair keys = m_decider.getStore(DataType(key_type), exportable).generateAKey(keyGenAlgorithm); - retCode = saveDataHelper(cred, + DB::Crypto::Transaction transactionPriv(&handlerPriv.database); + // in case the same database is used for private and public - the second + // transaction will not be executed + DB::Crypto::Transaction transactionPub(&handlerPub.database); + + int retCode = saveDataHelper(cred, namePrivate, labelPrivate, - DataType(prv.getType()), - prv.getDER(), + keys.first.dataType, + keys.first.data, policyPrivate); if (CKM_API_SUCCESS != retCode) return retCode; @@ -1015,15 +1222,15 @@ int CKMLogic::createKeyPairHelper( retCode = saveDataHelper(cred, namePublic, labelPublic, - DataType(pub.getType()), - pub.getDER(), + keys.second.dataType, + keys.second.data, policyPublic); if (CKM_API_SUCCESS != retCode) return retCode; - transaction.commit(); - - return retCode; + transactionPub.commit(); + transactionPriv.commit(); + return CKM_API_SUCCESS; } RawBuffer CKMLogic::createKeyPair( @@ -1067,6 +1274,15 @@ RawBuffer CKMLogic::createKeyPair( labelPublic, policyPrivate, policyPublic); + } catch (const Crypto::Exception::OperationNotSupported &e) { + LogDebug("GStore error: operation not supported: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (const Crypto::Exception::InternalError & e) { + LogDebug("GStore key generation failed: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch( const Crypto::Exception::InputParam & e) { + LogDebug("Missing or wrong input parameters: " << e.GetMessage()); + retCode = CKM_API_ERROR_INPUT_PARAM; } catch (DB::Crypto::Exception::TransactionError &e) { LogDebug("DB::Crypto error: transaction error: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; @@ -1076,6 +1292,9 @@ RawBuffer CKMLogic::createKeyPair( } catch (DB::Crypto::Exception::InternalError &e) { LogDebug("DB::Crypto internal error: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; } catch (const CKM::Exception &e) { LogError("CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; @@ -1244,6 +1463,9 @@ RawBuffer CKMLogic::getCertificateChain( } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; } catch (const std::exception& e) { LogError("STD exception " << e.what()); retCode = CKM_API_ERROR_SERVER_ERROR; @@ -1269,20 +1491,17 @@ RawBuffer CKMLogic::createSignature( const RSAPaddingAlgorithm padding) { DB::Row row; - Crypto::SW::CryptoService cs; RawBuffer signature; + CryptoAlgorithm cryptoAlg; + cryptoAlg.addParam(ParamName::SV_HASH_ALGO, hash); + cryptoAlg.addParam(ParamName::SV_RSA_PADDING, padding); int retCode = CKM_API_SUCCESS; try { retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row); - if(retCode == CKM_API_SUCCESS) - { - KeyImpl keyParsed(row.data, Password()); - if (keyParsed.empty()) - retCode = CKM_API_ERROR_SERVER_ERROR; - else - retCode = cs.createSignature(keyParsed, message, hash, padding, signature); + if(retCode == CKM_API_SUCCESS) { + signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message); } } catch (const KeyProvider::Exception::Base &e) { LogError("KeyProvider failed with message: " << e.GetMessage()); @@ -1296,6 +1515,15 @@ RawBuffer CKMLogic::createSignature( } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; + } catch (const CKM::Crypto::Exception::InputParam &e) { + LogError("CKM::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_INPUT_PARAM; + } catch (const CKM::Crypto::Exception::Base &e) { + LogError("CKM::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const CKM::Exception &e) { LogError("Unknown CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; @@ -1322,39 +1550,25 @@ RawBuffer CKMLogic::verifySignature( int retCode = CKM_API_ERROR_VERIFICATION_FAILED; try { - do { - Crypto::SW::CryptoService cs; - DB::Row row; - KeyImpl key; - - // try certificate first - looking for a public key. - // in case of PKCS, pub key from certificate will be found first - // rather than private key from the same PKCS. - retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row); - if (retCode == CKM_API_SUCCESS) { - CertificateImpl cert(row.data, DataFormat::FORM_DER); - key = cert.getKeyImpl(); - } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) { - retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row); - if (retCode != CKM_API_SUCCESS) - break; - key = KeyImpl(row.data); - } else { - break; - } - - if (key.empty()) { - retCode = CKM_API_ERROR_SERVER_ERROR; - break; - } + DB::Row row; + + CryptoAlgorithm params; + params.addParam(ParamName::SV_HASH_ALGO, hash); + params.addParam(ParamName::SV_RSA_PADDING, padding); + + // try certificate first - looking for a public key. + // in case of PKCS, pub key from certificate will be found first + // rather than private key from the same PKCS. + retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row); + if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) { + retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row); + } - retCode = cs.verifySignature(key, message, signature, hash, padding); - } while(0); - } catch (const Crypto::SW::CryptoService::Exception::Crypto_internal &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const Crypto::SW::CryptoService::Exception::opensslError &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); + if (retCode == CKM_API_SUCCESS) { + retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature); + } + } catch (const Crypto::Exception::Base &e) { + LogError("GStore failed with error: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; } catch (const KeyProvider::Exception::Base &e) { LogError("KeyProvider failed with error: " << e.GetMessage()); @@ -1368,6 +1582,9 @@ RawBuffer CKMLogic::verifySignature( } catch (const DB::Crypto::Exception::Base &e) { LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; } catch (const CKM::Exception &e) { LogError("Unknown CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; @@ -1386,6 +1603,8 @@ int CKMLogic::setPermissionHelper( const Label &accessorLabel, // who will get the access const PermissionMask permissionMask) { + auto &handler = selectDatabase(cred, label); + // we don't know the client if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel)) return CKM_API_ERROR_INPUT_PARAM; @@ -1401,29 +1620,30 @@ int CKMLogic::setPermissionHelper( if (ownerLabel==accessorLabel) return CKM_API_ERROR_INPUT_PARAM; - // can the client modify permissions to owner's row? - int access_ec = m_accessControl.canModify(ownerLabel, cred.smackLabel); - if(access_ec != CKM_API_SUCCESS) - return access_ec; + // system database does not support write/remove permissions + if ((0 == ownerLabel.compare(LABEL_SYSTEM_DB)) && + (permissionMask & Permission::REMOVE)) + return CKM_API_ERROR_INPUT_PARAM; - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; + // can the client modify permissions to owner's row? + int retCode = m_accessControl.canModify(cred, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; - auto &database = m_userDataMap[cred.uid].database; - DB::Crypto::Transaction transaction(&database); + DB::Crypto::Transaction transaction(&handler.database); - if( !database.isNameLabelPresent(name, ownerLabel) ) + if( !handler.database.isNameLabelPresent(name, ownerLabel) ) return CKM_API_ERROR_DB_ALIAS_UNKNOWN; // removing non-existing permissions: fail if(permissionMask == Permission::NONE) { - if(!database.getPermissionRow(name, ownerLabel, accessorLabel)) + if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel)) return CKM_API_ERROR_INPUT_PARAM; } // set permissions to the row owned by ownerLabel for accessorLabel - database.setPermission(name, ownerLabel, accessorLabel, permissionMask); + handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask); transaction.commit(); return CKM_API_SUCCESS; @@ -1441,6 +1661,9 @@ RawBuffer CKMLogic::setPermission( int retCode; Try { retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask); + } catch (const CKMLogic::Exception::DatabaseLocked &e) { + LogError("Error " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_LOCKED; } Catch (CKM::Exception) { LogError("Error in set row!"); retCode = CKM_API_ERROR_DB_ERROR;