Add initial values support - values to feed the shared database on first startup.
[platform/core/security/key-manager.git] / src / manager / service / ckm-logic.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 3a58269..2f3c247
 #include <ckm/ckm-type.h>
 #include <key-provider.h>
 #include <file-system.h>
-#include <CryptoService.h>
 #include <ckm-logic.h>
-#include <generic-key.h>
+#include <key-impl.h>
+#include <certificate-config.h>
+#include <certificate-store.h>
+#include <dirent.h>
+#include <algorithm>
+#include <InitialValuesFile.h>
+
+#include <generic-backend/exception.h>
+#include <sw-backend/crypto-service.h>
 
 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          = "/opt/data/ckm/initial_values/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();
+
+    // make initial file list
+    std::vector<std::string> 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);
     }
 
-    if (CKM_API_SUCCESS != m_certStore.setSystemCertificateDir(CERT_SYSTEM_DIR)) {
-        LogError("Fatal error in CertificateStore::setSystemCertificateDir. Chain creation will not work");
+    // 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(){}
 
-SafeBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
-    // TODO try catch for all errors that should be supported by error code
+void CKMLogic::loadDKEKFile(uid_t user, const Password &password) {
+    auto &handle = m_userDataMap[user];
+
+    FileSystem fs(user);
+
+    auto wrappedDKEK = fs.getDKEK();
+
+    if (wrappedDKEK.empty()) {
+        wrappedDKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
+        fs.saveDKEK(wrappedDKEK);
+    }
+
+    handle.keyProvider = KeyProvider(wrappedDKEK, password);
+}
+
+void CKMLogic::saveDKEKFile(uid_t user, const Password &password) {
+    auto &handle = m_userDataMap[user];
+
+    FileSystem fs(user);
+    fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
+}
+
+int CKMLogic::unlockDatabase(uid_t user, const Password & password)
+{
+    if (0<m_userDataMap.count(user) && m_userDataMap[user].keyProvider.isInitialized())
+        return CKM_API_SUCCESS;
+
     int retCode = CKM_API_SUCCESS;
+    try
+    {
+        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.getDomainKEK();
-
-            if (wrappedDomainKEK.empty()) {
-                wrappedDomainKEK = KeyProvider::generateDomainKEK(std::to_string(user), password);
-                fs.saveDomainKEK(wrappedDomainKEK);
-            }
+        FileSystem fs(user);
+        loadDKEKFile(user, password);
+
+        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.keyProvider = KeyProvider(wrappedDomainKEK, password);
+        handle.database = DB::Crypto(fs.getDBPath(), key);
+        handle.crypto = CryptoLogic();
 
-            SafeBuffer key = handle.keyProvider.getPureDomainKEK();
-            handle.database = DBCrypto(fs.getDBPath(), key);
-            handle.crypto = CryptoLogic();
-            // TODO wipe key
+        if ( !m_accessControl.isSystemService(user) )
+        {
+            // remove data of removed apps during locked state
+            AppLabelVector removedApps = fs.clearRemovedsApps();
+            for(auto& appSmackLabel : removedApps) {
+                handle.crypto.removeKey(appSmackLabel);
+                handle.database.deleteKey(appSmackLabel);
+            }
         }
     } catch (const KeyProvider::Exception::PassWordError &e) {
         LogError("Incorrect Password " << e.GetMessage());
@@ -81,281 +171,743 @@ SafeBuffer CKMLogic::unlockUserKey(uid_t user, const std::string &password) {
     } catch (const CryptoLogic::Exception::Base &e) {
         LogError("CryptoLogic error: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("FileSystem error: " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
     } 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 (CKM_API_SUCCESS != retCode)
+        m_userDataMap.erase(user);
+
+    return retCode;
+}
+
+int CKMLogic::unlockSystemDB()
+{
+    return unlockDatabase(SYSTEM_DB_UID, SYSTEM_DB_PASSWD);
 }
 
-SafeBuffer CKMLogic::lockUserKey(uid_t user) {
+UserData & CKMLogic::selectDatabase(const Credentials &cred, const Label &incoming_label)
+{
+    // if user trying to access system service - check:
+    //    * if user database is unlocked [mandatory]
+    //    * if not - proceed with regular user database
+    //    * if explicit system database label given -> switch to system DB
+    if ( !m_accessControl.isSystemService(cred) )
+    {
+        if (0 == m_userDataMap.count(cred.clientUid))
+            ThrowMsg(Exception::DatabaseLocked, "database with UID: " << cred.clientUid << " locked");
+
+        if (0 != incoming_label.compare(LABEL_SYSTEM_DB))
+            return m_userDataMap[cred.clientUid];
+    }
+
+    // system database selected, modify the label
+    if (CKM_API_SUCCESS != unlockSystemDB() )
+        ThrowMsg(Exception::DatabaseLocked, "can not unlock system database");
+    return m_userDataMap[SYSTEM_DB_UID];
+}
+
+RawBuffer CKMLogic::unlockUserKey(uid_t user, const Password &password)
+{
     int retCode = CKM_API_SUCCESS;
-    // 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();
+    if( !m_accessControl.isSystemService(user) )
+    {
+        retCode = unlockDatabase(user, password);
+    }
+    else
+    {
+        // do not allow lock/unlock operations for system users
+        retCode = CKM_API_ERROR_INPUT_PARAM;
+    }
+
+    return MessageBuffer::Serialize(retCode).Pop();
 }
 
-SafeBuffer CKMLogic::removeUserData(uid_t user) {
+RawBuffer CKMLogic::updateCCMode() {
+    m_accessControl.updateCCMode();
+    return MessageBuffer::Serialize(CKM_API_SUCCESS).Pop();
+}
+
+RawBuffer CKMLogic::lockUserKey(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) )
+    {
+        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();
+
+}
+
+RawBuffer CKMLogic::removeUserData(uid_t user) {
+    int retCode = CKM_API_SUCCESS;
+
+    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();
 }
 
-SafeBuffer CKMLogic::changeUserPassword(
+int CKMLogic::changeUserPasswordHelper(uid_t user,
+                                       const Password &oldPassword,
+                                       const Password &newPassword)
+{
+    // do not allow to change system database password
+    if( m_accessControl.isSystemService(user) )
+        return CKM_API_ERROR_INPUT_PARAM;
+
+    loadDKEKFile(user, oldPassword);
+    saveDKEKFile(user, newPassword);
+
+    return CKM_API_SUCCESS;
+}
+
+RawBuffer CKMLogic::changeUserPassword(
     uid_t user,
-    const std::string &oldPassword,
-    const std::string &newPassword)
+    const Password &oldPassword,
+    const Password &newPassword)
 {
     int retCode = CKM_API_SUCCESS;
-    try {
-        FileSystem fs(user);
-        auto wrappedDomainKEK = fs.getDomainKEK();
-        if (wrappedDomainKEK.empty()) {
-            retCode = CKM_API_ERROR_BAD_REQUEST;
-        } else {
-            wrappedDomainKEK = KeyProvider::reencrypt(wrappedDomainKEK, oldPassword, newPassword);
-            fs.saveDomainKEK(wrappedDomainKEK);
-        }
+    try
+    {
+        retCode = changeUserPasswordHelper(user, oldPassword, newPassword);
     } 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 FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
     } catch (const CKM::Exception &e) {
         LogError("CKM::Exception: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, retCode);
-    return response.Pop();
+    return MessageBuffer::Serialize(retCode).Pop();
 }
 
-SafeBuffer CKMLogic::resetUserPassword(
+int CKMLogic::resetUserPasswordHelper(
     uid_t user,
-    const std::string &newPassword)
+    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.saveDomainKEK(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;
 }
 
-int CKMLogic::saveDataHelper(
-    Credentials &cred,
-    DBDataType dataType,
-    const Alias &alias,
-    const SafeBuffer &key,
-    const PolicySerializable &policy)
+RawBuffer CKMLogic::resetUserPassword(
+    uid_t user,
+    const Password &newPassword)
 {
-    if (0 == m_userDataMap.count(cred.uid))
-        return CKM_API_ERROR_DB_LOCKED;
+    int retCode = CKM_API_SUCCESS;
+    try {
+        retCode = resetUserPasswordHelper(user, newPassword);
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    }
+
+    return MessageBuffer::Serialize(retCode).Pop();
+}
+
+RawBuffer CKMLogic::removeApplicationData(const Label &smackLabel) {
+    int retCode = CKM_API_SUCCESS;
+
+    try {
 
-    DBRow row = { alias, cred.smackLabel, policy.restricted,
-         policy.extractable, dataType, DBCMAlgType::NONE,
-         0, SafeBuffer(), static_cast<int>(key.size()), key };
+        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.crypto.removeKey(smackLabel);
+                    handle.database.deleteKey(smackLabel);
+                }
+            }
+        }
+
+    } catch (const DB::Crypto::Exception::InternalError &e) {
+        LogError("DB::Crypto couldn't remove data: " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const DB::Crypto::Exception::TransactionError &e) {
+        LogError("DB::Crypto transaction failed with message " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    }
+
+    return MessageBuffer::Serialize(retCode).Pop();
+}
+
+int CKMLogic::checkSaveConditions(
+    const Credentials &cred,
+    UserData &handler,
+    const Name &name,
+    const Label &ownerLabel)
+{
+    // verify name and label are correct
+    if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
+        LogWarning("Invalid parameter passed to key-manager");
+        return CKM_API_ERROR_INPUT_PARAM;
+    }
 
-    auto &handler = m_userDataMap[cred.uid];
-    DBCrypto::Transaction transaction(&handler.database);
-    if (!handler.crypto.haveKey(cred.smackLabel)) {
-        SafeBuffer key;
-        auto key_optional = handler.database.getKey(cred.smackLabel);
+    // check if allowed to save using ownerLabel
+    int access_ec = m_accessControl.canSave(cred, ownerLabel);
+    if( access_ec != CKM_API_SUCCESS)
+    {
+        LogWarning("label " << cred.smackLabel << " can not save rows using label " << ownerLabel);
+        return access_ec;
+    }
+
+    // check if not a duplicate
+    if( handler.database.isNameLabelPresent(name, 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);
+        got_key = handler.keyProvider.getPureDEK(got_key);
+        handler.crypto.pushKey(ownerLabel, got_key);
     }
-    handler.crypto.encryptRow(policy.password, row);
-    handler.database.saveDBRow(row);
-    transaction.commit();
+
     return CKM_API_SUCCESS;
 }
 
-SafeBuffer CKMLogic::saveData(
-    Credentials &cred,
-    int commandId,
-    DBDataType dataType,
-    const Alias &alias,
-    const SafeBuffer &key,
+DB::Row CKMLogic::createEncryptedRow(
+    CryptoLogic &crypto,
+    const Name &name,
+    const Label &label,
+    DataType dataType,
+    const RawBuffer &data,
+    const Policy &policy) const
+{
+    DB::Row row(name, label, static_cast<int>(policy.extractable), dataType, data, static_cast<int>(data.size()));
+    row.backendId = m_decider.chooseCryptoBackend(dataType, policy);
+
+    // do not encrypt data with password during cc_mode on
+    if(m_accessControl.isCCMode()) {
+        crypto.encryptRow("", row);
+    } else {
+        crypto.encryptRow(policy.password, row);
+    }
+    return row;
+}
+
+int CKMLogic::verifyBinaryData(DataType dataType, RawBuffer &input_data) const
+{
+    RawBuffer dummy;
+    return toBinaryData(dataType, input_data, dummy);
+}
+
+int CKMLogic::toBinaryData(DataType dataType,
+                           const RawBuffer &input_data,
+                           RawBuffer &output_data) const
+{
+    // verify the data integrity
+    if (dataType.isKey())
+    {
+        KeyShPtr output_key = CKM::Key::create(input_data);
+        if(output_key.get() == NULL)
+        {
+            LogError("provided binary data is not valid key data");
+            return CKM_API_ERROR_INPUT_PARAM;
+        }
+        output_data = output_key->getDER();
+    }
+    else if (dataType.isCertificate() || dataType.isChainCert())
+    {
+        CertificateShPtr cert = CKM::Certificate::create(input_data, DataFormat::FORM_DER);
+        if(cert.get() == NULL)
+        {
+            LogError("provided binary data is not valid certificate data");
+            return CKM_API_ERROR_INPUT_PARAM;
+        }
+        output_data = cert->getDER();
+    }
+    else
+        output_data = input_data;
+    // TODO: add here BINARY_DATA verification, i.e: max size etc.
+    return CKM_API_SUCCESS;
+}
+
+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;
+    int retCode = CKM_API_ERROR_UNKNOWN;
+
     try {
-        retCode = saveDataHelper(cred, dataType, alias, key, policy);
-        LogDebug("SaveDataHelper returned: " << retCode);
+        // check if data is correct
+        RawBuffer binaryData;
+        retCode = toBinaryData(dataType, data, binaryData);
+        if(retCode == CKM_API_SUCCESS)
+        {
+            retCode = saveDataHelper(cred, name, label, dataType, binaryData, policy);
+        }
     } catch (const KeyProvider::Exception::Base &e) {
         LogError("KeyProvider failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
     } catch (const CryptoLogic::Exception::Base &e) {
         LogError("CryptoLogic failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const DBCrypto::Exception::InternalError &e) {
-        LogError("DBCrypto failed with message: " << e.GetMessage());
+    } catch (const DB::Crypto::Exception::InternalError &e) {
+        LogError("DB::Crypto 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());
+    } catch (const DB::Crypto::Exception::TransactionError &e) {
+        LogError("DB::Crypto transaction failed with message " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const FileSystem::Exception::Base &e) {
+        LogError("Error in FileSystem " << e.GetMessage());
+        retCode = CKM_API_ERROR_FILE_SYSTEM;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
+    return retCode;
+}
 
-    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));
-
+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<int>(LogicCommand::SAVE),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(dataType));
     return response.Pop();
 }
 
-SafeBuffer CKMLogic::removeData(
-    Credentials &cred,
-    int commandId,
-    DBDataType dataType,
-    const Alias &alias)
+int CKMLogic::extractPKCS12Data(
+    CryptoLogic &crypto,
+    const Name &name,
+    const Label &ownerLabel,
+    const PKCS12Serializable &pkcs,
+    const PolicySerializable &keyPolicy,
+    const PolicySerializable &certPolicy,
+    DB::RowVector &output) const
 {
-    int retCode = CKM_API_SUCCESS;
+    // 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));
 
-    if (0 < m_userDataMap.count(cred.uid)) {
-       // check if the data exists or not
-        DBCrypto::DBRowOptional row_optional;
-        if (dataType == DBDataType::CERTIFICATE || dataType == DBDataType::BINARY_DATA) {
-            row_optional = m_userDataMap[cred.uid].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)))
-        {
-            row_optional = m_userDataMap[cred.uid].database.getKeyDBRow(alias, cred.smackLabel);
-        } else {
-            LogError("Unknown type of requested data" << (int)dataType);
-            retCode = CKM_API_ERROR_BAD_REQUEST;
-        }
-        if(!row_optional) {
-            LogError("No row for given alias, label and type");
-            retCode = CKM_API_ERROR_DB_ALIAS_UNKNOWN;
-        }
+    // 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;
 
-        // remove if the data exists
-        if(retCode == CKM_API_SUCCESS) {
-            Try {
-                m_userDataMap[cred.uid].database.deleteDBRow(alias, cred.smackLabel);
-            } Catch (CKM::Exception) {
-                LogError("Error in deleting row!");
-                retCode = CKM_API_ERROR_DB_ERROR;
-            }
-        }
-    } else {
-        retCode = CKM_API_ERROR_DB_LOCKED;
+        output.push_back(createEncryptedRow(crypto, name, ownerLabel, chainDataType, caCertData, certPolicy));
     }
 
-    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));
+    return CKM_API_SUCCESS;
+}
+
+RawBuffer CKMLogic::savePKCS12(
+    const Credentials &cred,
+    int commandId,
+    const Name &name,
+    const Label &label,
+    const PKCS12Serializable &pkcs,
+    const PolicySerializable &keyPolicy,
+    const PolicySerializable &certPolicy)
+{
+    int retCode = CKM_API_ERROR_UNKNOWN;
+    try {
+        retCode = saveDataHelper(cred, name, label, pkcs, keyPolicy, certPolicy);
+    } catch (const KeyProvider::Exception::Base &e) {
+        LogError("KeyProvider failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const CryptoLogic::Exception::Base &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const DB::Crypto::Exception::InternalError &e) {
+        LogError("DB::Crypto failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const DB::Crypto::Exception::TransactionError &e) {
+        LogError("DB::Crypto transaction failed with message " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    }
 
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::SAVE_PKCS12),
+                                             commandId,
+                                             retCode);
     return response.Pop();
 }
 
-int CKMLogic::getDataHelper(
-    Credentials &cred,
-    DBDataType dataType,
-    const Alias &alias,
-    const std::string &password,
-    DBRow &row)
+
+int CKMLogic::removeDataHelper(
+        const Credentials &cred,
+        const Name &name,
+        const Label &label)
+{
+    auto &handler = selectDatabase(cred, label);
+
+    // use client label if not explicitly provided
+    const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
+    if (!isNameValid(name) || !isLabelValid(ownerLabel)) {
+        LogError("Invalid label or name format");
+        return CKM_API_ERROR_INPUT_PARAM;
+    }
+
+    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)
+    {
+        LogWarning("access control check result: " << retCode);
+        return retCode;
+    }
+
+    auto erased = handler.database.deleteRow(name, ownerLabel);
+    // check if the data existed or not
+    if(erased)
+        transaction.commit();
+    else {
+        LogError("No row for given name and label");
+        return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+    }
+
+    return CKM_API_SUCCESS;
+}
+
+RawBuffer CKMLogic::removeData(
+    const Credentials &cred,
+    int commandId,
+    const Name &name,
+    const Label &label)
 {
+    int retCode = CKM_API_ERROR_UNKNOWN;
 
-    if (0 == m_userDataMap.count(cred.uid))
-        return CKM_API_ERROR_DB_LOCKED;
+    try
+    {
+        retCode = removeDataHelper(cred, name, label);
+    }
+    catch (const CKMLogic::Exception::DatabaseLocked &e)
+    {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    }
+    catch (const CKM::Exception &)
+    {
+        LogError("Error in deleting row!");
+        retCode = CKM_API_ERROR_DB_ERROR;
+    }
 
-    auto &handler = m_userDataMap[cred.uid];
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::REMOVE),
+                                             commandId,
+                                             retCode);
+    return response.Pop();
+}
 
-    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<int>(dataType) >= static_cast<int>(DBDataType::DB_KEY_FIRST))
-            && (static_cast<int>(dataType) <= static_cast<int>(DBDataType::DB_KEY_LAST)))
+int CKMLogic::readSingleRow(const Name &name,
+                            const Label &ownerLabel,
+                            DataType dataType,
+                            DB::Crypto & database,
+                            DB::Row &row)
+{
+    DB::Crypto::RowOptional row_optional;
+    if (dataType.isKey())
     {
-        row_optional = handler.database.getKeyDBRow(alias, cred.smackLabel);
+        // read all key types
+        row_optional = database.getRow(name,
+                                         ownerLabel,
+                                         DataType::DB_KEY_FIRST,
+                                         DataType::DB_KEY_LAST);
     } else {
-        LogError("Unknown type of requested data" << (int)dataType);
-        return CKM_API_ERROR_BAD_REQUEST;
+        // read anything else
+        row_optional = database.getRow(name,
+                                         ownerLabel,
+                                         dataType);
     }
+
     if(!row_optional) {
-        LogError("No row for given alias, label and type");
+        LogError("No row for given name, label and type");
         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
     } else {
         row = *row_optional;
     }
 
-    if (!handler.crypto.haveKey(row.smackLabel)) {
-        SafeBuffer key;
-        auto key_optional = handler.database.getKey(row.smackLabel);
+    return CKM_API_SUCCESS;
+}
+
+
+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(!output.size()) {
+        LogError("No row for given name, label and type");
+        return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+    }
+
+    return CKM_API_SUCCESS;
+}
+
+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));
+}
+
+int CKMLogic::readDataHelper(
+    bool exportFlag,
+    const Credentials &cred,
+    DataType dataType,
+    const Name &name,
+    const Label &label,
+    const Password &password,
+    DB::RowVector &rows)
+{
+    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);
+    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;
+
+    // decrypt row
+    if (!handler.crypto.haveKey(firstRow.ownerLabel)) {
+        RawBuffer key;
+        auto key_optional = handler.database.getKey(firstRow.ownerLabel);
+        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(firstRow.ownerLabel, key);
+    }
+    for(auto &row : rows)
+        handler.crypto.decryptRow(password, row);
+
+    return CKM_API_SUCCESS;
+}
+
+int CKMLogic::readDataHelper(
+    bool exportFlag,
+    const Credentials &cred,
+    DataType dataType,
+    const Name &name,
+    const Label &label,
+    const Password &password,
+    DB::Row &row)
+{
+    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);
+    int retCode = readSingleRow(name, ownerLabel, dataType, handler.database, row);
+    if(CKM_API_SUCCESS != retCode)
+        return retCode;
+
+    // check access rights
+    retCode = checkDataPermissionsHelper(cred, name, ownerLabel, cred.smackLabel, row, exportFlag, handler.database);
+    if(CKM_API_SUCCESS != retCode)
+        return retCode;
+
+    // decrypt row
+    if (!handler.crypto.haveKey(row.ownerLabel)) {
+        RawBuffer key;
+        auto key_optional = handler.database.getKey(row.ownerLabel);
         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.pushKey(row.ownerLabel, key);
     }
     handler.crypto.decryptRow(password, row);
 
     return CKM_API_SUCCESS;
 }
 
