CC mode logic updated
[platform/core/security/key-manager.git] / src / manager / service / ckm-logic.cpp
index f0d86a2..7744066 100644 (file)
  * @version     1.0
  * @brief       Sample service implementation.
  */
+#include <vconf/vconf.h>
 #include <dpl/serialization.h>
 #include <dpl/log/log.h>
-
 #include <ckm/ckm-error.h>
 #include <ckm/ckm-type.h>
 #include <key-provider.h>
 #include <file-system.h>
-
+#include <CryptoService.h>
 #include <ckm-logic.h>
+#include <key-impl.h>
+
+#ifndef VCONFKEY_SECURITY_MDPP_STATE
+#define VCONFKEY_SECURITY_MDPP_STATE = "file/security_mdpp/security_mdpp_state";
+#endif
+
+namespace {
+const char * const CERT_SYSTEM_DIR = "/etc/ssl/certs";
+
+const char* const MDPP_MODE_ENFORCING = "Enforcing";
+const char* const MDPP_MODE_ENABLED = "Enabled";
+
+} // anonymous namespace
 
 namespace CKM {
 
-CKMLogic::CKMLogic(){
+CKMLogic::CKMLogic() : m_ccMode(false)
+{
     int retCode = FileSystem::init();
     // TODO what can I do when init went wrong? exit(-1) ??
     if (retCode) {
         LogError("Fatal error in FileSystem::init()");
     }
+
+    if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
+        LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
+    }
+
+    updateCCMode_internal();
 }
 
 CKMLogic::~CKMLogic(){}
 
-RawBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
+RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password) {
     // TODO try catch for all errors that should be supported by error code
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
 
     try {
         if (0 == m_userDataMap.count(user) || !(m_userDataMap[user].keyProvider.isInitialized())) {
             auto &handle = m_userDataMap[user];
             FileSystem fs(user);
-            auto wrappedDomainKEK = fs.getDomainKEK();
+            auto wrappedDomainKEK = fs.getDKEK();
 
             if (wrappedDomainKEK.empty()) {
                 wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
-                fs.saveDomainKEK(wrappedDomainKEK);
+                fs.saveDKEK(wrappedDomainKEK);
             }
 
             handle.keyProvider = KeyProvider(wrappedDomainKEK, password);
 
-            RawBuffer key = handle.keyProvider.getPureDomainKEK();
+            auto wrappedDatabaseDEK = fs.getDBDEK();
+
+            if (wrappedDatabaseDEK.empty()) {
+                wrappedDatabaseDEK = handle.keyProvider.generateDEK(std::to_string(user));
+                fs.saveDBDEK(wrappedDatabaseDEK);
+            }
+
+            RawBuffer key = handle.keyProvider.getPureDEK(wrappedDatabaseDEK);
             handle.database = DBCrypto(fs.getDBPath(), key);
-            handle.crypto = DBCryptoModule(key);
+            handle.crypto = CryptoLogic();
+
+            // remove data of removed apps during locked state
+            AppLabelVector removedApps = fs.clearRemovedsApps();
+            for(auto& appSmackLabel : removedApps) {
+                handle.database.deleteKey(appSmackLabel);
+            }
+
             // TODO wipe key
         }
+    } 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 = KEY_MANAGER_API_ERROR_SERVER_ERROR;
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const CryptoLogic::Exception::Base &e) {
+        LogError("CryptoLogic error: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_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();
+    if(retCode != CKM_API_SUCCESS) {
+        // When not successful, UserData in m_userDataMap should be erased.
+        // Because other operations make decision based on the existence of UserData in m_userDataMap.
+        m_userDataMap.erase(user);
+    }
+
+    return MessageBuffer::Serialize(retCode).Pop();
+}
+
+void CKMLogic::updateCCMode_internal() {
+    int fipsModeStatus = 0;
+    int rc = 0;
+    bool newMode;
+
+    char *mdppState = vconf_get_str(VCONFKEY_SECURITY_MDPP_STATE);
+    newMode = ( mdppState && (!strcmp(mdppState, MDPP_MODE_ENABLED) ||
+                              !strcmp(mdppState, MDPP_MODE_ENFORCING)) );
+    if (newMode == m_ccMode)
+        return;
+
+    m_ccMode = newMode;
+
+    fipsModeStatus = FIPS_mode();
+
+    if(m_ccMode) {
+        if(fipsModeStatus == 0) { // If FIPS mode off
+            rc = FIPS_mode_set(1); // Change FIPS_mode from off to on
+            if(rc == 0) {
+                LogError("Error in FIPS_mode_set function");
+            }
+        }
+    } else {
+        if(fipsModeStatus == 1) { // If FIPS mode on
+            rc = FIPS_mode_set(0); // Change FIPS_mode from on to off
+            if(rc == 0) {
+                LogError("Error in FIPS_mode_set function");
+            }
+        }
+    }
+}
+
+RawBuffer CKMLogic::updateCCMode() {
+    updateCCMode_internal();
+    return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
 }
 
 RawBuffer CKMLogic::lockUserKey(uid_t user) {
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
     // TODO try catch for all errors that should be supported by error code
     m_userDataMap.erase(user);
 
-    MessageBuffer response;
-    Serialization::Serialize(response, retCode);
-    return response.Pop();
+    return MessageBuffer::Serialize(retCode).Pop();
+
 }
 
 RawBuffer CKMLogic::removeUserData(uid_t user) {
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
     // TODO try catch for all errors that should be supported by error code
     m_userDataMap.erase(user);
 
     FileSystem fs(user);
     fs.removeUserData();
 
-    MessageBuffer response;
-    Serialization::Serialize(response, retCode);
-    return response.Pop();
+    return MessageBuffer::Serialize(retCode).Pop();
 }
 
 RawBuffer CKMLogic::changeUserPassword(
     uid_t user,
-    const std::string &oldPassword,
-    const std::string &newPassword)
+    const Password &oldPassword,
+    const Password &newPassword)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
-    // TODO try-catch
-    FileSystem fs(user);
-    auto wrappedDomainKEK = fs.getDomainKEK();
-    if (wrappedDomainKEK.empty()) {
-        retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
-    } else {
-        wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
-        fs.saveDomainKEK(wrappedDomainKEK);
+    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;
+    } 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(
     uid_t user,
-    const std::string &newPassword)
+    const Password &newPassword)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
     // TODO try-catch
     if (0 == m_userDataMap.count(user)) {
-        retCode = KEY_MANAGER_API_ERROR_BAD_REQUEST;
+        retCode = CKM_API_ERROR_BAD_REQUEST;
     } else {
         auto &handler = m_userDataMap[user];
         FileSystem fs(user);
-        fs.saveDomainKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
+        fs.saveDKEK(handler.keyProvider.getWrappedDomainKEK(newPassword));
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, retCode);
-    return response.Pop();
+    return MessageBuffer::Serialize(retCode).Pop();
+}
+
+RawBuffer CKMLogic::removeApplicationData(const std::string &smackLabel) {
+    int retCode = CKM_API_SUCCESS;
+
+    try {
+
+        if (smackLabel.empty()) {
+            retCode = CKM_API_ERROR_INPUT_PARAM;
+        } else {
+            UidVector uids = FileSystem::getUIDsFromDBFile();
+            for (auto userId : uids) {
+                if (0 == m_userDataMap.count(userId)) {
+                    FileSystem fs(userId);
+                    fs.addRemovedApp(smackLabel);
+                } else {
+                    auto &handle = m_userDataMap[userId];
+                    handle.database.deleteKey(smackLabel);
+                }
+            }
+        }
+
+    } catch (const DBCrypto::Exception::InternalError &e) {
+        LogError("DBCrypto 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());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    }
+
+    return MessageBuffer::Serialize(retCode).Pop();
 }
 
 int CKMLogic::saveDataHelper(
@@ -143,29 +262,75 @@ int CKMLogic::saveDataHelper(
     const PolicySerializable &policy)
 {
     if (0 == m_userDataMap.count(cred.uid))
-        return KEY_MANAGER_API_ERROR_DB_LOCKED;
+        return CKM_API_ERROR_DB_LOCKED;
 
-    DBRow row = {   alias,  cred.smackLabel, policy.restricted,
+    // proceed to data save
+    DBRow row = { alias, cred.smackLabel,
          policy.extractable, dataType, DBCMAlgType::NONE,
-         0, RawBuffer(10, 'c'), key.size(), key };
+         0, RawBuffer(), static_cast<int>(key.size()), key, RawBuffer() };
 
     auto &handler = m_userDataMap[cred.uid];
+    DBCrypto::Transaction transaction(&handler.database);
     if (!handler.crypto.haveKey(cred.smackLabel)) {
         RawBuffer key;
-        int status = handler.database.getKey(cred.smackLabel, key);
-        if (KEY_MANAGER_API_ERROR_DB_BAD_REQUEST == status) {
-            LogDebug("No Key in database found. Generating new one for label: " << cred.smackLabel);
+        auto key_optional = handler.database.getKey(cred.smackLabel);
+        if(!key_optional) {
+            LogDebug("No Key in database found. Generating new one for label: "
+                    << cred.smackLabel);
             key = handler.keyProvider.generateDEK(cred.smackLabel);
-            if (KEY_MANAGER_API_SUCCESS != handler.database.saveKey(cred.smackLabel, key)) {
-                LogError("Failed to save key for smack label: " << cred.smackLabel);
-                return KEY_MANAGER_API_ERROR_DB_ERROR;
-            }
+            handler.database.saveKey(cred.smackLabel, key);
+        } else {
+            LogDebug("Key from DB");
+            key = *key_optional;
         }
+
         key = handler.keyProvider.getPureDEK(key);
         handler.crypto.pushKey(cred.smackLabel, key);
     }
-    handler.crypto.encryptRow(policy.password, row);
-    return handler.database.saveDBRow(row);
+
+    // Do not encrypt data with password during cc_mode on
+    if(m_ccMode) {
+        handler.crypto.encryptRow("", row);
+    } else {
+        handler.crypto.encryptRow(policy.password, row);
+    }
+
+    handler.database.saveDBRow(row);
+    transaction.commit();
+    return CKM_API_SUCCESS;
+}
+
+void CKMLogic::verifyBinaryData(DBDataType dataType, const RawBuffer &input_data) const
+{
+    // verify the data integrity
+    switch(dataType)
+    {
+        case DBDataType::KEY_RSA_PUBLIC:
+        case DBDataType::KEY_RSA_PRIVATE:
+        case DBDataType::KEY_ECDSA_PUBLIC:
+        case DBDataType::KEY_ECDSA_PRIVATE:
+        case DBDataType::KEY_DSA_PUBLIC:
+        case DBDataType::KEY_DSA_PRIVATE:
+        case DBDataType::KEY_AES:
+        {
+            KeyShPtr output_key = CKM::Key::create(input_data);
+            if(output_key.get() == NULL)
+                ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid key data");
+            break;
+        }
+
+        case DBDataType::CERTIFICATE:
+        {
+            CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
+            if(cert.get() == NULL)
+                ThrowMsg(CKMLogic::Exception::InputDataInvalid, "provided binary data is not valid certificate data");
+            break;
+        }
+
+        // TODO: add here BINARY_DATA verification, i.e: max size etc.
+
+        default: break;
+    }
 }
 
 RawBuffer CKMLogic::saveData(
@@ -176,25 +341,36 @@ RawBuffer CKMLogic::saveData(
     const RawBuffer &key,
     const PolicySerializable &policy)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
-
+    int retCode = CKM_API_SUCCESS;
     try {
+        verifyBinaryData(dataType, key);
+
         retCode = saveDataHelper(cred, dataType, alias, key, policy);
         LogDebug("SaveDataHelper returned: " << retCode);
+    } catch (const CKMLogic::Exception::InputDataInvalid &e) {
+        LogError("Provided data invalid: " << e.GetMessage());
+        retCode = CKM_API_ERROR_INPUT_PARAM;
     } catch (const KeyProvider::Exception::Base &e) {
         LogError("KeyProvider failed with message: " << e.GetMessage());
-        retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
-    } catch (const DBCryptoModule::Exception::Base &e) {
-        LogError("DBCryptoModule failed with message: " << e.GetMessage());
-        retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
+        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;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::SAVE));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, static_cast<int>(dataType));
-
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(dataType));
     return response.Pop();
 }
 
@@ -204,20 +380,31 @@ RawBuffer CKMLogic::removeData(
     DBDataType dataType,
     const Alias &alias)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
 
     if (0 < m_userDataMap.count(cred.uid)) {
-        retCode = m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
+        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 = KEY_MANAGER_API_ERROR_DB_LOCKED;
+        retCode = CKM_API_ERROR_DB_LOCKED;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::REMOVE));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, static_cast<int>(dataType));
-
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(dataType));
     return response.Pop();
 }
 
