Enable -Wshadow and fix warnings
[platform/core/security/key-manager.git] / src / manager / service / ckm-logic.cpp
index d39ca76..f57f920 100644 (file)
@@ -55,16 +55,6 @@ bool isNameValid(const CKM::Name &name)
        return true;
 }
 
-// keypair data type, having private key data type and public key data type
-// private is assumed to be .first, public .second
-using DataTypePair = std::pair<CKM::DataType, CKM::DataType>;
-
-const std::map<CKM::AlgoType, DataTypePair> ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP = {
-       { CKM::AlgoType::RSA_GEN,       { CKM::DataType(CKM::KeyType::KEY_RSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_RSA_PUBLIC) } },
-       { CKM::AlgoType::DSA_GEN,       { CKM::DataType(CKM::KeyType::KEY_DSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_DSA_PUBLIC) } },
-       { CKM::AlgoType::ECDSA_GEN,     { CKM::DataType(CKM::KeyType::KEY_ECDSA_PRIVATE), CKM::DataType(CKM::KeyType::KEY_ECDSA_PUBLIC) } },
-};
-
 } // anonymous namespace
 
 namespace CKM {
@@ -91,7 +81,7 @@ int toBinaryData(const Crypto::Data &input, Crypto::Data &output)
        if (input.type.isKey()) {
                KeyShPtr output_key;
 
-               if (input.type.isSKey())
+               if (input.type.isSymmetricKey())
                        output_key = CKM::Key::createAES(input.data);
                else
                        output_key = CKM::Key::create(input.data);
@@ -373,52 +363,21 @@ RawBuffer CKMLogic::removeUserData(uid_t user)
        return SerializeMessage(retCode);
 }
 
-int CKMLogic::changeUserPasswordHelper(uid_t user,
-                                                                          const Password &oldPassword,
-                                                                          const Password &newPassword)
-{
-       // do not allow to change system database password
-       if (m_accessControl.isSystemService(user))
-               return CKM_API_ERROR_INPUT_PARAM;
-
-       loadDKEKFile(user, oldPassword);
-       saveDKEKFile(user, newPassword);
-
-       return CKM_API_SUCCESS;
-}
-
 RawBuffer CKMLogic::changeUserPassword(
        uid_t user,
        const Password &oldPassword,
        const Password &newPassword)
 {
        return SerializeMessage(tryRet([&] {
-               return changeUserPasswordHelper(user, oldPassword, newPassword);
-       }));
-}
-
-int CKMLogic::resetUserPasswordHelper(
-       uid_t user,
-       const Password &newPassword)
-{
-       // do not allow to reset system database password
-       if (m_accessControl.isSystemService(user))
-               return CKM_API_ERROR_INPUT_PARAM;
-
-       int retCode = CKM_API_SUCCESS;
-
-       if (0 == m_userDataMap.count(user)) {
-               // Check if key exists. If exists we must return error
-               FileSystem fs(user);
-               auto wrappedDKEKMain = fs.getDKEK();
+               // do not allow to change system database password
+               if (m_accessControl.isSystemService(user))
+                       return CKM_API_ERROR_INPUT_PARAM;
 
-               if (!wrappedDKEKMain.empty())
-                       retCode = CKM_API_ERROR_BAD_REQUEST;
-       } else {
+               loadDKEKFile(user, oldPassword);
                saveDKEKFile(user, newPassword);
-       }
 
-       return retCode;
+               return CKM_API_SUCCESS;
+       }));
 }
 
 RawBuffer CKMLogic::resetUserPassword(
@@ -426,7 +385,24 @@ RawBuffer CKMLogic::resetUserPassword(
        const Password &newPassword)
 {
        return SerializeMessage(tryRet([&] {
-               return resetUserPasswordHelper(user, newPassword);
+               // do not allow to reset system database password
+               if (m_accessControl.isSystemService(user))
+                       return CKM_API_ERROR_INPUT_PARAM;
+
+               int retCode = CKM_API_SUCCESS;
+
+               if (0 == m_userDataMap.count(user)) {
+                       // Check if key exists. If exists we must return error
+                       FileSystem fs(user);
+                       auto wrappedDKEKMain = fs.getDKEK();
+
+                       if (!wrappedDKEKMain.empty())
+                               retCode = CKM_API_ERROR_BAD_REQUEST;
+               } else {
+                       saveDKEKFile(user, newPassword);
+               }
+
+               return retCode;
        }));
 }
 
@@ -464,10 +440,21 @@ int CKMLogic::verifyAndSaveDataHelper(
                // check if data is correct
                Crypto::Data binaryData;
                int retCode = toBinaryData(data, binaryData);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
+
+               auto [dbOp, digest, ret] = beginSaveAndGetHash(cred, name, owner);
+               if (ret != CKM_API_SUCCESS)
+                       return ret;
+
+               Crypto::GStore &store = m_decider.getStore(binaryData.type, policy);
 
-               return retCode != CKM_API_SUCCESS
-                       ? retCode
-                       : saveDataHelper(cred, name, owner, binaryData, policy);
+               // do not encrypt data with password during cc_mode on
+               Token token = store.import(binaryData,
+                                                                  m_accessControl.isCCMode() ? "" : policy.password,
+                                                                  Crypto::EncryptionParams(), digest);
+               dbOp.finalize(std::move(token), policy);
+               return CKM_API_SUCCESS;
        });
 }
 
