X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fmanager%2Fservice%2Fckm-logic.cpp;h=8736fd50bfc27fcdb6d0fae0b534c3c52db06909;hb=51a5e9cfe81d0374a02c1e28375a482b68afd879;hp=29a70623f2500b19fed76c136540a2003d90c257;hpb=4cf6e9564b53b247625b561a143a26b465be1db9;p=platform%2Fcore%2Fsecurity%2Fkey-manager.git diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 29a7062..8736fd5 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -25,130 +25,247 @@ #include #include #include -#include #include #include +#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) + if (label.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Label::npos) + return false; + return true; +} + +bool isNameValid(const CKM::Name &name) { + if (name.find(CKM::LABEL_NAME_SEPARATOR) != CKM::Name::npos) + return false; + return true; +} } // anonymous namespace namespace CKM { +const uid_t CKMLogic::SYSTEM_DB_UID = 0; + CKMLogic::CKMLogic() { - int retCode = FileSystem::init(); - // TODO what can I do when init went wrong? exit(-1) ?? - if (retCode) { - LogError("Fatal error in FileSystem::init()"); - } + CertificateConfig::addSystemCertificateDir(CERT_SYSTEM_DIR); + + m_accessControl.updateCCMode(); - if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) { - LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work"); + // 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); } - cc_mode_status = CCModeState::CC_MODE_OFF; + // 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(){} -RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) { - // TODO try catch for all errors that should be supported by error code - int retCode = CKM_API_SUCCESS; +void CKMLogic::loadDKEKFile(uid_t user, const Password &password) { + auto &handle = m_userDataMap[user]; - try { - if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) { - auto &handle = m_userDataMap[user]; - FileSystem fs(user); - auto wrappedDomainKEK = fs.getDKEK(); - - if (wrappedDomainKEK.empty()) { - wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password); - fs.saveDKEK(wrappedDomainKEK); - } + FileSystem fs(user); + + auto wrappedDKEK = fs.getDKEK(); - handle.keyProvider = KeyProvider(wrappedDomainKEK, password); + if (wrappedDKEK.empty()) { + wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password); + fs.saveDKEK(wrappedDKEK); + } + + handle.keyProvider = KeyProvider(wrappedDKEK, password); +} - auto wrappedDatabaseDEK = fs.getDBDEK(); +void CKMLogic::saveDKEKFile(uid_t user, const Password &password) { + auto &handle = m_userDataMap[user]; - if (wrappedDatabaseDEK.empty()) { - wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user)); - fs.saveDBDEK(wrappedDatabaseDEK); - } + FileSystem fs(user); + fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password)); +} + +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)) + ThrowErr(Exc::DatabaseLocked, "database with UID: ", cred.clientUid, " locked"); + + if (0 != incoming_label.compare(OWNER_ID_SYSTEM)) + return m_userDataMap[cred.clientUid]; + } + + // system database selected, modify the label + if (CKM_API_SUCCESS != unlockSystemDB() ) + ThrowErr(Exc::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((mode_status != CCModeState:: CC_MODE_OFF) && (mode_status != CCModeState:: CC_MODE_ON)) { + 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; } - cc_mode_status = mode_status; + return MessageBuffer::Serialize(retCode).Pop(); +} - MessageBuffer response; - Serialization::Serialize(response, retCode); - return response.Pop(); +RawBuffer CKMLogic::updateCCMode() { + m_accessControl.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(); - MessageBuffer response; - Serialization::Serialize(response, retCode); - return response.Pop(); } 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); fs.removeUserData(); - MessageBuffer response; - Serialization::Serialize(response, retCode); - return response.Pop(); + 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( @@ -157,51 +274,60 @@ RawBuffer CKMLogic::changeUserPassword( const Password &newPassword) { int retCode = CKM_API_SUCCESS; - try { - FileSystem fs(user); - auto wrappedDomainKEK = fs.getDKEK(); - if (wrappedDomainKEK.empty()) { - retCode = CKM_API_ERROR_BAD_REQUEST; - } else { - wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword); - fs.saveDKEK(wrappedDomainKEK); - } - } catch (const KeyProvider::Exception::PassWordError &e) { - LogError("Incorrect Password " << e.GetMessage()); - retCode = CKM_API_ERROR_AUTHENTICATION_FAILED; - } catch (const KeyProvider::Exception::Base &e) { - LogError("Error in KeyProvider " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; + try + { + retCode = changeUserPasswordHelper(user, oldPassword, newPassword); + } catch (const Exc::Exception &e) { + retCode = e.error(); } catch (const CKM::Exception &e) { LogError("CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; } - MessageBuffer response; - Serialization::Serialize(response, retCode); - return response.Pop(); + 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; - // TODO try-catch - if (0 == m_userDataMap.count(user)) { - retCode = CKM_API_ERROR_BAD_REQUEST; - } else { - auto &handler = m_userDataMap[user]; + if (0 == m_userDataMap.count(user)) + { + // Check if key exists. If exists we must return error FileSystem fs(user); - fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword)); + auto wrappedDKEKMain = fs.getDKEK(); + if (!wrappedDKEKMain.empty()) + retCode = CKM_API_ERROR_BAD_REQUEST; + } else { + saveDKEKFile(user, newPassword); } - MessageBuffer response; - Serialization::Serialize(response, retCode); - return response.Pop(); + return retCode; +} + +RawBuffer CKMLogic::resetUserPassword( + uid_t user, + const Password &newPassword) +{ + int retCode = CKM_API_SUCCESS; + try { + retCode = resetUserPasswordHelper(user, newPassword); + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } + + return MessageBuffer::Serialize(retCode).Pop(); } -RawBuffer CKMLogic::removeApplicationData(const std::string &smackLabel) { +RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) { int retCode = CKM_API_SUCCESS; try { @@ -216,549 +342,1264 @@ RawBuffer CKMLogic::removeApplicationData(const std::string &smackLabel) { fs.addRemovedApp(smackLabel); } else { auto &handle = m_userDataMap[userId]; + handle.crypto.removeKey(smackLabel); handle.database.deleteKey(smackLabel); } } } - } catch (const DBCrypto::Exception::InternalError &e) { - LogError("DBCrypto couldn't remove data: " << e.GetMessage()); + } catch (const DB::Crypto::Exception::InternalError &e) { + LogError("DB::Crypto couldn't remove data: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; - } catch (const DBCrypto::Exception::TransactionError &e) { - LogError("DBCrypto transaction failed with message " << e.GetMessage()); + } catch (const DB::Crypto::Exception::TransactionError &e) { + LogError("DB::Crypto transaction failed with message " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; } - MessageBuffer response; - Serialization::Serialize(response, retCode); - return response.Pop(); + return MessageBuffer::Serialize(retCode).Pop(); } -int CKMLogic::saveDataHelper( - Credentials &cred, - DBDataType dataType, - const Alias &alias, - const RawBuffer &key, - const PolicySerializable &policy) +int CKMLogic::checkSaveConditions( + const Credentials &cred, + UserData &handler, + const Name &name, + const Label &ownerLabel) { - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; + // verify name and label are correct + if (!isNameValid(name) || !isLabelValid(ownerLabel)) { + LogDebug("Invalid parameter passed to key-manager"); + return CKM_API_ERROR_INPUT_PARAM; + } - DBRow row = { alias, cred.smackLabel, - policy.extractable, dataType, DBCMAlgType::NONE, - 0, RawBuffer(), static_cast(key.size()), key, RawBuffer() }; + // check if allowed to save using ownerLabel + int access_ec = m_accessControl.canSave(cred, ownerLabel); + if( access_ec != CKM_API_SUCCESS) + { + LogDebug("label " << cred.smackLabel << " can not save rows using label " << ownerLabel); + return access_ec; + } - auto &handler = m_userDataMap[cred.uid]; - DBCrypto::Transaction transaction(&handler.database); - if (!handler.crypto.haveKey(cred.smackLabel)) { - RawBuffer key; - auto key_optional = handler.database.getKey(cred.smackLabel); + // check if not a duplicate + if( handler.database.isNameLabelPresent(name, ownerLabel)) + return CKM_API_ERROR_DB_ALIAS_EXISTS; + + // encryption section + if (!handler.crypto.haveKey(ownerLabel)) + { + RawBuffer got_key; + auto key_optional = handler.database.getKey(ownerLabel); if(!key_optional) { - LogDebug("No Key in database found. Generating new one for label: " - << cred.smackLabel); - key = handler.keyProvider.generateDEK(cred.smackLabel); - handler.database.saveKey(cred.smackLabel, 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"); - key = *key_optional; + got_key = *key_optional; } - key = handler.keyProvider.getPureDEK(key); - handler.crypto.pushKey(cred.smackLabel, key); - } - - // Do not encrypt data with password during cc_mode on - if(cc_mode_status == CCModeState::CC_MODE_ON) { - handler.crypto.encryptRow("", row); - } else { - handler.crypto.encryptRow(policy.password, row); + got_key = handler.keyProvider.getPureDEK(got_key); + handler.crypto.pushKey(ownerLabel, got_key); } - handler.database.saveDBRow(row); - transaction.commit(); return CKM_API_SUCCESS; } -RawBuffer CKMLogic::saveData( - Credentials &cred, - int commandId, - DBDataType dataType, - const Alias &alias, - const RawBuffer &key, - const PolicySerializable &policy) +DB::Row CKMLogic::createEncryptedRow( + CryptoLogic &crypto, + const Name &name, + const Label &label, + DataType dataType, + const RawBuffer &data, + const Policy &policy) const { - int retCode = CKM_API_SUCCESS; - try { - retCode = saveDataHelper(cred, dataType, alias, key, policy); - LogDebug("SaveDataHelper returned: " << retCode); - } 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 DBCrypto::Exception::InternalError &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (const DBCrypto::Exception::AliasExists &e) { - LogError("DBCrypto couldn't save duplicate alias"); - retCode = CKM_API_ERROR_DB_ALIAS_EXISTS; - } catch (const DBCrypto::Exception::TransactionError &e) { - LogError("DBCrypto transaction failed with message " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } + Crypto::GStore& store = m_decider.getStore(dataType, policy.extractable); - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::SAVE)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, static_cast(dataType)); - - return response.Pop(); + // do not encrypt data with password during cc_mode on + Token token = store.import(dataType, data, m_accessControl.isCCMode() ? "" : policy.password); + DB::Row row(std::move(token), name, label, static_cast(policy.extractable)); + crypto.encryptRow(row); + return row; } -RawBuffer CKMLogic::removeData( - Credentials &cred, - int commandId, - DBDataType dataType, - const Alias &alias) +int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const { - int retCode = CKM_API_SUCCESS; - - if (0 < m_userDataMap.count(cred.uid)) { - Try { - auto erased = m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel); - // check if the data existed or not - if(!erased) { - LogError("No row for given alias and label"); - retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN; - } - } Catch (DBCrypto::Exception::PermissionDenied) { - LogError("Error: not enough permissions!"); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } Catch (CKM::Exception) { - LogError("Error in deleting row!"); - retCode = CKM_API_ERROR_DB_ERROR; - } - } else { - retCode = CKM_API_ERROR_DB_LOCKED; - } - - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::REMOVE)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, static_cast(dataType)); - - return response.Pop(); + RawBuffer dummy; + return toBinaryData(dataType, input_data, dummy); } -int CKMLogic::getDataHelper( - Credentials &cred, - DBDataType dataType, - const Alias &alias, - const Password &password, - DBRow &row) +int CKMLogic::toBinaryData(DataType dataType, + const RawBuffer &input_data, + RawBuffer &output_data) const { - if (0 == m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; - - auto &handler = m_userDataMap[cred.uid]; - - DBCrypto::DBRowOptional row_optional; - if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) { - row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType); - } else if ((static_cast(dataType) >= static_cast(DBDataType::DB_KEY_FIRST)) - && (static_cast(dataType) <= static_cast(DBDataType::DB_KEY_LAST))) + // verify the data integrity + if (dataType.isKey()) { - row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel); - } else { - LogError("Unknown type of requested data" << (int)dataType); - return CKM_API_ERROR_BAD_REQUEST; - } - if(!row_optional) { - LogError("No row for given alias, label and type"); - return CKM_API_ERROR_DB_ALIAS_UNKNOWN; - } else { - row = *row_optional; + KeyShPtr output_key; + if(dataType.isSKey()) + output_key = CKM::Key::createAES(input_data); + else + output_key = CKM::Key::create(input_data); + if(output_key.get() == NULL) + { + LogDebug("provided binary data is not valid key data"); + return CKM_API_ERROR_INPUT_PARAM; + } + output_data = output_key->getDER(); } - - if (!handler.crypto.haveKey(row.smackLabel)) { - RawBuffer key; - auto key_optional = handler.database.getKey(row.smackLabel); - if(!key_optional) { - LogError("No key for given label in database"); - return CKM_API_ERROR_DB_ERROR; + else if (dataType.isCertificate() || dataType.isChainCert()) + { + CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER); + if(cert.get() == NULL) + { + LogDebug("provided binary data is not valid certificate data"); + return CKM_API_ERROR_INPUT_PARAM; } - key = *key_optional; - key = handler.keyProvider.getPureDEK(key); - handler.crypto.pushKey(cred.smackLabel, key); + output_data = cert->getDER(); } - handler.crypto.decryptRow(password, row); - + else + output_data = input_data; + // TODO: add here BINARY_DATA verification, i.e: max size etc. return CKM_API_SUCCESS; } -RawBuffer CKMLogic::getData( - Credentials &cred, - int commandId, - DBDataType dataType, - const Alias &alias, - const Password &password) +int CKMLogic::verifyAndSaveDataHelper( + const Credentials &cred, + const Name &name, + const Label &label, + const RawBuffer &data, + DataType dataType, + const PolicySerializable &policy) { - int retCode = CKM_API_SUCCESS; - DBRow row; + int retCode = CKM_API_ERROR_UNKNOWN; try { - retCode = getDataHelper(cred, dataType, alias, password, row); - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with error: " << 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 DBCrypto::Exception::PermissionDenied &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } catch (const DBCrypto::Exception::Base &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); + // 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 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 Exc::Exception &e) { + retCode = e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; } + return retCode; +} - if (CKM_API_SUCCESS != retCode) { - row.data.clear(); - row.dataType = dataType; +int CKMLogic::getKeyForService( + const Credentials &cred, + const Name &name, + const Label &label, + const Password &pass, + Crypto::GObjShPtr &key) +{ + DB::Row row; + try { + // Key is for internal service use. It won't be exported to the client + Crypto::GObjUPtr obj; + int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, name, label, pass, obj); + if (retCode == CKM_API_SUCCESS) + key = std::move(obj); + return retCode; + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + return CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + return e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + return CKM_API_ERROR_SERVER_ERROR; } +} - if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) { - row.data.clear(); - retCode = CKM_API_ERROR_NOT_EXPORTABLE; - } +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, + static_cast(dataType)); + return response.Pop(); +} - // Prevent extracting private keys during cc-mode on - if((cc_mode_status == CCModeState::CC_MODE_ON) && (row.dataType == DBDataType::KEY_RSA_PRIVATE || row.dataType == DBDataType::KEY_ECDSA_PRIVATE || row.dataType == DBDataType::KEY_DSA_PRIVATE)) { - row.data.clear(); - retCode = CKM_API_ERROR_BAD_REQUEST; +int CKMLogic::extractPKCS12Data( + CryptoLogic &crypto, + const Name &name, + const Label &ownerLabel, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy, + DB::RowVector &output) const +{ + // private key is mandatory + if( !pkcs.getKey() ) + return CKM_API_ERROR_INVALID_FORMAT; + Key* keyPtr = pkcs.getKey().get(); + DataType keyType = DataType(keyPtr->getType()); + RawBuffer keyData = keyPtr->getDER(); + int retCode = verifyBinaryData(keyType, keyData); + if(retCode != CKM_API_SUCCESS) + return retCode; + output.push_back(createEncryptedRow(crypto, name, ownerLabel, keyType, keyData, keyPolicy)); + + // certificate is mandatory + if( !pkcs.getCertificate() ) + return CKM_API_ERROR_INVALID_FORMAT; + RawBuffer certData = pkcs.getCertificate().get()->getDER(); + retCode = verifyBinaryData(DataType::CERTIFICATE, certData); + if(retCode != CKM_API_SUCCESS) + return retCode; + output.push_back(createEncryptedRow(crypto, name, ownerLabel, DataType::CERTIFICATE, certData, certPolicy)); + + // CA cert chain + unsigned int cert_index = 0; + for(const auto & ca : pkcs.getCaCertificateShPtrVector()) + { + DataType chainDataType = DataType::getChainDatatype(cert_index ++); + RawBuffer caCertData = ca->getDER(); + int retCode = verifyBinaryData(chainDataType, caCertData); + if(retCode != CKM_API_SUCCESS) + return retCode; + + output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy)); } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::GET)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, static_cast(row.dataType)); - Serialization::Serialize(response, row.data); - return response.Pop(); + return CKM_API_SUCCESS; } -RawBuffer CKMLogic::getDataList( - Credentials &cred, +RawBuffer CKMLogic::savePKCS12( + const Credentials &cred, int commandId, - DBDataType dataType) + const Name &name, + const Label &label, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy) { - int retCode = CKM_API_SUCCESS; - AliasVector aliasVector; - - if (0 < m_userDataMap.count(cred.uid)) { - auto &handler = m_userDataMap[cred.uid]; - Try { - if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) { - handler.database.getAliases(dataType, aliasVector); - } else { - handler.database.getKeyAliases(aliasVector); - } - } Catch (CKM::Exception) { - LogError("Failed to get aliases"); - retCode = CKM_API_ERROR_DB_ERROR; - } - } else { - retCode = CKM_API_ERROR_DB_LOCKED; + int retCode = CKM_API_ERROR_UNKNOWN; + try { + retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy); + } catch (const Exc::Exception &e) { + retCode = e.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; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::GET_LIST)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, static_cast(dataType)); - Serialization::Serialize(response, aliasVector); + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::SAVE_PKCS12), + commandId, + retCode); return response.Pop(); } -int CKMLogic::createKeyPairHelper( - Credentials &cred, - const KeyType key_type, - const int additional_param, - const Alias &aliasPrivate, - const Alias &aliasPublic, - const PolicySerializable &policyPrivate, - const PolicySerializable &policyPublic) +int CKMLogic::removeDataHelper( + const Credentials &cred, + const Name &name, + const Label &label) { - if (0 >= m_userDataMap.count(cred.uid)) - return CKM_API_ERROR_DB_LOCKED; + auto &handler = selectDatabase(cred, label); - auto &handler = m_userDataMap[cred.uid]; - KeyImpl prv, pub; - int retCode; - switch(key_type) - { - case KeyType::KEY_RSA_PUBLIC: - case KeyType::KEY_RSA_PRIVATE: - retCode = CryptoService::createKeyPairRSA(additional_param, prv, pub); - break; - - case KeyType::KEY_DSA_PUBLIC: - case KeyType::KEY_DSA_PRIVATE: - retCode = CryptoService::createKeyPairDSA(additional_param, prv, pub); - break; - - case KeyType::KEY_ECDSA_PUBLIC: - case KeyType::KEY_ECDSA_PRIVATE: - retCode = CryptoService::createKeyPairECDSA(static_cast(additional_param), prv, pub); - break; - - default: - return CKM_API_ERROR_INPUT_PARAM; + // use client label if not explicitly provided + const Label &ownerLabel = label.empty() ? cred.smackLabel : label; + if (!isNameValid(name) || !isLabelValid(ownerLabel)) { + LogDebug("Invalid label or name format"); + return CKM_API_ERROR_INPUT_PARAM; } - if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode) + DB::Crypto::Transaction transaction(&handler.database); + + // read and check permissions + PermissionMaskOptional permissionRowOpt = + handler.database.getPermissionRow(name, ownerLabel, cred.smackLabel); + int retCode = m_accessControl.canDelete(cred, + PermissionForLabel(cred.smackLabel, permissionRowOpt)); + if(retCode != CKM_API_SUCCESS) { - LogDebug("CryptoService error with code: " << retCode); - return CKM_API_ERROR_SERVER_ERROR; // TODO error code + LogWarning("access control check result: " << retCode); + return retCode; } - DBCrypto::Transaction transaction(&handler.database); - retCode = saveDataHelper(cred, - toDBDataType(prv.getType()), - aliasPrivate, - prv.getDER(), - policyPrivate); + // get all matching rows + DB::RowVector rows; + handler.database.getRows(name, ownerLabel, DataType::DB_FIRST, DataType::DB_LAST, rows); + if (rows.empty()) { + LogDebug("No row for given name and label"); + return CKM_API_ERROR_DB_ALIAS_UNKNOWN; + } - if (CKM_API_SUCCESS != retCode) + // load app key if needed + retCode = loadAppKey(handler, rows.front().ownerLabel); + if(CKM_API_SUCCESS != retCode) return retCode; - retCode = saveDataHelper(cred, - toDBDataType(pub.getType()), - aliasPublic, - pub.getDER(), - policyPublic); - - if (CKM_API_SUCCESS != retCode) - return retCode; + // destroy it in store + for(auto& r : rows) { + try { + handler.crypto.decryptRow(Password(), r); + m_decider.getStore(r).destroy(r); + } catch (const Exc::AuthenticationFailed&) { + LogDebug("Authentication failed when removing data. Ignored."); + } + } + // delete row in db + handler.database.deleteRow(name, ownerLabel); transaction.commit(); - return retCode; + return CKM_API_SUCCESS; } -RawBuffer CKMLogic::createKeyPair( - Credentials &cred, - LogicCommand protocol_cmd, +RawBuffer CKMLogic::removeData( + const Credentials &cred, int commandId, - const int additional_param, - const Alias &aliasPrivate, - const Alias &aliasPublic, - const PolicySerializable &policyPrivate, - const PolicySerializable &policyPublic) + const Name &name, + const Label &label) { - int retCode = CKM_API_SUCCESS; + int retCode = CKM_API_ERROR_UNKNOWN; - KeyType key_type = KeyType::KEY_NONE; - switch(protocol_cmd) + try { - case LogicCommand::CREATE_KEY_PAIR_RSA: - key_type = KeyType::KEY_RSA_PUBLIC; - break; - case LogicCommand::CREATE_KEY_PAIR_DSA: - key_type = KeyType::KEY_DSA_PUBLIC; - break; - case LogicCommand::CREATE_KEY_PAIR_ECDSA: - key_type = KeyType::KEY_ECDSA_PUBLIC; - break; - default: - break; + retCode = removeDataHelper(cred, name, label); } - - try { - retCode = createKeyPairHelper( - cred, - key_type, - additional_param, - aliasPrivate, - aliasPublic, - policyPrivate, - policyPublic); - - } catch (DBCrypto::Exception::AliasExists &e) { - LogDebug("DBCrypto error: alias exists: " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ALIAS_EXISTS; - } catch (DBCrypto::Exception::TransactionError &e) { - LogDebug("DBCrypto error: transaction error: " << e.GetMessage()); - retCode = CKM_API_ERROR_DB_ERROR; - } catch (CKM::CryptoLogic::Exception::Base &e) { - LogDebug("CryptoLogic error: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (DBCrypto::Exception::InternalError &e) { - LogDebug("DBCrypto internal error: " << e.GetMessage()); + catch (const Exc::Exception &e) + { + retCode = e.error(); + } + catch (const CKM::Exception &) + { + LogError("Error in deleting row!"); retCode = CKM_API_ERROR_DB_ERROR; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(protocol_cmd)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::REMOVE), + commandId, + retCode); return response.Pop(); } -RawBuffer CKMLogic::getCertificateChain( - Credentials &cred, - int commandId, - const RawBuffer &certificate, - const RawBufferVector &untrustedRawCertVector) +int CKMLogic::readSingleRow(const Name &name, + const Label &ownerLabel, + DataType dataType, + DB::Crypto & database, + DB::Row &row) { - (void)cred; + DB::Crypto::RowOptional row_optional; + if (dataType.isKey()) + { + // read all key types + row_optional = database.getRow(name, + ownerLabel, + DataType::DB_KEY_FIRST, + DataType::DB_KEY_LAST); + } else { + // read anything else + row_optional = database.getRow(name, + ownerLabel, + dataType); + } - CertificateImpl cert(certificate, DataFormat::FORM_DER); - CertificateImplVector untrustedCertVector; - CertificateImplVector chainVector; - RawBufferVector chainRawVector; + if(!row_optional) { + LogDebug("No row for given name, label and type"); + return CKM_API_ERROR_DB_ALIAS_UNKNOWN; + } else { + row = *row_optional; + } - for (auto &e: untrustedRawCertVector) - untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER)); + return CKM_API_SUCCESS; +} - LogDebug("Cert is empty: " << cert.empty()); - int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector); +int CKMLogic::readMultiRow(const Name &name, + const Label &ownerLabel, + DataType dataType, + DB::Crypto & database, + DB::RowVector &output) +{ + if (dataType.isKey()) + { + // read all key types + database.getRows(name, + ownerLabel, + DataType::DB_KEY_FIRST, + DataType::DB_KEY_LAST, + output); + } + else if (dataType.isChainCert()) + { + // read all key types + database.getRows(name, + ownerLabel, + DataType::DB_CHAIN_FIRST, + DataType::DB_CHAIN_LAST, + output); + } + else + { + // read anything else + database.getRows(name, + ownerLabel, + dataType, + output); + } - if (retCode == CKM_API_SUCCESS) { - for (auto &e : chainVector) - chainRawVector.push_back(e.getDER()); + if(!output.size()) { + LogDebug("No row for given name, label and type"); + return CKM_API_ERROR_DB_ALIAS_UNKNOWN; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::GET_CHAIN_CERT)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, chainRawVector); - return response.Pop(); + return CKM_API_SUCCESS; } -RawBuffer CKMLogic::getCertificateChain( - Credentials &cred, +int CKMLogic::checkDataPermissionsHelper(const Credentials &cred, + const Name &name, + const Label &ownerLabel, + const Label &accessorLabel, + const DB::Row &row, + bool exportFlag, + DB::Crypto & database) +{ + PermissionMaskOptional permissionRowOpt = + database.getPermissionRow(name, ownerLabel, accessorLabel); + + if(exportFlag) + return m_accessControl.canExport(cred, row, PermissionForLabel(accessorLabel, permissionRowOpt)); + return m_accessControl.canRead(cred, PermissionForLabel(accessorLabel, permissionRowOpt)); +} + +Crypto::GObjUPtr CKMLogic::rowToObject( + UserData& handler, + DB::Row row, + const Password& password) +{ + Crypto::GStore& store = m_decider.getStore(row); + + Password pass = m_accessControl.isCCMode() ? "" : password; + + // decrypt row + Crypto::GObjUPtr obj; + if(CryptoLogic::getSchemeVersion(row.encryptionScheme) == CryptoLogic::ENCRYPTION_V2) { + handler.crypto.decryptRow(Password(), row); + + obj = store.getObject(row, pass); + } else { + // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data + handler.crypto.decryptRow(pass, row); + // destroy it in store + store.destroy(row); + + // import it to store with new scheme: data -> pass(data) + Token token = store.import(row.dataType,row.data, pass); + + // get it from the store (it can be different than the data we imported into store) + obj = store.getObject(token, pass); + + // update row with new token + *static_cast(&row) = std::move(token); + + // encrypt it with app key: pass(data) -> b64(appkey(pass(data)) + handler.crypto.encryptRow(row); + + // update it in db + handler.database.updateRow(row); + } + return obj; +} + +int CKMLogic::readDataHelper( + bool exportFlag, + const Credentials &cred, + DataType dataType, + const Name &name, + const Label &label, + const Password &password, + Crypto::GObjUPtrVector &objs) +{ + 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)) + return CKM_API_ERROR_INPUT_PARAM; + + // read rows + DB::Crypto::Transaction transaction(&handler.database); + DB::RowVector rows; + 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 + retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, firstRow, exportFlag, handler.database); + if(CKM_API_SUCCESS != retCode) + return retCode; + + // load app key if needed + retCode = loadAppKey(handler, firstRow.ownerLabel); + if(CKM_API_SUCCESS != retCode) + return retCode; + + // decrypt row + for(auto &row : rows) + objs.push_back(rowToObject(handler, std::move(row), password)); + // rowToObject may modify db + transaction.commit(); + + return CKM_API_SUCCESS; +} + +int CKMLogic::readDataHelper( + bool exportFlag, + const Credentials &cred, + DataType dataType, + const Name &name, + const Label &label, + const Password &password, + Crypto::GObjUPtr &obj) +{ + DataType objDataType; + return readDataHelper(exportFlag, cred, dataType, name, label, password, obj, objDataType); +} + +int CKMLogic::readDataHelper( + bool exportFlag, + const Credentials &cred, + DataType dataType, + const Name &name, + const Label &label, + const Password &password, + Crypto::GObjUPtr &obj, + DataType& objDataType) +{ + 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)) + return CKM_API_ERROR_INPUT_PARAM; + + // read row + DB::Crypto::Transaction transaction(&handler.database); + DB::Row row; + int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row); + if(CKM_API_SUCCESS != retCode) + return retCode; + + objDataType = row.dataType; + + // check access rights + retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database); + if(CKM_API_SUCCESS != retCode) + return retCode; + + // load app key if needed + retCode = loadAppKey(handler, row.ownerLabel); + if(CKM_API_SUCCESS != retCode) + return retCode; + + obj = rowToObject(handler, std::move(row), password); + // rowToObject may modify db + transaction.commit(); + + return CKM_API_SUCCESS; +} + +RawBuffer CKMLogic::getData( + const Credentials &cred, int commandId, - const RawBuffer &certificate, - const AliasVector &aliasVector) + DataType dataType, + const Name &name, + const Label &label, + const Password &password) { int retCode = CKM_API_SUCCESS; - RawBufferVector chainRawVector; + DB::Row row; + DataType objDataType; + try { - CertificateImpl cert(certificate, DataFormat::FORM_DER); - CertificateImplVector untrustedCertVector; - CertificateImplVector chainVector; - DBRow row; - - if (cert.empty()) { - retCode = CKM_API_ERROR_SERVER_ERROR; - goto senderror; - } + Crypto::GObjUPtr obj; + retCode = readDataHelper(true, cred, dataType, name, label, password, obj, objDataType); + if(retCode == CKM_API_SUCCESS) + row.data = std::move(obj->getBinary()); + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } + + if (CKM_API_SUCCESS != retCode) { + row.data.clear(); + row.dataType = dataType; + } + + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET), + commandId, + retCode, + static_cast(objDataType), + row.data); + return response.Pop(); +} + +int CKMLogic::getPKCS12Helper( + const Credentials &cred, + const Name &name, + const Label &label, + const Password &keyPassword, + const Password &certPassword, + KeyShPtr & privKey, + CertificateShPtr & cert, + CertificateShPtrVector & caChain) +{ + int retCode; + + // read private key (mandatory) + Crypto::GObjUPtr keyObj; + retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, keyObj); + if(retCode != CKM_API_SUCCESS) + return retCode; + privKey = CKM::Key::create(keyObj->getBinary()); + + // read certificate (mandatory) + Crypto::GObjUPtr certObj; + retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certObj); + if(retCode != CKM_API_SUCCESS) + return retCode; + cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER); + + // read CA cert chain (optional) + Crypto::GObjUPtrVector caChainObjs; + retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, caChainObjs); + if(retCode != CKM_API_SUCCESS && + retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) + return retCode; + for(auto &caCertObj : caChainObjs) + caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(), DataFormat::FORM_DER)); + + // if anything found, return it + if(privKey || cert || caChain.size()>0) + retCode = CKM_API_SUCCESS; + + return retCode; +} + +RawBuffer CKMLogic::getPKCS12( + const Credentials &cred, + int commandId, + const Name &name, + const Label &label, + const Password &keyPassword, + const Password &certPassword) +{ + int retCode = CKM_API_ERROR_UNKNOWN; + + PKCS12Serializable output; + try { + KeyShPtr privKey; + CertificateShPtr cert; + CertificateShPtrVector caChain; + retCode = getPKCS12Helper(cred, name, label, keyPassword, certPassword, privKey, cert, caChain); + + // prepare response + if(retCode == CKM_API_SUCCESS) + output = PKCS12Serializable(privKey, cert, caChain); + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } + + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET_PKCS12), + commandId, + retCode, + output); + return response.Pop(); +} - for (auto &i: aliasVector) { - retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Password(), row); +int CKMLogic::getDataListHelper(const Credentials &cred, + const DataType dataType, + LabelNameVector &labelNameVector) +{ + 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, + tmpVector, + DataType::DB_KEY_FIRST, + DataType::DB_KEY_LAST); + } else { + // list anything else + database.listNames(cred.smackLabel, + 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; + } + } + return retCode; +} - if (retCode != CKM_API_SUCCESS) - goto senderror; +RawBuffer CKMLogic::getDataList( + const Credentials &cred, + int commandId, + DataType dataType) +{ + LabelNameVector systemVector; + LabelNameVector userVector; + LabelNameVector labelNameVector; - untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER)); + int retCode = unlockSystemDB(); + if (CKM_API_SUCCESS == retCode) + { + // system database + if (m_accessControl.isSystemService(cred)) + { + // lookup system DB + retCode = getDataListHelper(Credentials(SYSTEM_DB_UID, + OWNER_ID_SYSTEM), + 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, + static_cast(dataType), + labelNameVector); + return response.Pop(); +} + +int CKMLogic::saveDataHelper( + const Credentials &cred, + const Name &name, + const Label &label, + DataType dataType, + const RawBuffer &data, + const PolicySerializable &policy) +{ + 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(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + + // check if save is possible + DB::Crypto::Transaction transaction(&handler.database); + int retCode = checkSaveConditions(cred, handler, name, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // save the data + DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy); + handler.database.saveRow(encryptedRow); + + transaction.commit(); + return CKM_API_SUCCESS; +} + +int CKMLogic::saveDataHelper( + const Credentials &cred, + const Name &name, + const Label &label, + const PKCS12Serializable &pkcs, + const PolicySerializable &keyPolicy, + const PolicySerializable &certPolicy) +{ + 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(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + + // check if save is possible + DB::Crypto::Transaction transaction(&handler.database); + int retCode = checkSaveConditions(cred, handler, name, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // extract and encrypt the data + DB::RowVector encryptedRows; + retCode = extractPKCS12Data(handler.crypto, name, ownerLabel, pkcs, keyPolicy, certPolicy, encryptedRows); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // save the data + handler.database.saveRows(name, ownerLabel, encryptedRows); + transaction.commit(); + + return CKM_API_SUCCESS; +} + + +int CKMLogic::createKeyAESHelper( + const Credentials &cred, + const int size, + const Name &name, + const Label &label, + const PolicySerializable &policy) +{ + 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(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + + // check if save is possible + DB::Crypto::Transaction transaction(&handler.database); + int retCode = checkSaveConditions(cred, handler, name, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // create key in store + CryptoAlgorithm keyGenAlgorithm; + keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN); + keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size); + Token key = m_decider.getStore(DataType::KEY_AES, policy.extractable).generateSKey(keyGenAlgorithm, policy.password); - retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector); + // save the data + DB::Row row(std::move(key), name, ownerLabel, static_cast(policy.extractable)); + handler.crypto.encryptRow(row); - if (retCode != CKM_API_SUCCESS) - goto senderror; + handler.database.saveRow(row); - for (auto &i: chainVector) - chainRawVector.push_back(i.getDER()); + transaction.commit(); + return CKM_API_SUCCESS; +} - } catch (const CryptoLogic::Exception::Base &e) { - LogError("DBCyptorModule failed with message: " << e.GetMessage()); + +int CKMLogic::createKeyPairHelper( + const Credentials &cred, + const CryptoAlgorithmSerializable & keyGenParams, + const Name &namePrivate, + const Label &labelPrivate, + const Name &namePublic, + const Label &labelPublic, + const PolicySerializable &policyPrivate, + const PolicySerializable &policyPublic) +{ + auto &handlerPriv = selectDatabase(cred, labelPrivate); + auto &handlerPub = selectDatabase(cred, labelPublic); + + AlgoType keyType = AlgoType::RSA_GEN; + if(!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType)) + ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found."); + DataType dt(keyType); + if(!dt.isKey()) + ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value."); + + // use client label if not explicitly provided + const Label &ownerLabelPrv = labelPrivate.empty() ? cred.smackLabel : labelPrivate; + if( m_accessControl.isSystemService(cred) && ownerLabelPrv.compare(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + const Label &ownerLabelPub = labelPublic.empty() ? cred.smackLabel : labelPublic; + if( m_accessControl.isSystemService(cred) && ownerLabelPub.compare(OWNER_ID_SYSTEM)!=0) + return CKM_API_ERROR_INPUT_PARAM; + + bool exportable = policyPrivate.extractable || policyPublic.extractable; + TokenPair keys = m_decider.getStore(dt, exportable).generateAKey(keyGenParams, + policyPrivate.password, + policyPublic.password); + + 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; + retCode = checkSaveConditions(cred, handlerPriv, namePrivate, ownerLabelPrv); + if(retCode != CKM_API_SUCCESS) + return retCode; + retCode = checkSaveConditions(cred, handlerPub, namePrivate, ownerLabelPub); + if(retCode != CKM_API_SUCCESS) + return retCode; + + // save the data + DB::Row rowPrv(std::move(keys.first), namePrivate, ownerLabelPrv, static_cast(policyPrivate.extractable)); + handlerPriv.crypto.encryptRow(rowPrv); + handlerPriv.database.saveRow(rowPrv); + + DB::Row rowPub(std::move(keys.second), namePublic, ownerLabelPub, static_cast(policyPublic.extractable)); + handlerPub.crypto.encryptRow(rowPub); + handlerPub.database.saveRow(rowPub); + + transactionPub.commit(); + transactionPriv.commit(); + return CKM_API_SUCCESS; +} + +RawBuffer CKMLogic::createKeyPair( + const Credentials &cred, + int commandId, + const CryptoAlgorithmSerializable & keyGenParams, + const Name &namePrivate, + const Label &labelPrivate, + const Name &namePublic, + const Label &labelPublic, + const PolicySerializable &policyPrivate, + const PolicySerializable &policyPublic) +{ + int retCode = CKM_API_SUCCESS; + + try { + retCode = createKeyPairHelper( + cred, + keyGenParams, + namePrivate, + labelPrivate, + namePublic, + labelPublic, + policyPrivate, + policyPublic); + } catch(const Exc::Exception &e) { + retCode = e.error(); + } catch (DB::Crypto::Exception::TransactionError &e) { + LogDebug("DB::Crypto error: transaction error: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (DB::Crypto::Exception::InternalError &e) { + LogDebug("DB::Crypto internal error: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const DBCrypto::Exception::PermissionDenied &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } catch (const DBCrypto::Exception::Base &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); + } + + return MessageBuffer::Serialize(static_cast(LogicCommand::CREATE_KEY_PAIR), + commandId, retCode).Pop(); +} + +RawBuffer CKMLogic::createKeyAES( + const Credentials &cred, + int commandId, + const int size, + const Name &name, + const Label &label, + const PolicySerializable &policy) +{ + int retCode = CKM_API_SUCCESS; + + try { + retCode = createKeyAESHelper(cred, size, name, label, policy); + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (std::invalid_argument &e) { + LogDebug("invalid argument error: " << e.what()); + 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; + } catch (DB::Crypto::Exception::InternalError &e) { + LogDebug("DB::Crypto internal error: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const CKM::Exception &e) { + LogError("CKM::Exception: " << e.GetMessage()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } + + return MessageBuffer::Serialize(static_cast(LogicCommand::CREATE_KEY_AES), + commandId, retCode).Pop(); +} + +int CKMLogic::readCertificateHelper( + const Credentials &cred, + const LabelNameVector &labelNameVector, + CertificateImplVector &certVector) +{ + DB::Row row; + for (auto &i: labelNameVector) { + // certificates can't be protected with custom user password + Crypto::GObjUPtr obj; + int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), obj); + if (ec != CKM_API_SUCCESS) + return ec; + + certVector.emplace_back(obj->getBinary(), DataFormat::FORM_DER); + + // try to read chain certificates (if present) + Crypto::GObjUPtrVector caChainObjs; + ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), caChainObjs); + if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN) + return ec; + for(auto &caCertObj : caChainObjs) + certVector.emplace_back(caCertObj->getBinary(), DataFormat::FORM_DER); + } + return CKM_API_SUCCESS; +} + +int CKMLogic::getCertificateChainHelper( + const CertificateImpl &cert, + const RawBufferVector &untrustedCertificates, + const RawBufferVector &trustedCertificates, + bool useTrustedSystemCertificates, + RawBufferVector &chainRawVector) +{ + CertificateImplVector untrustedCertVector; + CertificateImplVector trustedCertVector; + CertificateImplVector chainVector; + + if (cert.empty()) + return CKM_API_ERROR_INPUT_PARAM; + + for (auto &e: untrustedCertificates) { + CertificateImpl c(e, DataFormat::FORM_DER); + if(c.empty()) + return CKM_API_ERROR_INPUT_PARAM; + untrustedCertVector.push_back(std::move(c)); + } + for (auto &e: trustedCertificates) { + CertificateImpl c(e, DataFormat::FORM_DER); + if(c.empty()) + return CKM_API_ERROR_INPUT_PARAM; + trustedCertVector.push_back(std::move(c)); + } + + CertificateStore store; + int retCode = store.verifyCertificate(cert, + untrustedCertVector, + trustedCertVector, + useTrustedSystemCertificates, + m_accessControl.isCCMode(), + chainVector); + if (retCode != CKM_API_SUCCESS) + return retCode; + + for (auto &e : chainVector) + chainRawVector.push_back(e.getDER()); + return CKM_API_SUCCESS; +} + +int CKMLogic::getCertificateChainHelper( + const Credentials &cred, + const CertificateImpl &cert, + const LabelNameVector &untrusted, + const LabelNameVector &trusted, + bool useTrustedSystemCertificates, + RawBufferVector &chainRawVector) +{ + CertificateImplVector untrustedCertVector; + CertificateImplVector trustedCertVector; + CertificateImplVector chainVector; + DB::Row row; + + if (cert.empty()) + return CKM_API_ERROR_INPUT_PARAM; + + int retCode = readCertificateHelper(cred, untrusted, untrustedCertVector); + if (retCode != CKM_API_SUCCESS) + return retCode; + retCode = readCertificateHelper(cred, trusted, trustedCertVector); + if (retCode != CKM_API_SUCCESS) + return retCode; + + CertificateStore store; + retCode = store.verifyCertificate(cert, + untrustedCertVector, + trustedCertVector, + useTrustedSystemCertificates, + m_accessControl.isCCMode(), + chainVector); + if (retCode != CKM_API_SUCCESS) + return retCode; + + for (auto &i: chainVector) + chainRawVector.push_back(i.getDER()); + + return CKM_API_SUCCESS; +} + +RawBuffer CKMLogic::getCertificateChain( + const Credentials & /*cred*/, + int commandId, + const RawBuffer &certificate, + const RawBufferVector &untrustedCertificates, + const RawBufferVector &trustedCertificates, + bool useTrustedSystemCertificates) +{ + CertificateImpl cert(certificate, DataFormat::FORM_DER); + RawBufferVector chainRawVector; + int retCode = CKM_API_ERROR_UNKNOWN; + try { + retCode = getCertificateChainHelper(cert, + untrustedCertificates, + trustedCertificates, + useTrustedSystemCertificates, + chainRawVector); + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const std::exception& e) { + LogError("STD exception " << e.what()); + retCode = CKM_API_ERROR_SERVER_ERROR; + } catch (...) { + LogError("Unknown error."); + } + + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET_CHAIN_CERT), + commandId, + retCode, + chainRawVector); + return response.Pop(); +} + +RawBuffer CKMLogic::getCertificateChain( + const Credentials &cred, + int commandId, + const RawBuffer &certificate, + const LabelNameVector &untrustedCertificates, + const LabelNameVector &trustedCertificates, + bool useTrustedSystemCertificates) +{ + int retCode = CKM_API_ERROR_UNKNOWN; + CertificateImpl cert(certificate, DataFormat::FORM_DER); + RawBufferVector chainRawVector; + try { + retCode = getCertificateChainHelper(cred, + cert, + untrustedCertificates, + trustedCertificates, + useTrustedSystemCertificates, + chainRawVector); + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); + retCode = CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const std::exception& e) { + LogError("STD exception " << e.what()); + retCode = CKM_API_ERROR_SERVER_ERROR; } catch (...) { LogError("Unknown error."); } -senderror: - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::GET_CHAIN_ALIAS)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, chainRawVector); + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::GET_CHAIN_ALIAS), + commandId, + retCode, + chainRawVector); return response.Pop(); } RawBuffer CKMLogic::createSignature( - Credentials &cred, + const Credentials &cred, int commandId, - const Alias &privateKeyAlias, + const Name &privateKeyName, + const Label & ownerLabel, const Password &password, // password for private_key const RawBuffer &message, const HashAlgorithm hash, const RSAPaddingAlgorithm padding) { - DBRow row; - CryptoService cs; + DB::Row row; RawBuffer signature; + CryptoAlgorithm cryptoAlg; + cryptoAlg.setParam(ParamName::SV_HASH_ALGO, hash); + cryptoAlg.setParam(ParamName::SV_RSA_PADDING, padding); int retCode = CKM_API_SUCCESS; try { - do { - retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, privateKeyAlias, password, row); - if (CKM_API_SUCCESS != retCode) { - LogError("getDataHelper return error"); - break; - } - - KeyImpl keyParsed(row.data, Password()); - if (keyParsed.empty()) - retCode = CKM_API_ERROR_SERVER_ERROR; - else - retCode = cs.createSignature(keyParsed, message, hash, padding, signature); - } while(0); - } 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 DBCrypto::Exception::PermissionDenied &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } catch (const DBCrypto::Exception::Base &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); + Crypto::GObjUPtr obj; + retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, obj); + if(retCode == CKM_API_SUCCESS) { + signature = obj->sign(cryptoAlg, message); + } + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; + } catch (const Exc::Exception &e) { + retCode = e.error(); } catch (const CKM::Exception &e) { LogError("Unknown CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::CREATE_SIGNATURE)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - Serialization::Serialize(response, signature); + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::CREATE_SIGNATURE), + commandId, + retCode, + signature); return response.Pop(); } RawBuffer CKMLogic::verifySignature( - Credentials &cred, + const Credentials &cred, int commandId, - const Alias &publicKeyOrCertAlias, + const Name &publicKeyOrCertName, + const Label & ownerLabel, const Password &password, // password for public_key (optional) const RawBuffer &message, const RawBuffer &signature, @@ -768,130 +1609,129 @@ RawBuffer CKMLogic::verifySignature( int retCode = CKM_API_ERROR_VERIFICATION_FAILED; try { - do { - CryptoService cs; - DBRow row; - KeyImpl key; - - retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row); - - if (retCode == CKM_API_SUCCESS) { - key = KeyImpl(row.data); - } else if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) { - retCode = getDataHelper(cred, DBDataType::CERTIFICATE, publicKeyOrCertAlias, password, row); - if (retCode != CKM_API_SUCCESS) - break; - CertificateImpl cert(row.data, DataFormat::FORM_DER); - key = cert.getKeyImpl(); - } else { - break; - } - - if (key.empty()) { - retCode = CKM_API_ERROR_SERVER_ERROR; - break; - } + DB::Row row; + + CryptoAlgorithm params; + params.setParam(ParamName::SV_HASH_ALGO, hash); + params.setParam(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. + Crypto::GObjUPtr obj; + retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, obj); + if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) { + retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, obj); + } - retCode = cs.verifySignature(key, message, signature, hash, padding); - } while(0); - } catch (const CryptoService::Exception::Crypto_internal &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const CryptoService::Exception::opensslError &e) { - LogError("KeyProvider failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_SERVER_ERROR; - } catch (const KeyProvider::Exception::Base &e) { - LogError("KeyProvider failed with error: " << 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 DBCrypto::Exception::PermissionDenied &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } catch (const DBCrypto::Exception::Base &e) { - LogError("DBCrypto failed with message: " << e.GetMessage()); + if (retCode == CKM_API_SUCCESS) { + retCode = obj->verify(params, message, signature); + } + } catch (const Exc::Exception &e) { + retCode = e.error(); + } catch (const DB::Crypto::Exception::Base &e) { + LogError("DB::Crypto failed with message: " << e.GetMessage()); retCode = CKM_API_ERROR_DB_ERROR; } catch (const CKM::Exception &e) { LogError("Unknown CKM::Exception: " << e.GetMessage()); retCode = CKM_API_ERROR_SERVER_ERROR; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::VERIFY_SIGNATURE)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); - + auto response = MessageBuffer::Serialize(static_cast(LogicCommand::VERIFY_SIGNATURE), + commandId, + retCode); return response.Pop(); } -RawBuffer CKMLogic::allowAccess( - Credentials &cred, - int commandId, - const Alias &item_alias, - const std::string &accessor_label, - const AccessRight req_rights) +int CKMLogic::setPermissionHelper( + const Credentials &cred, // who's the client + const Name &name, + const Label &label, // who's the owner + const Label &accessorLabel, // who will get the access + const PermissionMask permissionMask) { - int retCode = CKM_API_ERROR_VERIFICATION_FAILED; + auto &handler = selectDatabase(cred, label); + + // we don't know the client + if (cred.smackLabel.empty() || !isLabelValid(cred.smackLabel)) + return CKM_API_ERROR_INPUT_PARAM; + + // use client label if not explicitly provided + const Label& ownerLabel = label.empty() ? cred.smackLabel : label; + + // verify name and label are correct + if (!isNameValid(name) || !isLabelValid(ownerLabel) || !isLabelValid(accessorLabel)) + return CKM_API_ERROR_INPUT_PARAM; + + // currently we don't support modification of owner's permissions to his own rows + if (ownerLabel==accessorLabel) + return CKM_API_ERROR_INPUT_PARAM; + + // system database does not support write/remove permissions + if ((0 == ownerLabel.compare(OWNER_ID_SYSTEM)) && + (permissionMask & Permission::REMOVE)) + return CKM_API_ERROR_INPUT_PARAM; + + // can the client modify permissions to owner's row? + int retCode = m_accessControl.canModify(cred, ownerLabel); + if(retCode != CKM_API_SUCCESS) + return retCode; + + DB::Crypto::Transaction transaction(&handler.database); - if (0 < m_userDataMap.count(cred.uid)) + if( !handler.database.isNameLabelPresent(name, ownerLabel) ) + return CKM_API_ERROR_DB_ALIAS_UNKNOWN; + + // removing non-existing permissions: fail + if(permissionMask == Permission::NONE) { - Try { - retCode = m_userDataMap[cred.uid].database.setAccessRights(cred.smackLabel, item_alias, accessor_label, req_rights); - } Catch (DBCrypto::Exception::InvalidArgs) { - LogError("Error: invalid args!"); - retCode = CKM_API_ERROR_INPUT_PARAM; - } Catch (DBCrypto::Exception::PermissionDenied) { - LogError("Error: not enough permissions!"); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } Catch (CKM::Exception) { - LogError("Error in set row!"); - retCode = CKM_API_ERROR_DB_ERROR; - } - } else { - retCode = CKM_API_ERROR_DB_LOCKED; + if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel)) + return CKM_API_ERROR_INPUT_PARAM; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::ALLOW_ACCESS)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); + // set permissions to the row owned by ownerLabel for accessorLabel + handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask); + transaction.commit(); - return response.Pop(); + return CKM_API_SUCCESS; } -RawBuffer CKMLogic::denyAccess( - Credentials &cred, - int commandId, - const Alias &item_alias, - const std::string &accessor_label) +RawBuffer CKMLogic::setPermission( + const Credentials &cred, + const int command, + const int msgID, + const Name &name, + const Label &label, + const Label &accessorLabel, + const PermissionMask permissionMask) { - int retCode = CKM_API_ERROR_VERIFICATION_FAILED; - - if (0 < m_userDataMap.count(cred.uid)) - { - Try { - retCode = m_userDataMap[cred.uid].database.clearAccessRights(cred.smackLabel, item_alias, accessor_label); - } Catch (DBCrypto::Exception::PermissionDenied) { - LogError("Error: not enough permissions!"); - retCode = CKM_API_ERROR_ACCESS_DENIED; - } Catch (DBCrypto::Exception::InvalidArgs) { - LogError("Error: permission not found!"); - retCode = CKM_API_ERROR_INPUT_PARAM; - } Catch (CKM::Exception) { - LogError("Error in deleting row!"); - retCode = CKM_API_ERROR_DB_ERROR; - } - } else { - retCode = CKM_API_ERROR_DB_LOCKED; + int retCode; + Try { + retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask); + } catch (const Exc::Exception &e) { + retCode = e.error(); + } Catch (CKM::Exception) { + LogError("Error in set row!"); + retCode = CKM_API_ERROR_DB_ERROR; } - MessageBuffer response; - Serialization::Serialize(response, static_cast(LogicCommand::DENY_ACCESS)); - Serialization::Serialize(response, commandId); - Serialization::Serialize(response, retCode); + return MessageBuffer::Serialize(command, msgID, retCode).Pop(); +} - return response.Pop(); +int CKMLogic::loadAppKey(UserData& handle, const Label& appLabel) +{ + if (!handle.crypto.haveKey(appLabel)) { + RawBuffer key; + auto key_optional = handle.database.getKey(appLabel); + if(!key_optional) { + LogError("No key for given label in database"); + return CKM_API_ERROR_DB_ERROR; + } + key = *key_optional; + key = handle.keyProvider.getPureDEK(key); + handle.crypto.pushKey(appLabel, key); + } + return CKM_API_SUCCESS; } } // namespace CKM