@@ -225,45 +412,46 @@ int CKMLogic::getDataHelper(
     Credentials &cred,
     DBDataType dataType,
     const Alias &alias,
-    const std::string &password,
+    const Password &password,
     DBRow &row)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
-
     if (0 == m_userDataMap.count(cred.uid))
-        return KEY_MANAGER_API_ERROR_DB_LOCKED;
+        return CKM_API_ERROR_DB_LOCKED;
 
     auto &handler = m_userDataMap[cred.uid];
 
+    DBCrypto::DBRowOptional row_optional;
     if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
-        retCode = handler.database.getDBRow(alias, cred.smackLabel, dataType, row);
+        row_optional = handler.database.getDBRow(alias, cred.smackLabel, dataType);
     } else if ((static_cast<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
             && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
     {
-        retCode = handler.database.getKeyDBRow(alias, cred.smackLabel, row);
+        row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
     } else {
         LogError("Unknown type of requested data" << (int)dataType);
-        return KEY_MANAGER_API_ERROR_BAD_REQUEST;
+        return CKM_API_ERROR_BAD_REQUEST;
     }
-
-    if (KEY_MANAGER_API_SUCCESS != retCode){
-        LogDebug("DBCrypto::getDBRow failed with code: " << retCode);
-        return retCode;
+    if(!row_optional) {
+        LogError("No row for given alias, label and type");
+        return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+    } else {
+        row = *row_optional;
     }
 
     if (!handler.crypto.haveKey(row.smackLabel)) {
         RawBuffer key;
-        retCode = handler.database.getKey(row.smackLabel, key);
-        if (KEY_MANAGER_API_SUCCESS != retCode) {
-            LogDebug("DBCrypto::getKey failed with: " << retCode);
-            return retCode;
+        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;
         }
+        key = *key_optional;
         key = handler.keyProvider.getPureDEK(key);
         handler.crypto.pushKey(cred.smackLabel, key);
     }
     handler.crypto.decryptRow(password, row);
 
-    return KEY_MANAGER_API_SUCCESS;
+    return CKM_API_SUCCESS;
 }
 
 RawBuffer CKMLogic::getData(
@@ -271,32 +459,51 @@ RawBuffer CKMLogic::getData(
     int commandId,
     DBDataType dataType,
     const Alias &alias,
-    const std::string &password)
+    const Password &password)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
     DBRow row;
 
     try {
         retCode = getDataHelper(cred, dataType, alias, password, row);
     } catch (const KeyProvider::Exception::Base &e) {
         LogError("KeyProvider failed with error: " << e.GetMessage());
-        retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
-    } catch (const DBCryptoModule::Exception::Base &e) {
-        LogError("DBCryptoModule failed with message: " << e.GetMessage());
-        retCode = KEY_MANAGER_API_ERROR_SERVER_ERROR;
+        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());
+        retCode = CKM_API_ERROR_DB_ERROR;
     }
 
-    if (KEY_MANAGER_API_SUCCESS != retCode) {
+    if (CKM_API_SUCCESS != retCode) {
         row.data.clear();
         row.dataType = dataType;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::GET));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, static_cast<int>(row.dataType));