-SafeBuffer CKMLogic::getData(
-    Credentials &cred,
+RawBuffer CKMLogic::getData(
+    const Credentials &cred,
     int commandId,
-    DBDataType dataType,
-    const Alias &alias,
-    const std::string &password)
+    DataType dataType,
+    const Name &name,
+    const Label &label,
+    const Password &password)
 {
     int retCode = CKM_API_SUCCESS;
-    DBRow row;
+    DB::Row row;
 
     try {
-        retCode = getDataHelper(cred, dataType, alias, password, row);
+        retCode = readDataHelper(true, cred, dataType, name, label, 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::DecryptDBRowError &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
     } catch (const CryptoLogic::Exception::Base &e) {
         LogError("CryptoLogic failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const DBCrypto::Exception::Base &e) {
-        LogError("DBCrypto failed with message: " << e.GetMessage());
+    } catch (const DB::Crypto::Exception::Base &e) {
+        LogError("DB::Crypto failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
     if (CKM_API_SUCCESS != retCode) {
@@ -363,428 +915,760 @@ SafeBuffer CKMLogic::getData(
         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);
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(row.dataType),
+                                             row.data);
     return response.Pop();
 }
 
-SafeBuffer CKMLogic::getDataList(
-    Credentials &cred,
-    int commandId,
-    DBDataType dataType)
+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 = CKM_API_SUCCESS;
-    AliasVector aliasVector;
+    int retCode;
+
+    // read private key (mandatory)
+    DB::Row privKeyRow;
+    retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, label, keyPassword, privKeyRow);
+    if(retCode != CKM_API_SUCCESS)
+        return retCode;
+    privKey = CKM::Key::create(privKeyRow.data);
+
+    // read certificate (mandatory)
+    DB::Row certRow;
+    retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, label, certPassword, certRow);
+    if(retCode != CKM_API_SUCCESS)
+        return retCode;
+    cert = CKM::Certificate::create(certRow.data, DataFormat::FORM_DER);
+
+    // read CA cert chain (optional)
+    DB::RowVector rawCaChain;
+    retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, label, certPassword, rawCaChain);
+    if(retCode != CKM_API_SUCCESS &&
+       retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+        return retCode;
+    for(auto &rawCaCert : rawCaChain)
+        caChain.push_back(CKM::Certificate::create(rawCaCert.data, 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 KeyProvider::Exception::Base &e) {
+        LogError("KeyProvider failed with error: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
+    } catch (const CryptoLogic::Exception::Base &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const DB::Crypto::Exception::Base &e) {
+        LogError("DB::Crypto failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
+    }
+
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_PKCS12),
+                                             commandId,
+                                             retCode,
+                                             output);
+    return response.Pop();
+}
+
+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;
 
-    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, cred.smackLabel, aliasVector);
+            LabelNameVector tmpVector;
+            if (dataType.isKey()) {
+                // list all key types
+                database.listNames(cred.smackLabel,
+                                   tmpVector,
+                                   DataType::DB_KEY_FIRST,
+                                   DataType::DB_KEY_LAST);
             } else {
-                handler.database.getKeyAliases(cred.smackLabel, aliasVector);
+                // list anything else
+                database.listNames(cred.smackLabel,
+                                   tmpVector,
+                                   dataType);
             }
-        } Catch (CKM::Exception) {
-            LogError("Failed to get aliases");
+            labelNameVector.insert(labelNameVector.end(), tmpVector.begin(), tmpVector.end());
+            retCode = CKM_API_SUCCESS;
+        }
+        Catch (CKM::Exception) {
+            LogError("Failed to get names");
             retCode = CKM_API_ERROR_DB_ERROR;
         }