@@ -511,52 +498,72 @@ RawBuffer CKMLogic::savePKCS12(
        const PolicySerializable &certPolicy)
 {
        return SerializeMessage(msgId, tryRet([&] {
-               return saveDataHelper(cred, name, owner, pkcs, keyPolicy, certPolicy);
-       }));
-}
+               auto [dbOp, retCode] = beginSave(cred, name, owner);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
 
-int CKMLogic::removeDataHelper(
-       const Credentials &cred,
-       const Name &name,
-       const ClientId &owner)
-{
-       auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
-       if (retCode != CKM_API_SUCCESS)
-               return retCode;
+               // extract and encrypt the data
+               DB::RowVector encryptedRows;
 
-       retCode = m_accessControl.canDelete(cred, permission);
-       if (retCode != CKM_API_SUCCESS) {
-               LogWarning("access control check result: " << retCode);
-               return retCode;
-       }
+               auto import = [&](const Crypto::Data &data, const Policy& policy){
+                       retCode = verifyBinaryData(data);
+                       if (retCode != CKM_API_SUCCESS)
+                               return retCode;
 
-       // get all matching rows
-       DB::RowVector rows;
-       dbOp.database().getRows(name, owner, DataType::DB_FIRST, DataType::DB_LAST, rows);
-       if (rows.empty()) {
-               LogDebug("No row for given name and owner");
-               return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
-       }
+                       auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid, data.type);
+                       if (digest.empty())
+                               return CKM_API_ERROR_HASH_ERROR;
 
-       retCode = dbOp.loadAppKey();
-       if (retCode != CKM_API_SUCCESS)
-               return retCode;
+                       Crypto::GStore &store = m_decider.getStore(data.type, policy);
+
+                       // do not encrypt data with password during cc_mode on
+                       Token token = store.import(data,
+                                                                          m_accessControl.isCCMode() ? "" : policy.password,
+                                                                          Crypto::EncryptionParams(), digest);
+
+                       encryptedRows.push_back(dbOp.encryptOne(std::move(token), policy));
+                       return CKM_API_SUCCESS;
+               };
 