-    Serialization::Serialize(response, row.data);
+    if ((CKM_API_SUCCESS == retCode) && (row.exportable == 0)) {
+        row.data.clear();
+        retCode = CKM_API_ERROR_NOT_EXPORTABLE;
+    }
+
+    // Prevent extracting private keys during cc-mode on
+    if((m_ccMode) && (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;
+    }
+
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(row.dataType),
+                                             row.data);
     return response.Pop();
 }
 
@@ -305,75 +512,425 @@ RawBuffer CKMLogic::getDataList(
     int commandId,
     DBDataType dataType)
 {
-    int retCode = KEY_MANAGER_API_SUCCESS;
+    int retCode = CKM_API_SUCCESS;
     AliasVector aliasVector;
 
     if (0 < m_userDataMap.count(cred.uid)) {
         auto &handler = m_userDataMap[cred.uid];
-        if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
-            retCode = handler.database.getAliases(dataType, cred.smackLabel, aliasVector);
-        } else {
-            retCode = handler.database.getKeyAliases(cred.smackLabel, aliasVector);
+        Try {
+            if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
+                handler.database.getAliases(cred.smackLabel, dataType, aliasVector);
+            } else {
+                handler.database.getKeyAliases(cred.smackLabel, aliasVector);
+            }
+        } Catch (CKM::Exception) {
+            LogError("Failed to get aliases");
+            retCode = CKM_API_ERROR_DB_ERROR;
         }
     } else {
-        retCode = KEY_MANAGER_API_ERROR_DB_LOCKED;
+        retCode = CKM_API_ERROR_DB_LOCKED;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_LIST));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, static_cast<int>(dataType));
-    Serialization::Serialize(response, aliasVector);
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_LIST),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(dataType),
+                                             aliasVector);
     return response.Pop();
 }
 
