From 27ad4ebab5c36a4c48fb4ae029b69fdd621841e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 7 Jun 2023 10:32:58 +0200 Subject: [PATCH 01/16] Extend E2EE API support back to 6.0 Change-Id: I7aff7fb9a35fa26804303a11a4cf0a8c03fb287c --- src/include/ckmc/ckmc-manager.h | 16 ++++++++-------- src/include/ckmc/ckmc-type.h | 40 ++++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/include/ckmc/ckmc-manager.h b/src/include/ckmc/ckmc-manager.h index 76cca21..6386f23 100644 --- a/src/include/ckmc/ckmc-manager.h +++ b/src/include/ckmc/ckmc-manager.h @@ -1104,7 +1104,7 @@ int ckmc_decrypt_data(ckmc_param_list_h params, /** * @brief Unwraps one key with another and stores it inside key manager. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks The wrapping key must be either symmetric (#CKMC_KEY_AES) or private RSA * (#CKMC_KEY_RSA_PRIVATE). @@ -1165,7 +1165,7 @@ int ckmc_import_wrapped_key(const ckmc_param_list_h params, /** * @brief Wraps one key with another and returns it to the client. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks The wrapping key must be either symmetric (#CKMC_KEY_AES) or public RSA * (#CKMC_KEY_RSA_PUBLIC). @@ -1217,7 +1217,7 @@ int ckmc_export_wrapped_key(const ckmc_param_list_h params, /** * @brief Derives a secret or key from another key/secret and stores it inside key manager. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks In case of #CKMC_ALGO_KBKDF algorithm, the secret pointed to by @a secret_alias must be * a binary data or a symmetric key (#CKMC_KEY_AES). The derived key pointed to by @@ -1267,7 +1267,7 @@ int ckmc_key_derive(const ckmc_param_list_h params, /** * @brief Sets up a symmetric encryption or decryption context with given key and parameters. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks The newly created @a context must be destroyed using ckmc_cipher_free() when it's no * longer needed. @@ -1316,7 +1316,7 @@ int ckmc_cipher_initialize(ckmc_param_list_h params, * @brief Performs symmetric encryption or decryption of the input and places the result in the * output. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks The function may be called multiple times to encrypt succcessive blocks of data. * @remarks The newly created @a ppout must be destroyed using ckmc_buffer_free() when it's no @@ -1344,7 +1344,7 @@ int ckmc_cipher_update(ckmc_cipher_ctx_h context, /** * @brief Finalizes symmetric encryption or decryption and returns remaining output if any. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks After the call to this function the ckmc_cipher_update() can be called no more. * @remarks The newly created @a ppout must be destroyed using ckmc_buffer_free() when it's no @@ -1375,7 +1375,7 @@ int ckmc_cipher_finalize(ckmc_cipher_ctx_h context, /** * @brief Destroys the encryption/decryption context and releases all its resources. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @param[in] context Encryption/decryption context created with ckmc_cipher_initialize() * @@ -1389,7 +1389,7 @@ void ckmc_cipher_free(ckmc_cipher_ctx_h context); /** * @brief Retrieves backend information. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @remarks The newly created @a ppinfo must be destroyed using ckmc_backend_info_free() when it's * no longer needed. diff --git a/src/include/ckmc/ckmc-type.h b/src/include/ckmc/ckmc-type.h index 192598b..1d6d9cc 100644 --- a/src/include/ckmc/ckmc-type.h +++ b/src/include/ckmc/ckmc-type.h @@ -300,45 +300,45 @@ typedef enum __ckmc_param_name { CKMC_PARAM_ED_LABEL, /**< buffer - RSA OAEP label (not supported at the moment) */ CKMC_PARAM_KDF_PRF = 401, /**< integer - pseudo-random function number (see #ckmc_kdf_prf_e) - (Since 6.5) */ + (Since 6.0) */ CKMC_PARAM_KDF_LEN, /**< integer - length of the derived key in bytes. The value must be one of - {16, 24, 32} (Since 6.5) */ + {16, 24, 32} (Since 6.0) */ - CKMC_PARAM_KBKDF_MODE, /**< integer - KDF mode number (see #ckmc_kbkdf_mode_e) (Since 6.5) */ + CKMC_PARAM_KBKDF_MODE, /**< integer - KDF mode number (see #ckmc_kbkdf_mode_e) (Since 6.0) */ CKMC_PARAM_KBKDF_LABEL, /**< buffer - the purpose for the derived key. Conflicts with - #CKMC_PARAM_KBKDF_FIXED_INPUT (Since 6.5) */ + #CKMC_PARAM_KBKDF_FIXED_INPUT (Since 6.0) */ CKMC_PARAM_KBKDF_CONTEXT, /**< buffer - information related to the derived key. Conflicts with - #CKMC_PARAM_KBKDF_FIXED_INPUT (Since 6.5) */ + #CKMC_PARAM_KBKDF_FIXED_INPUT (Since 6.0) */ CKMC_PARAM_KBKDF_FIXED_INPUT, /**< buffer - KBKDF fixed input replacing context and label - (Since 6.5). Conflicts with: + (Since 6.0). Conflicts with: - #CKMC_PARAM_KBKDF_LABEL, - #CKMC_PARAM_KBKDF_CONTEXT, - #CKMC_PARAM_KBKDF_LLEN, - #CKMC_PARAM_KBKDF_NO_SEPARATOR */ CKMC_PARAM_KBKDF_COUNTER_LOCATION, /**< integer - specifies location of the counter in KBKDF - (see #ckmc_kbkdf_counter_location_e) (Since 6.5) */ + (see #ckmc_kbkdf_counter_location_e) (Since 6.0) */ CKMC_PARAM_KBKDF_RLEN, /**< integer - specifies the length of the counter representation in bits in KBKDF. The value must be one of {8, 16, 24, 32}. If not set, the - default value = 32 will be used. (Since 6.5) */ + default value = 32 will be used. (Since 6.0) */ CKMC_PARAM_KBKDF_LLEN, /**< integer - specifies the length of the length suffix representation in bits in KBKDF. The value must be one of {0, 8, 16, 24, 32}. If set to 0 the length suffix will be skipped. If not set, the default value = 32 will be used. The length suffix is skipped if #CKMC_PARAM_KBKDF_FIXED_INPUT is passed and this parameter conflicts - with it. (Since 6.5) */ + with it. (Since 6.0) */ CKMC_PARAM_KBKDF_NO_SEPARATOR, /**< integer - presence of this parameter will skip the zero octet separator between label and context in KBKDF. All values are allowed. This parameter conflicts with - #CKMC_PARAM_KBKDF_FIXED_INPUT. (Since 6.5) */ + #CKMC_PARAM_KBKDF_FIXED_INPUT. (Since 6.0) */ - CKMC_PARAM_ECDH_PUBKEY, /**< buffer - EC public key in DER form (see #ckmc_key_s) (Since 6.5) */ + CKMC_PARAM_ECDH_PUBKEY, /**< buffer - EC public key in DER form (see #ckmc_key_s) (Since 6.0) */ } ckmc_param_name_e; /** * @brief Enumeration for key derivation function pseudo-random function parameter. - * @since_tizen 6.5 + * @since_tizen 6.0 * * @see ckmc_key_derive() * @see #ckmc_param_name_e @@ -351,7 +351,7 @@ typedef enum __ckmc_kdf_prf { /** * @brief Enumeration for key based key derivation function mode. - * @since_tizen 6.5 + * @since_tizen 6.0 * * @see ckmc_key_derive() * @see #ckmc_param_name_e @@ -362,7 +362,7 @@ typedef enum __ckmc_kbkdf_mode { /** * @brief Enumeration for KBKDF counter location relative to fixed input. - * @since_tizen 6.5 + * @since_tizen 6.0 * * @see ckmc_key_derive() * @see #ckmc_param_name_e @@ -463,7 +463,7 @@ typedef enum __ckmc_algo_type { /** * @brief Enumeration for backend identifiers. - * @since_tizen 6.5 + * @since_tizen 6.0 * @see ckmc_get_backend_info() * @see ckmc_alias_info_get_backend() */ @@ -476,7 +476,7 @@ struct __ckmc_backend_info_s; /** * @brief Backend information handle. - * @since_tizen 6.5 + * @since_tizen 6.0 * @see ckmc_alias_info_get_backend() * @see ckmc_get_backend_info() * @see ckmc_backend_get_max_chunk_size() @@ -486,7 +486,7 @@ typedef struct __ckmc_backend_info_s *ckmc_backend_info_h; /** * @brief Encryption/decryption context handle. - * @since_tizen 6.5 + * @since_tizen 6.0 * @see ckmc_cipher_initialize() * @see ckmc_cipher_update() * @see ckmc_cipher_finalize() @@ -525,7 +525,7 @@ int ckmc_alias_info_is_password_protected(const ckmc_alias_info_s* info, /** * @brief Gets the backend identifier from #ckmc_alias_info_s structure. - * @since_tizen 6.5 + * @since_tizen 6.0 * @param[in] info The pointer to the #ckmc_alias_info_s structure * @param[out] backend The pointer to the backend identifier * @return #CKMC_ERROR_NONE on success, otherwise a negative error value @@ -1097,7 +1097,7 @@ int ckmc_generate_new_params(ckmc_algo_type_e type, ckmc_param_list_h *pparams); * @brief Retrieves maximum data chunk size that can be passed to given backend. This is the maximum * size of data passed for encryption/decryption. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @param[in] info Backend info handle * @param[out] size Maximum chunk size @@ -1115,7 +1115,7 @@ int ckmc_backend_get_max_chunk_size(const ckmc_backend_info_h info, size_t* size /** * @brief Destroys the backend information handle and releases all its resources. * - * @since_tizen 6.5 + * @since_tizen 6.0 * * @param[in] info Backend information handle created with ckmc_get_backend_info() * -- 2.7.4 From 801476a2ee32d6f565953defcaf04522de34997e Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 26 May 2023 15:00:58 +0200 Subject: [PATCH 02/16] Alias info refactoring To extract alias backend information, the current structures and mechanisms meant for alias & password protection status extraction have to be modified as follows: * Modify 'join_all_tables' view in db to include 'backendId' and other columns from OBJECTS table. It also requires a db version bump and a migration script * Modify db query that lists aliases to include 'backendId'. * Move AliasSupport to common library so it can be used in DBCrypto. * Replace OwnerNameVector and OwnerNameEncryptionStatusVector with a vector of AliasInfo structures. * Add AliasInfoSerializableVector wrapper to allow AliasInfo (de)serialization. * Modify client to get password protection status during ckmc_alias_info_is_password_protected() instead of checking all accessible aliases one by one. * Modify client to get aliases from AliasInfo vector when other info is not required. * Update unit-tests Change-Id: Ic6741f7329afe858d561cab89d9616a53327a6bd --- data/scripts/CMakeLists.txt | 1 + data/scripts/create_schema.sql | 2 +- data/scripts/migrate_4.sql | 24 +++++++++ misc/db_perf/test_db_perf.cpp | 10 ++-- src/include/ckm/ckm-type.h | 19 ++++++- src/manager/client-async/storage-receiver.cpp | 9 ++-- src/manager/client-capi/ckmc-manager.cpp | 11 ++--- src/manager/client-capi/ckmc-type.cpp | 25 ++++++++-- src/manager/client/client-common.cpp | 38 -------------- src/manager/client/client-common.h | 17 +------ src/manager/client/client-manager-impl.cpp | 61 +++++++---------------- src/manager/client/client-manager-impl.h | 10 ++-- src/manager/common/protocols.cpp | 68 ++++++++++++++++++++++++++ src/manager/common/protocols.h | 25 +++++++++- src/manager/service/ckm-logic.cpp | 47 +++++++++--------- src/manager/service/ckm-logic.h | 4 +- src/manager/service/crypto-logic.h | 2 +- src/manager/service/db-crypto.cpp | 47 +++++++++++------- src/manager/service/db-crypto.h | 8 +-- unit-tests/CMakeLists.txt | 1 + unit-tests/resources/testme0_ver5.db | Bin 0 -> 5341184 bytes unit-tests/test_db_crypto.cpp | 32 ++++++------ 22 files changed, 270 insertions(+), 191 deletions(-) create mode 100644 data/scripts/migrate_4.sql create mode 100644 unit-tests/resources/testme0_ver5.db diff --git a/data/scripts/CMakeLists.txt b/data/scripts/CMakeLists.txt index b4dd0d1..b3ec6a6 100644 --- a/data/scripts/CMakeLists.txt +++ b/data/scripts/CMakeLists.txt @@ -23,4 +23,5 @@ INSTALL(FILES migrate_1.sql migrate_2.sql migrate_3.sql + migrate_4.sql DESTINATION ${RO_DATA_DIR}/scripts) diff --git a/data/scripts/create_schema.sql b/data/scripts/create_schema.sql index 8b66af9..519af1f 100644 --- a/data/scripts/create_schema.sql +++ b/data/scripts/create_schema.sql @@ -63,7 +63,7 @@ CREATE VIEW IF NOT EXISTS [join_name_permission_tables] AS JOIN PERMISSIONS AS P ON P.idx=N.idx; CREATE VIEW IF NOT EXISTS [join_all_tables] AS - SELECT N.*, P.permissionLabel, P.permissionMask, O.dataType FROM NAMES AS N + SELECT N.*, P.permissionLabel, P.permissionMask, O.* FROM NAMES AS N JOIN OBJECTS AS O ON O.idx=N.idx JOIN PERMISSIONS AS P ON P.idx=N.idx; diff --git a/data/scripts/migrate_4.sql b/data/scripts/migrate_4.sql new file mode 100644 index 0000000..65b93cf --- /dev/null +++ b/data/scripts/migrate_4.sql @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +-- update schema +DROP VIEW IF EXISTS join_all_tables; + +CREATE VIEW [join_all_tables] AS + SELECT N.*, P.permissionLabel, P.permissionMask, O.* FROM NAMES AS N + JOIN OBJECTS AS O ON O.idx=N.idx + JOIN PERMISSIONS AS P ON P.idx=N.idx; \ No newline at end of file diff --git a/misc/db_perf/test_db_perf.cpp b/misc/db_perf/test_db_perf.cpp index b48ad18..356636f 100644 --- a/misc/db_perf/test_db_perf.cpp +++ b/misc/db_perf/test_db_perf.cpp @@ -196,8 +196,8 @@ BOOST_AUTO_TEST_CASE(DBperfAliasRemovalWithFullPermissions) // verify everything has been removed for (unsigned l = 0; l < OWNERS; l++) { generate_owner(l, owner); - OwnerNameVector expect_no_data; - BOOST_REQUIRE_NO_THROW(m_db.listNames(owner, expect_no_data, + AliasInfoVector expect_no_data; + BOOST_REQUIRE_NO_THROW(m_db.listInfos(owner, expect_no_data, DataType::BINARY_DATA)); BOOST_REQUIRE(0 == expect_no_data.size()); } @@ -215,13 +215,13 @@ BOOST_AUTO_TEST_CASE(DBperfGetAliasList) unsigned seed = 0; // actual test - random lookup - Perf perf("listNames", ITERATIONS); + Perf perf("listInfos", ITERATIONS); for (unsigned t = 0; t < ITERATIONS; t++) { - OwnerNameVector ret_list; + AliasInfoVector ret_list; generate_owner(rand_r(&seed) % OWNERS, owner); - BOOST_REQUIRE_NO_THROW(m_db.listNames(owner, ret_list, DataType::BINARY_DATA)); + BOOST_REQUIRE_NO_THROW(m_db.listInfos(owner, ret_list, DataType::BINARY_DATA)); BOOST_REQUIRE(NAMES == ret_list.size()); ret_list.clear(); } diff --git a/src/include/ckm/ckm-type.h b/src/include/ckm/ckm-type.h index 72ab1c4..3bbbf03 100644 --- a/src/include/ckm/ckm-type.h +++ b/src/include/ckm/ckm-type.h @@ -43,6 +43,7 @@ typedef std::vector RawBufferVector; * ClientId is optional */ typedef std::string Alias; + /* * ClientId is an identifier of the API caller returned by security-manager(pkgid). * It can be an application or a system component. @@ -50,6 +51,11 @@ typedef std::string Alias; * or just a client in general. */ typedef std::string ClientId; +/* + * Name is an object identifier. It is unique among names of objects owned by given owner (ClientId) + */ +typedef std::string Name; + typedef std::vector AliasVector; // backend identifiers @@ -60,10 +66,19 @@ enum class BackendId : int { }; struct AliasInfo { - bool passwordProtected; + Alias alias; + int type; BackendId backend; + + AliasInfo() : type(0), backend(BackendId::SW) {} + AliasInfo(const Alias& alias, int type, BackendId backend) : + alias(alias), + type(type), + backend(backend) + { + } }; -typedef std::vector> AliasInfoVector; +typedef std::vector AliasInfoVector; enum class KeyType : int { KEY_NONE = 0, diff --git a/src/manager/client-async/storage-receiver.cpp b/src/manager/client-async/storage-receiver.cpp index 8e71e0a..3d42fb6 100644 --- a/src/manager/client-async/storage-receiver.cpp +++ b/src/manager/client-async/storage-receiver.cpp @@ -156,8 +156,9 @@ void StorageReceiver::parseGetListCommand() { DataType dataType; int retCode = 0; - OwnerNameVector ownerNameVector; - m_buffer.Deserialize(retCode, dataType, ownerNameVector); + AliasInfoVector aliasInfoVector; + AliasInfoSerializableVector aisv(aliasInfoVector); + m_buffer.Deserialize(retCode, dataType, aisv); // check error code if (retCode != CKM_API_SUCCESS) { @@ -167,8 +168,8 @@ void StorageReceiver::parseGetListCommand() AliasVector aliasVector; - for (const auto &it : ownerNameVector) - aliasVector.push_back(AliasSupport::merge(it.first, it.second)); + for (const auto &it : aliasInfoVector) + aliasVector.push_back(it.alias); if (dataType.isKey()) m_observer->ReceivedKeyAliasVector(std::move(aliasVector)); diff --git a/src/manager/client-capi/ckmc-manager.cpp b/src/manager/client-capi/ckmc-manager.cpp index 9c9ca34..326685e 100644 --- a/src/manager/client-capi/ckmc-manager.cpp +++ b/src/manager/client-capi/ckmc-manager.cpp @@ -45,7 +45,7 @@ struct CipherCtx }; int _ckmc_alias_info_new(const char* alias, - bool is_password_protected, + int type, ckmc_backend_id_e backend, ckmc_alias_info_s** info) { @@ -66,7 +66,7 @@ int _ckmc_alias_info_new(const char* alias, free(_info); return CKMC_ERROR_OUT_OF_MEMORY; } - _info->is_password_protected = is_password_protected; + _info->type = type; _info->backend = backend; *info = _info; return CKMC_ERROR_NONE; @@ -246,10 +246,9 @@ int _toNewCkmcAliasInfoList(const CKM::AliasInfoVector &aliasInfoVector, if (previous != nullptr) previous->next = plist; - const auto& info = std::get<1>(it); - ret = _ckmc_alias_info_new(std::get<0>(it).c_str(), - info.passwordProtected, - static_cast(info.backend), + ret = _ckmc_alias_info_new(it.alias.c_str(), + it.type, + static_cast(it.backend), &plist->info); if (ret != CKMC_ERROR_NONE) break; diff --git a/src/manager/client-capi/ckmc-type.cpp b/src/manager/client-capi/ckmc-type.cpp index e385355..bd8f5a8 100644 --- a/src/manager/client-capi/ckmc-type.cpp +++ b/src/manager/client-capi/ckmc-type.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -632,10 +632,29 @@ int ckmc_alias_info_is_password_protected(const ckmc_alias_info_s* info, if (info == NULL || is_password_protected == NULL) return CKMC_ERROR_INVALID_PARAMETER; - *is_password_protected = info->is_password_protected; + EXCEPTION_GUARD_START_CAPI + + auto mgr = CKM::Manager::create(); + bool status; + int ret; + CKM::DataType dt(static_cast(info->type)); + if (dt.isBinaryData()) + ret = mgr->getDataEncryptionStatus(info->alias, status); + else if (dt.isKey()) + ret = mgr->getKeyEncryptionStatus(info->alias, status); + else if (dt.isCertificate() || dt.isChainCert()) + ret = mgr->getCertificateEncryptionStatus(info->alias, status); + else + return CKMC_ERROR_SERVER_ERROR; + + if (ret != CKM_API_SUCCESS) + return to_ckmc_error(ret); + + *is_password_protected = status; return CKMC_ERROR_NONE; -} + EXCEPTION_GUARD_END +} KEY_MANAGER_CAPI void ckmc_alias_info_list_all_free(ckmc_alias_info_list_s *first) diff --git a/src/manager/client/client-common.cpp b/src/manager/client/client-common.cpp index e565138..238b2ff 100644 --- a/src/manager/client/client-common.cpp +++ b/src/manager/client/client-common.cpp @@ -171,44 +171,6 @@ int SockRAII::get() const return m_sock; } -AliasSupport::AliasSupport(const Alias &alias) -{ - std::size_t separator_pos = alias.rfind(CKM::ALIAS_SEPARATOR); - - if (separator_pos == Alias::npos) { - m_owner.clear(); - m_name = alias; - } else { - m_owner = alias.substr(0, separator_pos); - m_name = alias.substr(separator_pos + strlen(CKM::ALIAS_SEPARATOR)); - } -} - -Alias AliasSupport::merge(const ClientId &owner, const Name &name) -{ - if (owner.empty()) - return name; - - std::stringstream output; - output << owner << std::string(CKM::ALIAS_SEPARATOR) << name; - return output.str(); -} - -const Name &AliasSupport::getName() const -{ - return m_name; -} - -const ClientId &AliasSupport::getOwner() const -{ - return m_owner; -} - -bool AliasSupport::isOwnerEmpty() const -{ - return m_owner.empty(); -} - ServiceConnection::ServiceConnection(const char *service_interface) { if (service_interface) diff --git a/src/manager/client/client-common.h b/src/manager/client/client-common.h index 98fe38f..fee7183 100644 --- a/src/manager/client/client-common.h +++ b/src/manager/client/client-common.h @@ -45,7 +45,7 @@ extern "C" { struct ckmc_alias_info_s { char* alias; - bool is_password_protected; + int type; ckmc_backend_id_e backend; }; @@ -56,21 +56,6 @@ extern "C" { namespace CKM { -class AliasSupport { -public: - explicit AliasSupport(const Alias &alias); - - const ClientId &getOwner() const; - const Name &getName() const; - bool isOwnerEmpty() const; - - static Alias merge(const ClientId &owner, const Name &alias); - -private: - Name m_name; - ClientId m_owner; -}; - class SockRAII { public: SockRAII(); diff --git a/src/manager/client/client-manager-impl.cpp b/src/manager/client/client-manager-impl.cpp index 9a89839..adf67b6 100644 --- a/src/manager/client/client-manager-impl.cpp +++ b/src/manager/client/client-manager-impl.cpp @@ -359,55 +359,28 @@ int Manager::Impl::getData(const Alias &alias, const Password &password, return recvDataType.isBinaryData() ? CKM_API_SUCCESS : CKM_API_ERROR_BAD_RESPONSE; } -int Manager::Impl::getBinaryDataAliasVectorHelper(DataType dataType, - OwnerNameVector &ownerNameVector) +int Manager::Impl::getAliasInfoVectorHelper(DataType dataType, AliasInfoVector &aliasInfoVector) { DataType tmpDataType; - return Request(*this, LogicCommand::GET_LIST, m_storageConnection, - dataType - ).maybeDeserialize(tmpDataType, ownerNameVector); -} - -int Manager::Impl::getBinaryDataAliasVector(DataType dataType, - AliasVector &aliasVector) -{ - EXCEPTION_GUARD_START_CPPAPI - OwnerNameVector ownerNameVector; - int retCode = getBinaryDataAliasVectorHelper(dataType, ownerNameVector); - - if (retCode != CKM_API_SUCCESS) - return retCode; - - for (const auto &it : ownerNameVector) - aliasVector.push_back(AliasSupport::merge(it.first, it.second)); - - return CKM_API_SUCCESS; - EXCEPTION_GUARD_END + AliasInfoSerializableVector aisv(aliasInfoVector); + return Request(*this, + LogicCommand::GET_LIST, + m_storageConnection, + dataType).maybeDeserialize(tmpDataType, aisv); } -int Manager::Impl::getBinaryDataAliasInfoVector(DataType dataType, - AliasInfoVector &aliasInfoVector) +int Manager::Impl::getAliasVectorHelper(DataType dataType, AliasVector &aliasVector) { EXCEPTION_GUARD_START_CPPAPI - OwnerNameVector ownerNameVector; - OwnerNameEncryptionStatusVector ownerNameEncryptionStatusVector; - int retCode = getBinaryDataAliasVectorHelper(dataType, ownerNameVector); + AliasInfoVector aliasInfoVector; + int retCode = getAliasInfoVectorHelper(dataType, aliasInfoVector); if (retCode != CKM_API_SUCCESS) return retCode; - for (const auto &it : ownerNameVector) - { - Alias alias = AliasSupport::merge(std::get<0>(it), std::get<1>(it)); - bool status; - retCode = getBinaryDataEncryptionStatus(dataType, alias, status); - - if (retCode != CKM_API_SUCCESS) - return retCode; + for (const auto &it : aliasInfoVector) + aliasVector.push_back(it.alias); - // TODO get the actual backend - aliasInfoVector.push_back(std::make_pair(alias, AliasInfo({status, BackendId::SW}))); - } return CKM_API_SUCCESS; EXCEPTION_GUARD_END } @@ -416,22 +389,22 @@ int Manager::Impl::getKeyAliasVector(AliasVector &aliasVector) { // in fact datatype has no meaning here - if not certificate or binary data // then manager decides to list all between DB_KEY_FIRST and DB_KEY_LAST - return getBinaryDataAliasVector(DataType::DB_KEY_LAST, aliasVector); + return getAliasVectorHelper(DataType::DB_KEY_LAST, aliasVector); } int Manager::Impl::getCertificateAliasVector(AliasVector &aliasVector) { - return getBinaryDataAliasVector(DataType::CERTIFICATE, aliasVector); + return getAliasVectorHelper(DataType::CERTIFICATE, aliasVector); } int Manager::Impl::getDataAliasVector(AliasVector &aliasVector) { - return getBinaryDataAliasVector(DataType::BINARY_DATA, aliasVector); + return getAliasVectorHelper(DataType::BINARY_DATA, aliasVector); } int Manager::Impl::getKeyAliasInfoVector(AliasInfoVector &aliasInfoVector) { - return getBinaryDataAliasInfoVector(DataType::DB_KEY_LAST, aliasInfoVector); + return getAliasInfoVectorHelper(DataType::DB_KEY_LAST, aliasInfoVector); } int Manager::Impl::getKeyEncryptionStatus(const Alias &alias, bool &status) @@ -441,7 +414,7 @@ int Manager::Impl::getKeyEncryptionStatus(const Alias &alias, bool &status) int Manager::Impl::getCertificateAliasInfoVector(AliasInfoVector &aliasInfoVector) { - return getBinaryDataAliasInfoVector(DataType::CERTIFICATE, aliasInfoVector); + return getAliasInfoVectorHelper(DataType::CERTIFICATE, aliasInfoVector); } int Manager::Impl::getCertificateEncryptionStatus(const Alias &alias, bool &status) @@ -451,7 +424,7 @@ int Manager::Impl::getCertificateEncryptionStatus(const Alias &alias, bool &stat int Manager::Impl::getDataAliasInfoVector(AliasInfoVector &aliasInfoVector) { - return getBinaryDataAliasInfoVector(DataType::BINARY_DATA, aliasInfoVector); + return getAliasInfoVectorHelper(DataType::BINARY_DATA, aliasInfoVector); } int Manager::Impl::getDataEncryptionStatus(const Alias &alias, bool &status) diff --git a/src/manager/client/client-manager-impl.h b/src/manager/client/client-manager-impl.h index 52ec1cc..e88894e 100644 --- a/src/manager/client/client-manager-impl.h +++ b/src/manager/client/client-manager-impl.h @@ -184,16 +184,12 @@ private: const Alias &alias, bool &status); - int getBinaryDataAliasVector( + int getAliasVectorHelper( DataType sendDataType, AliasVector &aliasVector); - int getBinaryDataAliasVectorHelper( - DataType sendDataType, - OwnerNameVector &ownerNameVector); - - int getBinaryDataAliasInfoVector( - DataType sendDataType, + int getAliasInfoVectorHelper( + DataType dataType, AliasInfoVector &aliasInfoVector); int createKeyPair( diff --git a/src/manager/common/protocols.cpp b/src/manager/common/protocols.cpp index cd31509..3e6503f 100644 --- a/src/manager/common/protocols.cpp +++ b/src/manager/common/protocols.cpp @@ -278,5 +278,73 @@ void CryptoAlgorithmSerializable::Serialize(IStream &stream) const } } + +AliasInfoSerializableVector::AliasInfoSerializableVector(AliasInfoVector &v) : aliasInfoVector(v) +{ +} + +void AliasInfoSerializableVector::Deserialize(IStream &stream) +{ + size_t size; + Deserialization::Deserialize(stream, size); + aliasInfoVector.clear(); + aliasInfoVector.reserve(size); + for (size_t i = 0; i < size; i++) { + AliasInfo ai; + Deserialization::Deserialize(stream, ai.alias); + Deserialization::Deserialize(stream, ai.type); + Deserialization::Deserialize(stream, ai.backend); + aliasInfoVector.push_back(std::move(ai)); + } +} + +void AliasInfoSerializableVector::Serialize(IStream &stream) const +{ + Serialization::Serialize(stream, aliasInfoVector.size()); + for (const auto& ai : aliasInfoVector) { + Serialization::Serialize(stream, ai.alias); + Serialization::Serialize(stream, ai.type); + Serialization::Serialize(stream, ai.backend); + } +} + +AliasSupport::AliasSupport(const Alias &alias) +{ + std::size_t separator_pos = alias.rfind(CKM::ALIAS_SEPARATOR); + + if (separator_pos == Alias::npos) { + m_owner.clear(); + m_name = alias; + } else { + m_owner = alias.substr(0, separator_pos); + m_name = alias.substr(separator_pos + strlen(CKM::ALIAS_SEPARATOR)); + } +} + +Alias AliasSupport::merge(const ClientId &owner, const Name &name) +{ + if (owner.empty()) + return name; + + std::stringstream output; + output << owner << std::string(CKM::ALIAS_SEPARATOR) << name; + return output.str(); +} + +const Name &AliasSupport::getName() const +{ + return m_name; +} + +const ClientId &AliasSupport::getOwner() const +{ + return m_owner; +} + +bool AliasSupport::isOwnerEmpty() const +{ + return m_owner.empty(); +} + } // namespace CKM diff --git a/src/manager/common/protocols.h b/src/manager/common/protocols.h index 5d6a759..b95354f 100644 --- a/src/manager/common/protocols.h +++ b/src/manager/common/protocols.h @@ -85,9 +85,7 @@ COMMON_API extern char const *const ALIAS_SEPARATOR; COMMON_API extern char const *const CLIENT_ID_SYSTEM; COMMON_API extern char const *const CLIENT_ID_ADMIN_USER; -typedef std::string Name; typedef std::vector> OwnerNameVector; -typedef std::vector> OwnerNameEncryptionStatusVector; class IStream; @@ -132,4 +130,27 @@ struct COMMON_API CryptoAlgorithmSerializable final : public CryptoAlgorithm, void Deserialize(IStream &) override; }; +struct COMMON_API AliasInfoSerializableVector : public ISerializable { + explicit AliasInfoSerializableVector(AliasInfoVector &); + void Serialize(IStream &) const override; + void Deserialize(IStream &) override; +private: + AliasInfoVector& aliasInfoVector; +}; + +class COMMON_API AliasSupport { +public: + explicit AliasSupport(const Alias &alias); + + const ClientId &getOwner() const; + const Name &getName() const; + bool isOwnerEmpty() const; + + static Alias merge(const ClientId &owner, const Name &alias); + +private: + Name m_name; + ClientId m_owner; +}; + } // namespace CKM diff --git a/src/manager/service/ckm-logic.cpp b/src/manager/service/ckm-logic.cpp index 0d0a06b..8b6261c 100644 --- a/src/manager/service/ckm-logic.cpp +++ b/src/manager/service/ckm-logic.cpp @@ -930,9 +930,9 @@ RawBuffer CKMLogic::getPKCS12( 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; @@ -940,23 +940,20 @@ int CKMLogic::getDataListHelper(const Credentials &cred, auto &database = m_userDataMap[cred.clientUid].database; retCode = tryRet([&] { - 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; }); } @@ -969,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(); @@ -979,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( diff --git a/src/manager/service/ckm-logic.h b/src/manager/service/ckm-logic.h index 36eb56d..f9a3cb5 100644 --- a/src/manager/service/ckm-logic.h +++ b/src/manager/service/ckm-logic.h @@ -351,10 +351,10 @@ private: bool useTrustedSystemCertificates, RawBufferVector &chainRawVector); - int getDataListHelper( + int getAliasInfoListHelper( const Credentials &cred, const DataType dataType, - OwnerNameVector &ownerNameVector); + AliasInfoVector &aliasInfoVector); void migrateSecureStorageData(bool isAdminUser); diff --git a/src/manager/service/crypto-logic.h b/src/manager/service/crypto-logic.h index aec7352..61f5f36 100644 --- a/src/manager/service/crypto-logic.h +++ b/src/manager/service/crypto-logic.h @@ -23,8 +23,8 @@ #include #include -#include #include +#include namespace CKM { diff --git a/src/manager/service/db-crypto.cpp b/src/manager/service/db-crypto.cpp index d7f7c1c..ceccd69 100644 --- a/src/manager/service/db-crypto.cpp +++ b/src/manager/service/db-crypto.cpp @@ -53,7 +53,7 @@ enum DBVersion : int { * increment and update DB_VERSION_CURRENT, * then provide migration mechanism! */ - DB_VERSION_CURRENT = 4 + DB_VERSION_CURRENT = 5 }; const char *SCRIPT_CREATE_SCHEMA = "create_schema"; @@ -148,8 +148,8 @@ const char *DB_CMD_PERMISSION_DELETE = // SQLite does not support updating views * objects accessible by L1 the query will produce one result (L1, N1) for each allowed * accessor but GROUP BY will reduce them to one so L1 will have (L1, N1) on its list only once */ -const char *DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION = - "SELECT label, name FROM [join_all_tables] " +const char *DB_CMD_INFO_SELECT_BY_TYPE_AND_PERMISSION = + "SELECT label, name, dataType, backendId FROM [join_all_tables] " " WHERE dataType>=?001 AND dataType<=?002 " " AND permissionLabel=?104 AND permissionMask&?004!=0 GROUP BY idx;"; } @@ -618,24 +618,22 @@ void Crypto::getRows( " name ", name, " with owner label ", owner); } -void Crypto::listNames( - const ClientId &owner, - OwnerNameVector &ownerNameVector, - DataType type) +void Crypto::listInfos(const ClientId &owner, + AliasInfoVector &aliasInfoVector, + DataType type) { - listNames(owner, ownerNameVector, type, type); + listInfos(owner, aliasInfoVector, type, type); } -void Crypto::listNames( - const ClientId &owner, - OwnerNameVector &ownerNameVector, - DataType typeRangeStart, - DataType typeRangeStop) +void Crypto::listInfos(const ClientId &owner, + AliasInfoVector &aliasInfoVector, + DataType typeRangeStart, + DataType typeRangeStop) { try { Transaction transaction(this); SqlConnection::DataCommandUniquePtr selectCommand = - m_connection->PrepareDataCommand(DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION); + m_connection->PrepareDataCommand(DB_CMD_INFO_SELECT_BY_TYPE_AND_PERMISSION); selectCommand->BindInteger(1, typeRangeStart); selectCommand->BindInteger(2, typeRangeStop); selectCommand->BindString(104, owner.c_str()); @@ -643,9 +641,24 @@ void Crypto::listNames( static_cast(Permission::READ | Permission::REMOVE)); while (selectCommand->Step()) { - ClientId itemOwner = selectCommand->GetColumnString(0); - Name itemName = selectCommand->GetColumnString(1); - ownerNameVector.push_back(std::make_pair(itemOwner, itemName)); + ClientId owner = selectCommand->GetColumnString(0); + Name name = selectCommand->GetColumnString(1); + int type = selectCommand->GetColumnInteger(2); + auto cryptoBackend = static_cast(selectCommand->GetColumnInteger(3)); + BackendId backendId; + switch (cryptoBackend) { + case CryptoBackend::OpenSSL: + backendId = BackendId::SW; + break; + case CryptoBackend::TrustZone: + backendId = BackendId::TZ; + break; + default: + ThrowErr(Exc::DatabaseFailed, + "Unexpected backend: ", + static_cast(cryptoBackend)); + } + aliasInfoVector.emplace_back(AliasSupport::merge(owner, name), type, backendId); } return; diff --git a/src/manager/service/db-crypto.h b/src/manager/service/db-crypto.h index 1b4ec71..a6f1a1a 100644 --- a/src/manager/service/db-crypto.h +++ b/src/manager/service/db-crypto.h @@ -98,14 +98,14 @@ public: DataType typeRangeStop, RowVector &output); - void listNames( + void listInfos( const ClientId &owner, - OwnerNameVector &ownerNameVector, + AliasInfoVector &aliasInfoVector, DataType type); - void listNames( + void listInfos( const ClientId &owner, - OwnerNameVector &ownerNameVector, + AliasInfoVector &aliasInfoVector, DataType typeRangeStart, DataType typeRangeStop); diff --git a/unit-tests/CMakeLists.txt b/unit-tests/CMakeLists.txt index b862516..139836d 100644 --- a/unit-tests/CMakeLists.txt +++ b/unit-tests/CMakeLists.txt @@ -172,6 +172,7 @@ INSTALL( resources/testme_ver2.db resources/testme_ver3.db resources/testme0_ver4.db + resources/testme0_ver5.db resources/KDFCTR_gen.rsp DESTINATION ${DB_TEST_DIR} ) diff --git a/unit-tests/resources/testme0_ver5.db b/unit-tests/resources/testme0_ver5.db new file mode 100644 index 0000000000000000000000000000000000000000..a81694cddbe2a28c988fff5e3218c58d4ff2888f GIT binary patch literal 5341184 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