-       // destroy it in store
-       for (auto &r : rows) {
-               try {
-                       dbOp.handler().crypto.decryptRow(Password(), r);
-                       m_decider.getStore(r).destroy(r);
-               } catch (const Exc::AuthenticationFailed &) {
-                       LogDebug("Authentication failed when removing data. Ignored.");
+               // private key is mandatory
+               auto key = pkcs.getKey();
+               if (!key) {
+                       LogError("Failed to get private key from pkcs");
+                       return CKM_API_ERROR_INVALID_FORMAT;
                }
-       }
 
-       // delete row in db
-       dbOp.database().deleteRow(name, owner);
-       dbOp.transaction().commit();
+               Crypto::Data keyData(DataType(key->getType()), key->getDER());
+               retCode = import(keyData, keyPolicy);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
 
-       return CKM_API_SUCCESS;
+               // certificate is mandatory
+               auto cert = pkcs.getCertificate();
+               if (!cert) {
+                       LogError("Failed to get certificate from pkcs");
+                       return CKM_API_ERROR_INVALID_FORMAT;
+               }
+
+               Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
+               retCode = import(certData, certPolicy);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
+
+               // CA cert chain
+               unsigned int cert_index = 0;
+               for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
+                       Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++), ca->getDER());
+                       retCode = import(caCertData, certPolicy);
+                       if (retCode != CKM_API_SUCCESS)
+                               return retCode;
+               }
+
+               // save the data
+               dbOp.database().saveRows(name, owner, encryptedRows);
+               dbOp.transaction().commit();
+
+               return CKM_API_SUCCESS;
+       }));
 }
 
 RawBuffer CKMLogic::removeData(
@@ -566,7 +573,43 @@ RawBuffer CKMLogic::removeData(
        const ClientId &owner)
 {
        return SerializeMessage(msgId, tryRet([&] {
-               return removeDataHelper(cred, name, owner);
+               auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
+
+               retCode = m_accessControl.canDelete(cred, permission);
+               if (retCode != CKM_API_SUCCESS) {
+                       LogWarning("access control check result: " << retCode);
+                       return retCode;
+               }
+
+               // get all matching rows
+               DB::RowVector rows;
+               dbOp.database().getRows(name, owner, DataType::DB_FIRST, DataType::DB_LAST, rows);
+               if (rows.empty()) {
+                       LogDebug("No row for given name and owner");
+                       return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
+               }
+
+               retCode = dbOp.loadAppKey();
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
+
+               // destroy it in store
+               for (auto &r : rows) {
+                       try {
+                               dbOp.handler().crypto.decryptRow(Password(), r);
+                               m_decider.getStore(r).destroy(r);
+                       } catch (const Exc::AuthenticationFailed &) {
+                               LogDebug("Authentication failed when removing data. Ignored.");
+                       }
+               }
+
+               // delete row in db
+               dbOp.database().deleteRow(name, owner);
+               dbOp.transaction().commit();
+
+               return CKM_API_SUCCESS;
        }));
 }
 
@@ -582,25 +625,20 @@ int CKMLogic::checkDataPermissionsHelper(const Credentials &accessorCred,
        return m_accessControl.canRead(accessorCred, permission);
 }
 
-Crypto::GObjUPtr CKMLogic::rowToObject(
+void CKMLogic::decryptRow(
        UserData &handler,
-       DB::Row row,
+       DB::Row &row,
        const Password &password,
        const RawBuffer &hash)
 {
-       Crypto::GStore &store = m_decider.getStore(row);
-
-       Password pass = m_accessControl.isCCMode() ? "" : password;
-
-       // decrypt row
-       Crypto::GObjUPtr obj;
-
        if (CryptoLogic::getSchemeVersion(row.encryptionScheme) ==
                        CryptoLogic::ENCRYPTION_V2) {
                handler.crypto.decryptRow(Password(), row);
-
-               obj = store.getObject(row, pass);
        } else {
+               Crypto::GStore &store = m_decider.getStore(row);
+
+               Password pass = m_accessControl.isCCMode() ? "" : password;
+
                // decrypt entirely with old scheme: b64(pass(appkey(data))) -> data
                handler.crypto.decryptRow(pass, row);
                // destroy it in store
@@ -612,20 +650,26 @@ Crypto::GObjUPtr CKMLogic::rowToObject(
                                                                   Crypto::EncryptionParams(),
                                                                   hash);
 
-               // get it from the store (it can be different than the data we imported into store)
-               obj = store.getObject(token, pass);
-
                // update row with new token
                *static_cast<Token *>(&row) = std::move(token);
 
                // encrypt it with app key: pass(data) -> b64(appkey(pass(data))
-               handler.crypto.encryptRow(row);
+               auto encryptedRow = handler.crypto.encryptRow(row);
 
                // update it in db
-               handler.database.updateRow(row);
+               handler.database.updateRow(encryptedRow);
        }
+}
+
+Crypto::GObjUPtr CKMLogic::rowToObject(
+       UserData &handler,
+       DB::Row row,
+       const Password &password,
+       const RawBuffer &hash)
+{
+       decryptRow(handler, row, password, hash);
 
-       return obj;
+       return decryptedRowToObj(row, password);
 }
 
 int CKMLogic::readDataHelper(
@@ -697,21 +741,20 @@ int CKMLogic::readDataHelper(
                                                  password, obj, objDataType);
 }
 
-int CKMLogic::readDataHelper(
+int CKMLogic::readRowHelper(
        bool exportFlag,
        const Credentials &cred,
        DataType dataType,
        const Name &name,
        const ClientId &owner,
        const Password &password,
-       Crypto::GObjUPtr &obj,
+       DB::Row &row,
        DataType &objDataType)
 {
        auto [dbOp, permission, retCode] = beginAndGetPerm(cred, name, owner);
        if (retCode != CKM_API_SUCCESS)
                return retCode;
 
-       DB::Row row;
        retCode = readSingleRow(name, owner, dataType, dbOp.database(), row);
        if (CKM_API_SUCCESS != retCode)
                return retCode;
@@ -724,20 +767,49 @@ int CKMLogic::readDataHelper(
 
        // check access rights
        retCode = checkDataPermissionsHelper(cred, row, exportFlag, permission);
-       if (CKM_API_SUCCESS != retCode)
+       if (retCode != CKM_API_SUCCESS)
                return retCode;
 
        auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid);
        if (digest.empty())
                return CKM_API_ERROR_HASH_ERROR;
 
-       obj = rowToObject(dbOp.handler(), std::move(row), password, digest);
-       // rowToObject may modify db
+       decryptRow(dbOp.handler(), row, password, digest);
+
+       // decryptRow may modify db
        dbOp.transaction().commit();
 
        return CKM_API_SUCCESS;
 }
 
+Crypto::GObjUPtr CKMLogic::decryptedRowToObj(const DB::Row& row, const Password &password)
+{
+       Crypto::GStore &store = m_decider.getStore(row);
+
+       Password pass = m_accessControl.isCCMode() ? "" : password;
+       return store.getObject(row, pass);
+}
+
+int CKMLogic::readDataHelper(
+       bool exportFlag,
+       const Credentials &cred,
+       DataType dataType,
+       const Name &name,
+       const ClientId &owner,
+       const Password &password,
+       Crypto::GObjUPtr &obj,
+       DataType &objDataType)
+{
+       DB::Row row;
+       int retCode = readRowHelper(exportFlag, cred, dataType, name, owner, password, row, objDataType);
+       if (retCode != CKM_API_SUCCESS)
+               return retCode;
+
+       obj = decryptedRowToObj(row, password);
+
+       return CKM_API_SUCCESS;
+}
+
 RawBuffer CKMLogic::getData(
        const Credentials &cred,
        int msgId,
@@ -751,13 +823,13 @@ RawBuffer CKMLogic::getData(
 
        int retCode = tryRet([&] {
                Crypto::GObjUPtr obj;
-               int retCode = readDataHelper(true, cred, dataType, name, owner,
-                                                                        password, obj, objDataType);
+               int retCode2 = readDataHelper(true, cred, dataType, name, owner,
+                                                                         password, obj, objDataType);
 
-               if (retCode == CKM_API_SUCCESS)
+               if (retCode2 == CKM_API_SUCCESS)
                        rowData = obj->getBinary();
 
-               return retCode;
+               return retCode2;
        });
 
        if (CKM_API_SUCCESS != retCode)
@@ -790,63 +862,6 @@ RawBuffer CKMLogic::getDataProtectionStatus(
        return SerializeMessage(msgId, retCode, objDataType, status);
 }
 
-int CKMLogic::getPKCS12Helper(
-       const Credentials &cred,
-       const Name &name,
-       const ClientId &owner,
-       const Password &keyPassword,
-       const Password &certPassword,
-       KeyShPtr &privKey,
-       CertificateShPtr &cert,
-       CertificateShPtrVector &caChain)
-{
-       int retCode;
-
-       // read private key (mandatory)
-       Crypto::GObjUPtr keyObj;
-       retCode = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, owner,
-                                                        keyPassword, keyObj);
-
-       if (retCode != CKM_API_SUCCESS) {
-               if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
-                       return retCode;
-       } else {
-               privKey = CKM::Key::create(keyObj->getBinary());
-       }
-
-       // read certificate (mandatory)
-       Crypto::GObjUPtr certObj;
-       retCode = readDataHelper(true, cred, DataType::CERTIFICATE, name, owner,
-                                                        certPassword, certObj);
-
-       if (retCode != CKM_API_SUCCESS) {
-               if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
-                       return retCode;
-       } else {
-               cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
-       }
-
-       // read CA cert chain (optional)
-       Crypto::GObjUPtrVector caChainObjs;
-       retCode = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, owner,
-                                                        certPassword, caChainObjs);
-
-       if (retCode != CKM_API_SUCCESS && retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
-               if (retCode != CKM_API_ERROR_NOT_EXPORTABLE)
-                       return retCode;
-       } else {
-               for (auto &caCertObj : caChainObjs)
-                       caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
-                                                                                                          DataFormat::FORM_DER));
-       }
-
-       // if anything found, return it
-       if (privKey || cert || caChain.size() > 0)
-               retCode = CKM_API_SUCCESS;
-
-       return retCode;
-}
-
 RawBuffer CKMLogic::getPKCS12(
        const Credentials &cred,
        int msgId,
@@ -861,22 +876,63 @@ RawBuffer CKMLogic::getPKCS12(
                KeyShPtr privKey;
                CertificateShPtr cert;
                CertificateShPtrVector caChain;
-               int retCode = getPKCS12Helper(cred, name, owner, keyPassword,
-                                                                 certPassword, privKey, cert, caChain);
+
+               // read private key (mandatory)
+               Crypto::GObjUPtr keyObj;
+               int retCode2 = readDataHelper(true, cred, DataType::DB_KEY_FIRST, name, owner,
+                                                                         keyPassword, keyObj);
+
+               if (retCode2 != CKM_API_SUCCESS) {
+                       if (retCode2 != CKM_API_ERROR_NOT_EXPORTABLE)
+                               return retCode2;
+               } else {
+                       privKey = CKM::Key::create(keyObj->getBinary());
+               }
+
+               // read certificate (mandatory)
+               Crypto::GObjUPtr certObj;
+               retCode2 = readDataHelper(true, cred, DataType::CERTIFICATE, name, owner,
+                                                                 certPassword, certObj);
+
+               if (retCode2 != CKM_API_SUCCESS) {
+                       if (retCode2 != CKM_API_ERROR_NOT_EXPORTABLE)
+                               return retCode2;
+               } else {
+                       cert = CKM::Certificate::create(certObj->getBinary(), DataFormat::FORM_DER);
+               }
+
+               // read CA cert chain (optional)
+               Crypto::GObjUPtrVector caChainObjs;
+               retCode2 = readDataHelper(true, cred, DataType::DB_CHAIN_FIRST, name, owner,
+                                                                 certPassword, caChainObjs);
+
+               if (retCode2 != CKM_API_SUCCESS && retCode2 != CKM_API_ERROR_DB_ALIAS_UNKNOWN) {
+                       if (retCode2 != CKM_API_ERROR_NOT_EXPORTABLE)
+                               return retCode2;
+               } else {
+                       for (auto &caCertObj : caChainObjs)
+                               caChain.push_back(CKM::Certificate::create(caCertObj->getBinary(),
+                                                                                                                  DataFormat::FORM_DER));
+               }
+
+               // if anything found, return it
+               if (privKey || cert || caChain.size() > 0)
+                       retCode2 = CKM_API_SUCCESS;
 
                // prepare response
-               if (retCode == CKM_API_SUCCESS)
-                       output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
+               if (retCode2 != CKM_API_SUCCESS)
+                       return retCode2;
 
-               return retCode;
+               output = PKCS12Serializable(std::move(privKey), std::move(cert), std::move(caChain));
+               return CKM_API_SUCCESS;
        });
 
        return SerializeMessage(msgId, retCode, output);
 }
 