-RawBuffer CKMLogic::createKeyPairRSA(
+
+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)
+{
+    if (0 >= m_userDataMap.count(cred.uid))
+        return CKM_API_ERROR_DB_LOCKED;
+
+    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<ElipticCurve>(additional_param), prv, pub);
+            break;
+
+        default:
+            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
+    }
+
+    DBCrypto::Transaction transaction(&handler.database);
+    retCode = saveDataHelper(cred,
+                            toDBDataType(prv.getType()),
+                            aliasPrivate,
+                            prv.getDER(),
+                            policyPrivate);
+
+    if (CKM_API_SUCCESS != retCode)
+        return retCode;
+
+    retCode = saveDataHelper(cred,
+                            toDBDataType(pub.getType()),
+                            aliasPublic,
+                            pub.getDER(),
+                            policyPublic);
+
+    if (CKM_API_SUCCESS != retCode)
+        return retCode;
+
+    transaction.commit();
+
+    return retCode;
+}
+
+RawBuffer CKMLogic::createKeyPair(
+    Credentials &cred,
+    LogicCommand protocol_cmd,
+    int commandId,
+    const int additional_param,
+    const Alias &aliasPrivate,
+    const Alias &aliasPublic,
+    const PolicySerializable &policyPrivate,
+    const PolicySerializable &policyPublic)
+{
+    int retCode = CKM_API_SUCCESS;
+
+    KeyType key_type = KeyType::KEY_NONE;
+    switch(protocol_cmd)
+    {
+        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;
+    }
+
+    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());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    }
+
+    return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
+}
+
+RawBuffer CKMLogic::getCertificateChain(
     Credentials &cred,
     int commandId,
-    int size,
-    const Alias &privateKeyAlias,
-    const Alias &publicKeyAlias,
-    PolicySerializable policyPrivateKey,
-    PolicySerializable policyPublicKey)
+    const RawBuffer &certificate,
+    const RawBufferVector &untrustedRawCertVector)
 {
     (void)cred;
-    (void)size;
-    (void)privateKeyAlias;
-    (void)publicKeyAlias,
-    (void)policyPrivateKey;
-    (void)policyPublicKey;
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+
+    CertificateImpl cert(certificate, DataFormat::FORM_DER);
+    CertificateImplVector untrustedCertVector;
+    CertificateImplVector chainVector;
+    RawBufferVector chainRawVector;
+
+    for (auto &e: untrustedRawCertVector)
+        untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
+
+    LogDebug("Cert is empty: " << cert.empty());
+
+    int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
+
+    if (retCode == CKM_API_SUCCESS) {
+        for (auto &e : chainVector)
+            chainRawVector.push_back(e.getDER());
+    }
+
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_CERT),
+                                             commandId,
+                                             retCode,
+                                             chainRawVector);
     return response.Pop();
 }
 