-    } else {
-        retCode = CKM_API_ERROR_DB_LOCKED;
     }
-
-    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);
-    return response.Pop();
+    return retCode;
 }
 
-int CKMLogic::createKeyPairRSAHelper(
-    Credentials &cred,
-    int size,
-    const Alias &aliasPrivate,
-    const Alias &aliasPublic,
-    const PolicySerializable &policyPrivate,
-    const PolicySerializable &policyPublic)
+RawBuffer CKMLogic::getDataList(
+    const Credentials &cred,
+    int commandId,
+    DataType dataType)
 {
-    if (0 >= m_userDataMap.count(cred.uid))
-        return CKM_API_ERROR_DB_LOCKED;
-
-    auto &handler = m_userDataMap[cred.uid];
-    GenericKey prv, pub;
-    int retCode;
+    LabelNameVector systemVector;
+    LabelNameVector userVector;
+    LabelNameVector labelNameVector;
 
-    if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
-        (retCode = CryptoService::createKeyPairRSA(size, prv, pub)))
+    int retCode = unlockSystemDB();
+    if (CKM_API_SUCCESS == retCode)
     {
-        LogDebug("CryptoService error with code: " << retCode);
-        return CKM_API_ERROR_SERVER_ERROR; // TODO error code
+        // system database
+        if (m_accessControl.isSystemService(cred))
+        {
+            // lookup system DB
+            retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
+                                                    LABEL_SYSTEM_DB),
+                                        dataType,
+                                        systemVector);
+        }
+        else
+        {
+            // user - lookup system, then client DB
+            retCode = getDataListHelper(Credentials(SYSTEM_DB_UID,
+                                                    cred.smackLabel),
+                                        dataType,
+                                        systemVector);
+
+            // private database
+            if(retCode == CKM_API_SUCCESS)
+            {
+                retCode = getDataListHelper(cred,
+                                            dataType,
+                                            userVector);
+            }
+        }
     }
 