-int CKMLogic::getDataListHelper(const Credentials &cred,
-                                                               const DataType dataType,
-                                                               OwnerNameVector &ownerNameVector)
+int CKMLogic::getAliasInfoListHelper(const Credentials &cred,
+                                                                        const DataType dataType,
+                                                                        AliasInfoVector &aliasInfoVector)
 {
        int retCode = CKM_API_ERROR_DB_LOCKED;
 
@@ -884,23 +940,20 @@ int CKMLogic::getDataListHelper(const Credentials &cred,
                auto &database = m_userDataMap[cred.clientUid].database;
 
                retCode = tryRet<CKM_API_ERROR_DB_ERROR>([&] {
-                       OwnerNameVector tmpVector;
+                       AliasInfoVector tmpVector;
 
                        if (dataType.isKey()) {
                                // list all key types
-                               database.listNames(cred.client,
+                               database.listInfos(cred.client,
                                                                   tmpVector,
                                                                   DataType::DB_KEY_FIRST,
                                                                   DataType::DB_KEY_LAST);
                        } else {
                                // list anything else
-                               database.listNames(cred.client,
-                                                                  tmpVector,
-                                                                  dataType);
+                               database.listInfos(cred.client, tmpVector, dataType);
                        }
 
-                       ownerNameVector.insert(ownerNameVector.end(), tmpVector.begin(),
-                                                                  tmpVector.end());
+                       aliasInfoVector.insert(aliasInfoVector.end(), tmpVector.begin(), tmpVector.end());
                        return CKM_API_SUCCESS;
                });
        }
@@ -913,9 +966,9 @@ RawBuffer CKMLogic::getDataList(
        int msgId,
        DataType dataType)
 {
-       OwnerNameVector systemVector;
-       OwnerNameVector userVector;
-       OwnerNameVector ownerNameVector;
+       AliasInfoVector systemVector;
+       AliasInfoVector userVector;
+       AliasInfoVector aliasInfoVector;
 
        int retCode = unlockSystemDB();
 
@@ -923,32 +976,32 @@ RawBuffer CKMLogic::getDataList(
                // system database
                if (m_accessControl.isSystemService(cred)) {
                        // lookup system DB
-                       retCode = getDataListHelper(Credentials(SYSTEM_DB_UID, CLIENT_ID_SYSTEM),
-                                                                               dataType,
-                                                                               systemVector);
+                       retCode = getAliasInfoListHelper(Credentials(SYSTEM_DB_UID, CLIENT_ID_SYSTEM),
+                                                                                        dataType,
+                                                                                        systemVector);
                } else {
                        // user - lookup system, then client DB
-                       retCode = getDataListHelper(Credentials(SYSTEM_DB_UID, cred.client),
-                                                                               dataType,
-                                                                               systemVector);
+                       retCode = getAliasInfoListHelper(Credentials(SYSTEM_DB_UID, cred.client),
+                                                                                        dataType,
+                                                                                        systemVector);
 
                        // private database
                        if (retCode == CKM_API_SUCCESS) {
-                               retCode = getDataListHelper(cred,
-                                                                                       dataType,
-                                                                                       userVector);
+                               retCode = getAliasInfoListHelper(cred,
+                                                                                                dataType,
+                                                                                                userVector);
                        }
                }
        }
 
        if (retCode == CKM_API_SUCCESS) {
-               ownerNameVector.insert(ownerNameVector.end(), systemVector.begin(),
+               aliasInfoVector.insert(aliasInfoVector.end(), systemVector.begin(),
                                                           systemVector.end());
-               ownerNameVector.insert(ownerNameVector.end(), userVector.begin(),
+               aliasInfoVector.insert(aliasInfoVector.end(), userVector.begin(),
                                                           userVector.end());
        }
 
-       return SerializeMessage(msgId, retCode, dataType, ownerNameVector);
+       return SerializeMessage(msgId, retCode, dataType, AliasInfoSerializableVector(aliasInfoVector));
 }
 
 int CKMLogic::importInitialData(
@@ -972,7 +1025,7 @@ int CKMLogic::importInitialData(
                        if (retCode != CKM_API_SUCCESS)
                                return retCode;
 
-                       Crypto::GStore &store = m_decider.getStore(data.type, policy, !encParams.iv.empty());
+                       Crypto::GStore &store = m_decider.getStore(data.type, policy, true, !encParams.iv.empty());
 
                        Token token;
                        if (encParams.iv.empty()) {
@@ -1001,102 +1054,6 @@ int CKMLogic::importInitialData(
        }
 }
 
-int CKMLogic::saveDataHelper(
-       const Credentials &cred,
-       const Name &name,
-       const ClientId &owner,
-       const Crypto::Data &data,
-       const PolicySerializable &policy)
-{
-       auto [dbOp, digest, ret] = beginSaveAndGetHash(cred, name, owner);
-       if (ret != CKM_API_SUCCESS)
-               return ret;
-
-       Crypto::GStore &store = m_decider.getStore(data.type, policy);
-
-       // do not encrypt data with password during cc_mode on
-       Token token = store.import(data,
-                                                          m_accessControl.isCCMode() ? "" : policy.password,
-                                                          Crypto::EncryptionParams(), digest);
-       dbOp.finalize(std::move(token), policy);
-       return CKM_API_SUCCESS;
-}
-
-int CKMLogic::saveDataHelper(
-       const Credentials &cred,
-       const Name &name,
-       const ClientId &owner,
-       const PKCS12Serializable &pkcs,
-       const PolicySerializable &keyPolicy,
-       const PolicySerializable &certPolicy)
-{
-       auto [dbOp, retCode] = beginSave(cred, name, owner);
-       if (retCode != CKM_API_SUCCESS)
-               return retCode;
-
-       // extract and encrypt the data
-       DB::RowVector encryptedRows;
-
-       auto import = [&](const Crypto::Data &data, const Policy& policy){
-               retCode = verifyBinaryData(data);
-               if (retCode != CKM_API_SUCCESS)
-                       return retCode;
-
-               auto digest = CryptoLogic::makeHash(name, owner, cred.clientUid, data.type);
-               if (digest.empty())
-                       return CKM_API_ERROR_HASH_ERROR;
-
-               Crypto::GStore &store = m_decider.getStore(data.type, policy);
-
-               // do not encrypt data with password during cc_mode on
-               Token token = store.import(data,
-                                                                  m_accessControl.isCCMode() ? "" : policy.password,
-                                                                  Crypto::EncryptionParams(), digest);
-
-               encryptedRows.push_back(dbOp.encryptOne(std::move(token), policy));
-               return CKM_API_SUCCESS;
-       };
-
-       // private key is mandatory
-       auto key = pkcs.getKey();
-       if (!key) {
-               LogError("Failed to get private key from pkcs");
-               return CKM_API_ERROR_INVALID_FORMAT;
-       }
-
-       Crypto::Data keyData(DataType(key->getType()), key->getDER());
-       retCode = import(keyData, keyPolicy);
-       if (retCode != CKM_API_SUCCESS)
-               return retCode;
-
-       // certificate is mandatory
-       auto cert = pkcs.getCertificate();
-       if (!cert) {
-               LogError("Failed to get certificate from pkcs");
-               return CKM_API_ERROR_INVALID_FORMAT;
-       }
-
-       Crypto::Data certData(DataType::CERTIFICATE, cert->getDER());
-       retCode = import(certData, certPolicy);
-       if (retCode != CKM_API_SUCCESS)
-               return retCode;
-
-       // CA cert chain
-       unsigned int cert_index = 0;
-       for (const auto &ca : pkcs.getCaCertificateShPtrVector()) {
-               Crypto::Data caCertData(DataType::getChainDatatype(cert_index ++), ca->getDER());
-               retCode = import(caCertData, certPolicy);
-               if (retCode != CKM_API_SUCCESS)
-                       return retCode;
-       }
-
-       // save the data
-       dbOp.database().saveRows(name, owner, encryptedRows);
-       dbOp.transaction().commit();
-
-       return CKM_API_SUCCESS;
-}
-
 int CKMLogic::DBOperation::loadAppKey(bool keyRequired)
 {
        if (!m_handler.crypto.haveKey(m_owner)) {
@@ -1141,7 +1098,7 @@ std::tuple<CKMLogic::DBOperation, PermissionMask, int> CKMLogic::beginAndGetPerm
        const Name &name,
        const ClientId &owner)
 {
-       PermissionMask permission;
+       PermissionMask permission = Permission::NONE;
        auto [dbOp, retCode] = begin(cred, name, owner);
        if (retCode == CKM_API_SUCCESS)
                permission = toPermissionMask(dbOp.database().getPermissionRow(name, owner, cred.client));
@@ -1211,23 +1168,14 @@ RawBuffer CKMLogic::createKeyPair(
                if (retCodePub != CKM_API_SUCCESS)
                        return retCodePub;
 
-               AlgoType keyType = AlgoType::RSA_GEN;
-
-               if (!keyGenParams.getParam(ParamName::ALGO_TYPE, keyType))
-                       ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE not found.");
-
-               const auto dtIt = ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.find(keyType);
-               if (dtIt == ALGO_TYPE_TO_DATA_TYPE_PAIR_MAP.end())
-                       ThrowErr(Exc::InputParam, "Error, parameter ALGO_TYPE with wrong value.");
-               const DataTypePair& dt = dtIt->second;
-
                if (policyPrv.backend != policyPub.backend)
                        ThrowErr(Exc::InputParam, "Error, key pair must be supported with the same backend.");
 
                bool exportable = policyPrv.extractable || policyPub.extractable;
                Policy lessRestricted(Password(), exportable, policyPrv.backend);
 
-               TokenPair keys = m_decider.getStore(policyPrv, dt.first, dt.second).generateAKey(
+               // For now any asymmetric key will do. If necessary we can extract it from keyGenParams.
+               TokenPair keys = m_decider.getStore(DataType::DB_KEY_FIRST, policyPrv, false).generateAKey(
                        keyGenParams,
                        policyPrv.password,
                        policyPub.password,
@@ -1252,17 +1200,17 @@ RawBuffer CKMLogic::createKeyAES(
 
        try {
                retCode = tryRet([&] {
-                       auto [dbOp, digest, retCode] = beginSaveAndGetHash(cred, name, owner);
-                       if (retCode != CKM_API_SUCCESS)
-                               return retCode;
+                       auto [dbOp, digest, retCode2] = beginSaveAndGetHash(cred, name, owner);
+                       if (retCode2 != CKM_API_SUCCESS)
+                               return retCode2;
 
                        // create key in store
                        CryptoAlgorithm keyGenAlgorithm;
                        keyGenAlgorithm.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GEN);
                        keyGenAlgorithm.setParam(ParamName::GEN_KEY_LEN, size);
-                       Token key = m_decider.getStore(DataType::KEY_AES, policy).generateSKey(keyGenAlgorithm,
-                                                                                                                                                                  policy.password,
-                                                                                                                                                                  digest);
+
+                       auto& store = m_decider.getStore(DataType::KEY_AES, policy, false);
+                       Token key = store.generateSKey(keyGenAlgorithm, policy.password, digest);
 
                        dbOp.finalize(std::move(key), policy);
                        return CKM_API_SUCCESS;
@@ -1485,13 +1433,13 @@ RawBuffer CKMLogic::createSignature(
        try {
                retCode = tryRet([&] {
                        Crypto::GObjUPtr obj;
-                       int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
-                                                                                owner, password, obj);
+                       int retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, privateKeyName,
+                                                                                 owner, password, obj);
 
-                       if (retCode == CKM_API_SUCCESS)
+                       if (retCode2 == CKM_API_SUCCESS)
                                signature = obj->sign(cryptoAlg, message);
 
-                       return retCode;
+                       return retCode2;
                });
        } catch (const std::exception &e) {
                LogError("STD exception " << e.what());
@@ -1573,5 +1521,154 @@ RawBuffer CKMLogic::setPermission(
        }));
 }
 
-} // namespace CKM
+RawBuffer CKMLogic::deriveKey(
+       const Credentials &cred,
+       const int msgID,
+       const CryptoAlgorithm &params,
+       const Name &secretName,
+       const ClientId &secretOwner,
+       const Password &secretPassword,
+       const Name &newKeyName,
+       const ClientId &newKeyOwner,
+       const Policy &newKeyPolicy)
+{
+       return SerializeMessage(msgID, tryRet([&] {
+               // Get key/secret for internal service use. It won't be exported to the client
+               Crypto::GObjUPtr obj;
+               DataType objType;
+               int retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST,
+                                                                        secretName, secretOwner, secretPassword, obj, objType);
+               if (retCode != CKM_API_SUCCESS) {
+                       if (retCode != CKM_API_ERROR_DB_ALIAS_UNKNOWN)
+                               return retCode;
+
+                       retCode = readDataHelper(false, cred, DataType::BINARY_DATA,
+                                                                        secretName, secretOwner, secretPassword, obj, objType);
+                       if (retCode != CKM_API_SUCCESS)
+                               return retCode;
+               }
+
+               auto [dbOp, digest, ret] = beginSaveAndGetHash(cred, newKeyName, newKeyOwner);
+               if (ret != CKM_API_SUCCESS)
+                       return ret;
+
+               // ECDH (private key) -> binary secret, KBKDF -> symmetric key
+               DataType newKeyType = objType.isKeyPrivate() ? DataType::BINARY_DATA : DataType::KEY_AES;
+               if (!m_decider.checkStore(obj->backendId(), newKeyType, newKeyPolicy, false)) {
+                       LogDebug("Can't import the derived key to backend " <<
+                                static_cast<int>(obj->backendId()) << " with given policy");
+                       return CKM_API_ERROR_INPUT_PARAM;
+               }
+
+               // derive
+               Token derived = obj->derive(params, newKeyPolicy.password, digest);
+
+               dbOp.finalize(std::move(derived), newKeyPolicy);
+
+               return CKM_API_SUCCESS;
+       }));
+}
+
+RawBuffer CKMLogic::importWrappedKey(
+       const Credentials &cred,
+       const int msgId,
+       const CryptoAlgorithm &params,
+       const Name &wrappingKeyName,
+       const ClientId &wrappingKeyOwner,
+       const Password &wrappingKeyPassword,
+       const Name &keyName,
+       const ClientId &keyOwner,
+       const RawBuffer &wrappedKey,
+       const CKM::DataType keyType,
+       const PolicySerializable &policy)
+{
+       return SerializeMessage(msgId, tryRet([&] {
+               Crypto::GObjUPtr wrappingKey;
+
+               auto [dbOp, digest, retCode] = beginSaveAndGetHash(cred, keyName, keyOwner);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
+
+               retCode = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
+                                                               wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+               if (retCode != CKM_API_SUCCESS)
+                       return retCode;
+
+               if (!m_decider.checkStore(wrappingKey->backendId(), keyType, policy, true)) {
+                       LogDebug("Can't import the wrapped key to backend " <<
+                                static_cast<int>(wrappingKey->backendId()) << " with given policy");
+                       return CKM_API_ERROR_INPUT_PARAM;
+               }
+
+               Token token = wrappingKey->unwrap(params,
+                                                                                 Crypto::Data(keyType, std::move(wrappedKey)),
+                                                                                 policy.password,
+                                                                                 digest);
+
+               dbOp.finalize(std::move(token), policy);
+
+               return retCode;
+       }));
+}
+
+RawBuffer CKMLogic::exportWrappedKey(
+       const Credentials &cred,
+       const int msgID,
+       const CryptoAlgorithm &params,
+       const Name &wrappingKeyName,
+       const ClientId &wrappingKeyOwner,
+       const Password &wrappingKeyPassword,
+       const Name &keyName,
+       const ClientId &keyOwner,
+       const Password &keyPassword)
+{
+       Crypto::GObjUPtr wrappingKey;
+       DB::Row wrappedKeyRow;
+       DataType wrappedKeyType;
+       RawBuffer wrappedKey;
 
+       auto retCode = tryRet([&] {
+               auto retCode2 = readDataHelper(false, cred, DataType::DB_KEY_FIRST, wrappingKeyName,
+                                                                          wrappingKeyOwner, wrappingKeyPassword, wrappingKey);
+               if (retCode2 != CKM_API_SUCCESS)
+                       return retCode2;
+
+               retCode2 = readRowHelper(false, cred, DataType::DB_KEY_FIRST, keyName,
+                                                                keyOwner, keyPassword, wrappedKeyRow, wrappedKeyType);
+               if (retCode2 != CKM_API_SUCCESS)
+                       return retCode2;
+
+               wrappedKey = wrappingKey->wrap(params, wrappedKeyRow, keyPassword);
+
+               return retCode2;
+       });
+
+       return SerializeMessage(msgID, retCode, wrappedKeyType, wrappedKey);
+}
+
+RawBuffer CKMLogic::getBackendInfo(const int msgID, BackendId backend)
+{
+       BackendInfo info;
+       auto retCode = tryRet([&] {
+               CryptoBackend cryptoBackend;
+               if (backend == BackendId::SW)
+                       cryptoBackend = CryptoBackend::OpenSSL;
+               else if (backend == BackendId::TZ)
+                       cryptoBackend = CryptoBackend::TrustZone;
+               else
+                       return CKM_API_ERROR_INPUT_PARAM;
+
+               auto store = m_decider.getStore(cryptoBackend);
+               if (store == nullptr) {
+                       LogError("Required backend is unavailable");
+                       return CKM_API_ERROR_INPUT_PARAM;
+               }
+
+               info.maxChunkSize = store->maxChunkSize();
+               return CKM_API_SUCCESS;
+       });
+
+       return SerializeMessage(msgID, retCode, BackendInfoSerializable(info));
+}
+
+} // namespace CKM