-RawBuffer CKMLogic::createKeyPairECDSA(
+RawBuffer CKMLogic::getCertificateChain(
     Credentials &cred,
     int commandId,
-    int type,
-    const Alias &privateKeyAlias,
-    const Alias &publicKeyAlias,
-    PolicySerializable policyPrivateKey,
-    PolicySerializable policyPublicKey)
+    const RawBuffer &certificate,
+    const AliasVector &aliasVector)
 {
-    (void)cred;
-    (void)type;
-    (void)privateKeyAlias;
-    (void)publicKeyAlias,
-    (void)policyPrivateKey;
-    (void)policyPublicKey;
-    
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, static_cast<int>(KEY_MANAGER_API_SUCCESS));
+    int retCode = CKM_API_SUCCESS;
+    RawBufferVector chainRawVector;
+    try {
+        CertificateImpl cert(certificate, DataFormat::FORM_DER);
+        CertificateImplVector untrustedCertVector;
+        CertificateImplVector chainVector;
+        DBRow row;
+
+        if (cert.empty()) {
+            retCode = CKM_API_ERROR_SERVER_ERROR;
+            goto senderror;
+        }
+
+        for (auto &i: aliasVector) {
+            retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, Password(), row);
+
+            if (retCode != CKM_API_SUCCESS)
+                goto senderror;
+
+            untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
+        }
+
+        retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
+
+        if (retCode != CKM_API_SUCCESS)
+            goto senderror;
+
+        for (auto &i: chainVector)
+            chainRawVector.push_back(i.getDER());
+
+    } catch (const CryptoLogic::Exception::Base &e) {
+        LogError("DBCyptorModule 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());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (...) {
+        LogError("Unknown error.");
+    }
+
+senderror:
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
+                                             commandId,
+                                             retCode,
+                                             chainRawVector);
     return response.Pop();
 }
 