-    DBCrypto::Transaction transaction(&handler.database);
-    retCode = saveDataHelper(cred,
-                            toDBDataType(prv.getType()),
-                            aliasPrivate,
-                            prv.getDERSB(),
-                            policyPrivate);
+    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<int>(LogicCommand::GET_LIST),
+                                             commandId,
+                                             retCode,
+                                             static_cast<int>(dataType),
+                                             labelNameVector);
+    return response.Pop();
+}
 
-    if (CKM_API_SUCCESS != retCode)
-        return retCode;
+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);
 
-    retCode = saveDataHelper(cred,
-                            toDBDataType(pub.getType()),
-                            aliasPublic,
-                            pub.getDERSB(),
-                            policyPublic);
+    // use client label if not explicitly provided
+    const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
+    if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
+        return CKM_API_ERROR_INPUT_PARAM;
 
-    if (CKM_API_SUCCESS != retCode)
+    // 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;
 
-    transaction.commit();
+    // save the data
+    DB::Row encryptedRow = createEncryptedRow(handler.crypto, name, ownerLabel, dataType, data, policy);
+    handler.database.saveRow(encryptedRow);
 
-    return retCode;
+    transaction.commit();
+    return CKM_API_SUCCESS;
 }
 
-SafeBuffer CKMLogic::createKeyPairRSA(
-    Credentials &cred,
-    int commandId,
-    int size,
-    const Alias &aliasPrivate,
-    const Alias &aliasPublic,
-    const PolicySerializable &policyPrivate,
-    const PolicySerializable &policyPublic)
+int CKMLogic::saveDataHelper(
+    const Credentials &cred,
+    const Name &name,
+    const Label &label,
+    const PKCS12Serializable &pkcs,
+    const PolicySerializable &keyPolicy,
+    const PolicySerializable &certPolicy)
 {
-    int retCode = CKM_API_SUCCESS;
+    auto &handler = selectDatabase(cred, label);
 
-    try {
-        retCode = createKeyPairRSAHelper(
-                        cred,
-                        size,
-                        aliasPrivate,
-                        aliasPublic,
-                        policyPrivate,
-                        policyPublic);
+    // use client label if not explicitly provided
+    const Label &ownerLabel = label.empty() ? cred.smackLabel : label;
+    if( m_accessControl.isSystemService(cred) && ownerLabel.compare(LABEL_SYSTEM_DB)!=0)
+        return CKM_API_ERROR_INPUT_PARAM;
 
-    } 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;
-    }
+    // 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;
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, 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;
 
-    return response.Pop();
+    // save the data
+    handler.database.saveRows(name, ownerLabel, encryptedRows);
+    transaction.commit();
+
+    return CKM_API_SUCCESS;
 }
 
-int CKMLogic::createKeyPairECDSAHelper(
-    Credentials &cred,
-    int type,
-    const Alias &aliasPrivate,
-    const Alias &aliasPublic,
+
+int CKMLogic::createKeyPairHelper(
+    const Credentials &cred,
+    const KeyType key_type,
+    const int additional_param,
+    const Name &namePrivate,
+    const Label &labelPrivate,
+    const Name &namePublic,
+    const Label &labelPublic,
     const PolicySerializable &policyPrivate,
     const PolicySerializable &policyPublic)
 {
-    if (0 >= m_userDataMap.count(cred.uid))
-        return CKM_API_ERROR_DB_LOCKED;
+    auto &handlerPriv = selectDatabase(cred, labelPrivate);
+    auto &handlerPub = selectDatabase(cred, labelPublic);
+
 
-    auto &handler = m_userDataMap[cred.uid];
-    GenericKey prv, pub;
     int retCode;
+    KeyImpl prv, pub;
+    switch(key_type)
+    {
+        case KeyType::KEY_RSA_PUBLIC:
+        case KeyType::KEY_RSA_PRIVATE:
+            retCode = Crypto::SW::CryptoService::createKeyPairRSA(additional_param, prv, pub);
+            break;
+
+        case KeyType::KEY_DSA_PUBLIC:
+        case KeyType::KEY_DSA_PRIVATE:
+            retCode = Crypto::SW::CryptoService::createKeyPairDSA(additional_param, prv, pub);
+            break;
+
+        case KeyType::KEY_ECDSA_PUBLIC:
+        case KeyType::KEY_ECDSA_PRIVATE:
+            retCode = Crypto::SW::CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(additional_param), prv, pub);
+            break;
+
+        default:
+            return CKM_API_ERROR_INPUT_PARAM;
+    }
 
-    if (CKM_CRYPTO_CREATEKEY_SUCCESS !=
-        (retCode = CryptoService::createKeyPairECDSA(static_cast<ElipticCurve>(type), prv, pub)))
+    if (CKM_CRYPTO_CREATEKEY_SUCCESS != retCode)
     {
-        LogError("CryptoService failed with code: " << retCode);
+        LogDebug("CryptoService error with code: " << retCode);
         return CKM_API_ERROR_SERVER_ERROR; // TODO error code
     }
 
-    DBCrypto::Transaction transaction(&handler.database);
+    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);
 
     retCode = saveDataHelper(cred,
-                            toDBDataType(prv.getType()),
-                            aliasPrivate,
-                            prv.getDERSB(),
-                            policyPrivate);
-
+                             namePrivate,
+                             labelPrivate,
+                             DataType(prv.getType()),
+                             prv.getDER(),
+                             policyPrivate);
     if (CKM_API_SUCCESS != retCode)
         return retCode;
 
     retCode = saveDataHelper(cred,
-                            toDBDataType(pub.getType()),
-                            aliasPublic,
-                            pub.getDERSB(),
-                            policyPublic);
-
+                             namePublic,
+                             labelPublic,
+                             DataType(pub.getType()),
+                             pub.getDER(),
+                             policyPublic);
     if (CKM_API_SUCCESS != retCode)
         return retCode;
 