+RawBuffer CKMLogic::createSignature(
+        Credentials &cred,
+        int commandId,
+        const Alias &privateKeyAlias,
+        const Password &password,           // password for private_key
+        const RawBuffer &message,
+        const HashAlgorithm hash,
+        const RSAPaddingAlgorithm padding)
+{
+    DBRow row;
+    CryptoService cs;
+    RawBuffer signature;
+
+    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());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKM::Exception &e) {
+        LogError("Unknown CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    }
+
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
+                                             commandId,
+                                             retCode,
+                                             signature);
+    return response.Pop();
+}
+
+RawBuffer CKMLogic::verifySignature(
+        Credentials &cred,
+        int commandId,
+        const Alias &publicKeyOrCertAlias,
+        const Password &password,           // password for public_key (optional)
+        const RawBuffer &message,
+        const RawBuffer &signature,
+        const HashAlgorithm hash,
+        const RSAPaddingAlgorithm padding)
+{
+    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;
+            }
+
+            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());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKM::Exception &e) {
+        LogError("Unknown CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    }
+
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
+                                             commandId,
+                                             retCode);
+    return response.Pop();
+}
+
+RawBuffer CKMLogic::allowAccess(
+        Credentials &cred,
+        int command,
+        int msgID,
+        const Alias &item_alias,
+        const std::string &accessor_label,
+        const AccessRight req_rights)
+{
+    int retCode = CKM_API_ERROR_VERIFICATION_FAILED;
+
+    if (0 < m_userDataMap.count(cred.uid))
+    {
+        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;
+    }
+
+    return MessageBuffer::Serialize(command, msgID, retCode).Pop();
+}
+
+RawBuffer CKMLogic::denyAccess(
+        Credentials &cred,
+        int command,
+        int msgID,
+        const Alias &item_alias,
+        const std::string &accessor_label)
+{
+    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;
+    }
+
+    return MessageBuffer::Serialize(command, msgID, retCode).Pop();
+}
+
 } // namespace CKM