-    transaction.commit();
+    transactionPub.commit();
+    transactionPriv.commit();
 
     return retCode;
 }
 
-SafeBuffer CKMLogic::createKeyPairECDSA(
-    Credentials &cred,
+RawBuffer CKMLogic::createKeyPair(
+    const Credentials &cred,
+    LogicCommand protocol_cmd,
     int commandId,
-    int type,
-    const Alias &aliasPrivate,
-    const Alias &aliasPublic,
+    const int additional_param,
+    const Name &namePrivate,
+    const Label &labelPrivate,
+    const Name &namePublic,
+    const Label &labelPublic,
     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 = createKeyPairECDSAHelper(
+        retCode = createKeyPairHelper(
                         cred,
-                        type,
-                        aliasPrivate,
-                        aliasPublic,
+                        key_type,
+                        additional_param,
+                        namePrivate,
+                        labelPrivate,
+                        namePublic,
+                        labelPublic,
                         policyPrivate,
                         policyPublic);
-    } catch (const DBCrypto::Exception::AliasExists &e) {
-        LogDebug("DBCrypto error: alias exists: " << e.GetMessage());
-        retCode = CKM_API_ERROR_DB_ALIAS_EXISTS;
-    } catch (const DBCrypto::Exception::TransactionError &e) {
-        LogDebug("DBCrypto error: transaction error: " << e.GetMessage());
+    } catch (DB::Crypto::Exception::TransactionError &e) {
+        LogDebug("DB::Crypto error: transaction error: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
-    } catch (const CKM::CryptoLogic::Exception::Base &e) {
+    } catch (CKM::CryptoLogic::Exception::Base &e) {
         LogDebug("CryptoLogic error: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const DBCrypto::Exception::InternalError &e) {
-        LogDebug("DBCrypto internal error: " << e.GetMessage());
+    } catch (DB::Crypto::Exception::InternalError &e) {
+        LogDebug("DB::Crypto internal error: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } catch (const CKM::Exception &e) {
+        LogError("CKM::Exception: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_KEY_PAIR_RSA));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-
-    return response.Pop();
+    return MessageBuffer::Serialize(static_cast<int>(protocol_cmd), commandId, retCode).Pop();
 }
 
-SafeBuffer CKMLogic::getCertificateChain(
-    Credentials &cred,
-    int commandId,
-    const SafeBuffer &certificate,
-    const SafeBufferVector &untrustedRawCertVector)
+int CKMLogic::readCertificateHelper(
+        const Credentials &cred,
+        const LabelNameVector &labelNameVector,
+        CertificateImplVector &certVector)
 {
-    (void)cred;
+    DB::Row row;
+    for (auto &i: labelNameVector) {
+        int ec = readDataHelper(false, cred, DataType::CERTIFICATE, i.second, i.first, Password(), row);
+        if (ec != CKM_API_SUCCESS)
+            return ec;
+        certVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
+
+        // try to read chain certificates (if present)
+        DB::RowVector rawCaChain;
+        ec = readDataHelper(false, cred, DataType::DB_CHAIN_FIRST, i.second, i.first, CKM::Password(), rawCaChain);
+        if(ec != CKM_API_SUCCESS && ec != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+            return ec;
+        for(auto &rawCaCert : rawCaChain)
+            certVector.push_back(CertificateImpl(rawCaCert.data, DataFormat::FORM_DER));
+    }
+    return CKM_API_SUCCESS;
+}
 
-    CertificateImpl cert(certificate, DataFormat::FORM_DER);
+int CKMLogic::getCertificateChainHelper(
+        const CertificateImpl &cert,
+        const RawBufferVector &untrustedCertificates,
+        const RawBufferVector &trustedCertificates,
+        bool useTrustedSystemCertificates,
+        RawBufferVector &chainRawVector)
+{
     CertificateImplVector untrustedCertVector;
+    CertificateImplVector trustedCertVector;
     CertificateImplVector chainVector;
-    SafeBufferVector chainRawVector;
-
-    for (auto &e: untrustedRawCertVector)
-        untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
 
-    LogDebug("Cert is empty: " << cert.empty());
+    if (cert.empty())
+        return CKM_API_ERROR_INPUT_PARAM;
 
-    int retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
-
-    if (retCode == CKM_API_SUCCESS) {
-        for (auto &e : chainVector)
-            chainRawVector.push_back(e.getDERSB());
-    }
+    for (auto &e: untrustedCertificates)
+        untrustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
+    for (auto &e: trustedCertificates)
+        trustedCertVector.push_back(CertificateImpl(e, DataFormat::FORM_DER));
+
+    CertificateStore store;
+    int retCode = store.verifyCertificate(cert,
+                                          untrustedCertVector,
+                                          trustedCertVector,
+                                          useTrustedSystemCertificates,
+                                          m_accessControl.isCCMode(),
+                                          chainVector);
+    if (retCode != CKM_API_SUCCESS)
+        return retCode;
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_CERT));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, chainRawVector);
-    return response.Pop();
+    for (auto &e : chainVector)
+        chainRawVector.push_back(e.getDER());
+    return CKM_API_SUCCESS;
 }
 
-SafeBuffer CKMLogic::getCertificateChain(
-    Credentials &cred,
-    int commandId,
-    const SafeBuffer &certificate,
-    const AliasVector &aliasVector)
+int CKMLogic::getCertificateChainHelper(
+        const Credentials &cred,
+        const CertificateImpl &cert,
+        const LabelNameVector &untrusted,
+        const LabelNameVector &trusted,
+        bool useTrustedSystemCertificates,
+        RawBufferVector &chainRawVector)
 {
-    int retCode = CKM_API_SUCCESS;
-    SafeBufferVector 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;
-        }
+    CertificateImplVector untrustedCertVector;
+    CertificateImplVector trustedCertVector;
+    CertificateImplVector chainVector;
+    DB::Row row;
 
-        for (auto &i: aliasVector) {
-            retCode = getDataHelper(cred, DBDataType::CERTIFICATE, i, std::string(), row);
+    if (cert.empty())
+        return CKM_API_ERROR_INPUT_PARAM;
 
-            if (retCode != CKM_API_SUCCESS)
-                goto senderror;
+    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;
 
-            untrustedCertVector.push_back(CertificateImpl(row.data, DataFormat::FORM_DER));
-        }
+    CertificateStore store;
+    retCode = store.verifyCertificate(cert,
+                                      untrustedCertVector,
+                                      trustedCertVector,
+                                      useTrustedSystemCertificates,
+                                      m_accessControl.isCCMode(),
+                                      chainVector);
+    if (retCode != CKM_API_SUCCESS)
+        return retCode;
 
-        retCode = m_certStore.verifyCertificate(cert, untrustedCertVector, chainVector);
+    for (auto &i: chainVector)
+        chainRawVector.push_back(i.getDER());
 
-        if (retCode != CKM_API_SUCCESS)
-            goto senderror;
+    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 CryptoLogic::Exception::Base &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_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.");
+    }
 
-        for (auto &i: chainVector)
-            chainRawVector.push_back(i.getDERSB());
+    auto response = MessageBuffer::Serialize(static_cast<int>(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 CryptoLogic::Exception::DecryptDBRowError &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
     } catch (const CryptoLogic::Exception::Base &e) {
-        LogError("DBCyptorModule failed with message: " << e.GetMessage());
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const DBCrypto::Exception::Base &e) {
-        LogError("DBCrypto failed with message: " << e.GetMessage());
+    } catch (const DB::Crypto::Exception::Base &e) {
+        LogError("DB::Crypto failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } catch (const std::exception& e) {
+        LogError("STD exception " << e.what());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     } catch (...) {
         LogError("Unknown error.");
     }
 
-senderror:
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::GET_CHAIN_ALIAS));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, chainRawVector);
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::GET_CHAIN_ALIAS),
+                                             commandId,
+                                             retCode,
+                                             chainRawVector);
     return response.Pop();
 }
 
-SafeBuffer CKMLogic::createSignature(
-        Credentials &cred,
+RawBuffer CKMLogic::createSignature(
+        const Credentials &cred,
         int commandId,
-        const Alias &privateKeyAlias,
-        const std::string &password,           // password for private_key
-        const SafeBuffer &message,
+        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;
-    SafeBuffer signature;
+    DB::Row row;
+    RawBuffer signature;
+    CryptoAlgorithm cryptoAlg;
+    cryptoAlg.addParam(ParamName::SV_HASH_ALGO, hash);
+    cryptoAlg.addParam(ParamName::SV_RSA_PADDING, padding);
 
     int retCode = CKM_API_SUCCESS;
 
     try {
-        do {
-            retCode = getDataHelper(cred, DBDataType::KEY_RSA_PUBLIC, privateKeyAlias, password, row);
-            if (CKM_API_SUCCESS != retCode) {
-                LogError("getDataHelper return error");
-                break;
-            }
-
-            GenericKey keyParsed(row.data, std::string());
-            if (keyParsed.empty())
-                retCode = CKM_API_ERROR_SERVER_ERROR;
-            else
-                cs.createSignature(keyParsed, message, hash, padding, signature);
-        } while(0);
+        retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName, ownerLabel, password, row);
+        if(retCode == CKM_API_SUCCESS) {
+            signature = m_decider.getStore(row).getKey(row)->sign(cryptoAlg, message);
+        }
     } catch (const KeyProvider::Exception::Base &e) {
         LogError("KeyProvider failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
+    } catch (const CryptoLogic::Exception::DecryptDBRowError &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
     } catch (const CryptoLogic::Exception::Base &e) {
         LogError("CryptoLogic failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const DBCrypto::Exception::Base &e) {
-        LogError("DBCrypto failed with message: " << e.GetMessage());
+    } catch (const DB::Crypto::Exception::Base &e) {
+        LogError("DB::Crypto failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } catch (const CKM::Crypto::Exception::InputParam &e) {
+        LogError("CKM::Crypto failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_INPUT_PARAM;
+    } catch (const CKM::Crypto::Exception::Base &e) {
+        LogError("CKM::Crypto failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_SERVER_ERROR;
     } catch (const CKM::Exception &e) {
         LogError("Unknown CKM::Exception: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::CREATE_SIGNATURE));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-    Serialization::Serialize(response, signature);
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::CREATE_SIGNATURE),
+                                             commandId,
+                                             retCode,
+                                             signature);
     return response.Pop();
 }
 
-SafeBuffer CKMLogic::verifySignature(
-        Credentials &cred,
+RawBuffer CKMLogic::verifySignature(
+        const Credentials &cred,
         int commandId,
-        const Alias &publicKeyOrCertAlias,
-        const std::string &password,           // password for public_key (optional)
-        const SafeBuffer &message,
-        const SafeBuffer &signature,
+        const Name &publicKeyOrCertName,
+        const Label & ownerLabel,
+        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;
-            GenericKey key;
-
-            retCode = getDataHelper(cred, DBDataType::DB_KEY_FIRST, publicKeyOrCertAlias, password, row);
-
-            if (retCode == CKM_API_SUCCESS) {
-                key = GenericKey(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.getGenericKey();
-            } else {
-                break;
-            }
-
-            if (key.empty()) {
-                retCode = CKM_API_ERROR_SERVER_ERROR;
-                break;
-            }
+        DB::Row row;
+        KeyImpl key;
+
+        CryptoAlgorithm params;
+        params.addParam(ParamName::SV_HASH_ALGO, hash);
+        params.addParam(ParamName::SV_RSA_PADDING, padding);
+
+        // try certificate first - looking for a public key.
+        // in case of PKCS, pub key from certificate will be found first
+        // rather than private key from the same PKCS.
+        retCode = readDataHelper(false, cred, DataType::CERTIFICATE, publicKeyOrCertName, ownerLabel, password, row);
+        if (retCode == CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
+            retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, publicKeyOrCertName, ownerLabel, password, row);
+        }
 
-            retCode = cs.verifySignature(key, message, signature, hash, padding);
-        } while(0);
-    } catch (const CryptoService::Exception::Crypto_internal &e) {
+        if (retCode == CKM_API_SUCCESS) {
+            retCode = m_decider.getStore(row).getKey(row)->verify(params, message, signature);
+        }
+    } catch (const Crypto::SW::CryptoService::Exception::Crypto_internal &e) {
         LogError("KeyProvider failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const CryptoService::Exception::opensslError &e) {
+    } catch (const Crypto::SW::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::DecryptDBRowError &e) {
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
+        retCode = CKM_API_ERROR_AUTHENTICATION_FAILED;
     } catch (const CryptoLogic::Exception::Base &e) {
         LogError("CryptoLogic failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
-    } catch (const DBCrypto::Exception::Base &e) {
-        LogError("DBCrypto failed with message: " << e.GetMessage());
+    } catch (const DB::Crypto::Exception::Base &e) {
+        LogError("DB::Crypto failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_DB_ERROR;
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
     } catch (const CKM::Exception &e) {
         LogError("Unknown CKM::Exception: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
     }
 
-    MessageBuffer response;
-    Serialization::Serialize(response, static_cast<int>(LogicCommand::VERIFY_SIGNATURE));
-    Serialization::Serialize(response, commandId);
-    Serialization::Serialize(response, retCode);
-
+    auto response = MessageBuffer::Serialize(static_cast<int>(LogicCommand::VERIFY_SIGNATURE),
+                                             commandId,
+                                             retCode);
     return response.Pop();
 }
+
+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)
+{
+    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(LABEL_SYSTEM_DB)) &&
+        (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( !handler.database.isNameLabelPresent(name, ownerLabel) )
+        return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+
+    // removing non-existing permissions: fail
+    if(permissionMask == Permission::NONE)
+    {
+        if(!handler.database.getPermissionRow(name, ownerLabel, accessorLabel))
+            return CKM_API_ERROR_INPUT_PARAM;
+    }
+
+    // set permissions to the row owned by ownerLabel for accessorLabel
+    handler.database.setPermission(name, ownerLabel, accessorLabel, permissionMask);
+    transaction.commit();
+
+    return CKM_API_SUCCESS;
+}
+
+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;
+    Try {
+        retCode = setPermissionHelper(cred, name, label, accessorLabel, permissionMask);
+    } catch (const CKMLogic::Exception::DatabaseLocked &e) {
+        LogError("Error " << e.GetMessage());
+        retCode = CKM_API_ERROR_DB_LOCKED;
+    } Catch (CKM::Exception) {
+        LogError("Error in set row!");
+        retCode = CKM_API_ERROR_DB_ERROR;
+    }
+
+    return MessageBuffer::Serialize(command, msgID, retCode).Pop();
+}
+
 } // namespace CKM