From: Andrei Vakulich Date: Thu, 18 Jul 2024 15:18:07 +0000 (+0200) Subject: Added tests for Update API. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c05e4b83b2af0c4f6b249745c7de3c22fdffd909;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git Added tests for Update API. Change-Id: I2948736744093c8d9d47e3af69502f6b4473d9a6 --- diff --git a/src/ckm/ckm-common.cpp b/src/ckm/ckm-common.cpp index f46b128e..1569089b 100644 --- a/src/ckm/ckm-common.cpp +++ b/src/ckm/ckm-common.cpp @@ -135,6 +135,37 @@ std::string CKMCReadableError(int error) { return output; } +CKM::Password toPassword(const char *str) +{ + return str == nullptr ? CKM::Password() : CKM::Password(str); +} + +void ckmSaveKey(const ckmc_key_s& key, const CKM::Alias& alias, + const CKM::Policy& policy, int expected) +{ + callCKMManagerKeyFunc(key, alias, policy, &CKM::Manager::saveKey, expected); +} + +void ckmUpdateKey(const ckmc_key_s& key, const CKM::Alias& alias, + CKM::Policy policy, int expected) +{ + policy.overwritable = true; + callCKMManagerKeyFunc(key, alias, policy, &CKM::Manager::saveKey, expected); +} + +void ckmSaveData(const ckmc_raw_buffer_s& data, const CKM::Alias& alias, + const CKM::Policy& policy, int expected) +{ + callCKMManagerDataFunc(data, alias, policy, &CKM::Manager::saveData, expected); +} + +void ckmUpdateData(const ckmc_raw_buffer_s& data, const CKM::Alias& alias, + CKM::Policy policy, int expected) +{ + policy.overwritable = true; + callCKMManagerDataFunc(data, alias, policy, &CKM::Manager::saveData, expected); +} + void save_data(const char* alias, const char *data, size_t len, const char* password, int expected_err, bool exportable) { @@ -459,6 +490,11 @@ bool isPasswordProtected(const ckmc_policy_s& policy) return policy.password != nullptr; } +bool isPasswordProtected(const CKM::Policy& policy) +{ + return !policy.password.empty(); +} + CKM::BackendId backend() { #ifdef TZ_BACKEND @@ -592,6 +628,21 @@ void compare_AES_keys(ckmc_key_s *first, ckmc_key_s *second) // bypassing password intentionally } +KeyPtr createKeyPtr(ckmc_key_s* key) +{ + return KeyPtr(key, &ckmc_key_free); +} + +CertPtr createCertPtr(ckmc_cert_s* cert) +{ + return CertPtr(cert, &ckmc_cert_free); +} + +PKSC12Ptr createPKCS12Ptr(ckmc_pkcs12_s* pkcs12) +{ + return PKSC12Ptr(pkcs12, &ckmc_pkcs12_free); +} + ParamListPtr createParamListPtr() { ckmc_param_list_h list = NULL; @@ -637,6 +688,42 @@ void assert_keys_equal(const ckmc_key_s* b1, const ckmc_key_s* b2, bool equal) } } +void assert_cert_equal(const ckmc_cert_s* cert1, const ckmc_cert_s* cert2, bool equal) +{ + if(equal) { + RUNNER_ASSERT_MSG(cert1->cert_size == cert2->cert_size, + "Certs size differs: " << cert1->cert_size + << "!=" << cert2->cert_size); + RUNNER_ASSERT_MSG(0 == memcmp(cert1->raw_cert, cert2->raw_cert, + cert1->cert_size), "Certs contents differ"); + } else { + RUNNER_ASSERT_MSG(cert1->cert_size != cert2->cert_size || + 0 != memcmp(cert1->raw_cert, cert2->raw_cert, cert1->cert_size), + "Certs should be different"); + } +} + +void assert_ca_equal(const ckmc_cert_list_s* ca1, const ckmc_cert_list_s* ca2) +{ + size_t length1 = getListLength(ca1), length2 = getListLength(ca2); + RUNNER_ASSERT_MSG(length1 == length2, "The chain certificates size differs " + << length1 << " != " << length2); + + while (ca1) + { + assert_cert_equal(ca1->cert, ca2->cert); + ca1 = ca1->next; + ca2 = ca2->next; + } +} + +void assert_pkcs12_equal(const ckmc_pkcs12_s* pkcs12_1, const ckmc_pkcs12_s* pkcs12_2) +{ + assert_keys_equal(pkcs12_1->priv_key, pkcs12_2->priv_key); + assert_cert_equal(pkcs12_1->cert, pkcs12_2->cert); + assert_ca_equal(pkcs12_1->ca_chain, pkcs12_2->ca_chain); +} + void assert_key_type_equal(const ckmc_key_type_e t1, const ckmc_key_type_e t2) { RUNNER_ASSERT_MSG(t1 == t2, diff --git a/src/ckm/ckm-common.h b/src/ckm/ckm-common.h index 05b7e003..d7efa38b 100644 --- a/src/ckm/ckm-common.h +++ b/src/ckm/ckm-common.h @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -61,12 +63,89 @@ void assert_positive(F&& func, Args... args) assert_result(CKMC_ERROR_NONE, std::move(func), args...); } +template +void assert_db_alias_unknown(Func&& func, Args&&... args) +{ + assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN, std::forward(func), + std::forward(args)...); +} + template -void assert_invalid_param(F&& func, Args... args) +void assert_invalid_param(F&& func, Args&&... args) { assert_result(CKMC_ERROR_INVALID_PARAMETER, std::move(func), args...); } +// RUNNER_ERROR_MSG wrappers +template +void error_msg_result(int expected, Func&& func, Args&&... args) +{ + int ret = std::invoke(std::forward(func), std::forward(args)...); + if (ret != expected) + { + RUNNER_ERROR_MSG("Expected: " << CKMCErrorToString(expected) << "(" << expected << ")" + " got: " << CKMCErrorToString(ret) << "(" << ret << ")"); + } +} + +template +void error_msg_positive(Func&& func, Args&&... args) +{ + error_msg_result(CKMC_ERROR_NONE, std::forward(func), std::forward(args)...); +} + +// RUNNER_ASSERT wrappers for CKM error codes +template +void ckm_assert_result(int expected, Func&& func, Args&&... args) +{ + int ret = std::invoke(std::forward(func), std::forward(args)...); + RUNNER_ASSERT_MSG(ret == expected, + "Expected: " << CKM::APICodeToString(expected) << "(" << expected << ")" + " got: " << CKM::APICodeToString(ret) << "(" << ret << ")"); +} + +CKM::Password toPassword(const char *str); + +template +void callCKMManagerKeyFunc(const ckmc_key_s& key, const CKM::Alias& alias, + const CKM::Policy& policy, Func&& func, int expected = CKMC_ERROR_NONE) +{ + CKM::RawBuffer buffer(key.raw_key, key.raw_key + key.key_size); + CKM::KeyShPtr ckmKey; + if (key.key_type == CKMC_KEY_AES) + { + ckmKey = CKM::Key::createAES(buffer); + } else if (key.key_type == CKMC_KEY_KEM_PRIVATE) { + ckmKey = CKM::Key::createKEM(CKM::KeyType::KEY_KEM_PRIVATE, + buffer, toPassword(key.password)); + } else if (key.key_type == CKMC_KEY_KEM_PUBLIC) { + ckmKey = CKM::Key::createKEM(CKM::KeyType::KEY_KEM_PUBLIC, + buffer, toPassword(key.password)); + } else { + ckmKey = CKM::Key::create(buffer, toPassword(key.password)); + } + ckm_assert_result(expected, std::forward(func), *CKM::Manager::create(), + alias.c_str(), ckmKey, policy); +} + +void ckmSaveKey(const ckmc_key_s& key, const CKM::Alias& alias, + const CKM::Policy& policy, int expected = CKMC_ERROR_NONE); +void ckmUpdateKey(const ckmc_key_s& key, const CKM::Alias& alias, + CKM::Policy policy, int expected = CKMC_ERROR_NONE); + +template +void callCKMManagerDataFunc(const ckmc_raw_buffer_s& data, const CKM::Alias& alias, + const CKM::Policy& policy, Func&& func, int expected = CKMC_ERROR_NONE) +{ + CKM::RawBuffer buffer(data.data, data.data + data.size); + ckm_assert_result(expected, std::forward(func), *CKM::Manager::create(), + alias.c_str(), buffer, policy); +} + +void ckmSaveData(const ckmc_raw_buffer_s& data, const CKM::Alias& alias, + const CKM::Policy& policy, int expected = CKMC_ERROR_NONE); +void ckmUpdateData(const ckmc_raw_buffer_s& data, const CKM::Alias& alias, + CKM::Policy policy, int expected = CKMC_ERROR_NONE); // list operations template @@ -94,6 +173,7 @@ void save_data(const char* alias, const char *data, int expected_err = CKMC_ERRO bool exportable = true); void save_data(const char* alias, const char *data, size_t len, int expected_err = CKMC_ERROR_NONE, bool exportable = true); + class ScopedSaveData { public: @@ -158,6 +238,7 @@ CKM::BackendId get_self_key_alias_backend(const std::string& key); CKM::BackendId get_self_data_alias_backend(const std::string& key); bool isPasswordProtected(const ckmc_policy_s&); +bool isPasswordProtected(const CKM::Policy&); struct Info { Info(const CKM::Alias &alias, @@ -172,6 +253,11 @@ struct Info { const CKM::BackendId backend = CKM::BackendId::SW) : Info(alias, isPasswordProtected(policy), backend) {} + Info(const CKM::Alias &alias, + const CKM::Policy &policy, + const CKM::BackendId backend = CKM::BackendId::SW) : + Info(alias, isPasswordProtected(policy), backend) {} + Info(const CKM::Alias &alias, const ckmc_policy_s &policy, const CKM::Alias &aliasWithSameBackend, @@ -267,6 +353,16 @@ void check_self_data_alias_info_list(const bool shouldHaveSameSize, std::forward(args)...); } +template +void check_self_certificate_alias_info_list(const bool shouldHaveSameSize, + Args&&... args) +{ + check_alias_info_list(ckmc_get_cert_alias_info_list, + getOwnerIdFromSelf(), + shouldHaveSameSize, + std::forward(args)...); +} + template CKM::BackendId get_alias_backend(Func&& getAliasInfoList, const std::string &userSmackLabel, @@ -355,15 +451,40 @@ typedef std::shared_ptr RawBufferPtr; typedef std::shared_ptr ParamListPtr; typedef std::shared_ptr CipherCtxPtr; +using KeyPtr = std::unique_ptr; +KeyPtr createKeyPtr(ckmc_key_s* key); + +using CertPtr = std::unique_ptr; +CertPtr createCertPtr(ckmc_cert_s* cert); + +using PKSC12Ptr = std::unique_ptr; +PKSC12Ptr createPKCS12Ptr(ckmc_pkcs12_s* pkcs12); + ParamListPtr createParamListPtr(); void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer); void setParam(ParamListPtr& params, ckmc_param_name_e name, uint64_t integer); void assert_buffers_equal(const ckmc_raw_buffer_s* b1, const ckmc_raw_buffer_s* b2, bool equal=true); void assert_keys_equal(const ckmc_key_s* b1, const ckmc_key_s* b2, bool equal=true); +void assert_cert_equal(const ckmc_cert_s* cert1, const ckmc_cert_s* cert2, bool equal=true); +void assert_ca_equal(const ckmc_cert_list_s* ca1, const ckmc_cert_list_s* ca2); +void assert_pkcs12_equal(const ckmc_pkcs12_s* pkcs12_1, const ckmc_pkcs12_s* pkcs12_2); + void assert_key_type_equal(const ckmc_key_type_e t1, const ckmc_key_type_e t2); void assert_key_valid(const ckmc_key_s* k, size_t valid_key_size); +template +size_t getListLength(T* head) +{ + size_t length = 0; + while (head) + { + ++length; + head = head->next; + } + return length; +} + RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer); CipherCtxPtr create_cipher_ctx(ckmc_cipher_ctx_h ctx); diff --git a/src/ckm/privileged/capi-access_control.cpp b/src/ckm/privileged/capi-access_control.cpp index 905198ef..12891df4 100644 --- a/src/ckm/privileged/capi-access_control.cpp +++ b/src/ckm/privileged/capi-access_control.cpp @@ -735,6 +735,134 @@ RUNNER_CHILD_TEST(T3111_control_deny_access_as_user, RemoveDataEnv) "Ordinary user should not be able to use control API. Error " << CKMCErrorToString(ret)); } +// tries to use update API from another app +RUNNER_CHILD_TEST(T3112_control_allow_update_as_user, RemoveDataEnv) +{ + ScopedDBUnlock unlock(USER_ID_1, APP_PASS_1); + ckmc_policy_s policy { nullptr, true }; + ckmc_raw_buffer_s data { (unsigned char*)TEST_DATA, strlen(TEST_DATA) }; + + // prepare: add data + { + ScopedAppContext ctx(APP_LABEL_1, USER_ID_1, GROUP_ID_1); + save_data(TEST_ALIAS, TEST_DATA); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_2, GROUP_ID_2); + assert_result(CKMC_ERROR_PERMISSION_DENIED, ckmc_update_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + data, policy); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_2, GROUP_ID_1); + assert_result(CKMC_ERROR_PERMISSION_DENIED, ckmc_update_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + data, policy); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_1, GROUP_ID_1); + assert_result(CKMC_ERROR_PERMISSION_DENIED, ckmc_update_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + data, policy); + } + + // add data permissions + { + ScopedAppContext ctx(APP_LABEL_1, USER_ID_1, GROUP_ID_1); + assert_positive(ckmc_set_permission, aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + APP_LABEL_2, CKMC_PERMISSION_REMOVE | CKMC_PERMISSION_READ); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_1, GROUP_ID_1); + assert_result(CKMC_ERROR_PERMISSION_DENIED, ckmc_update_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + data, policy); + } +} + +// tries to get data after updating it from another app +RUNNER_CHILD_TEST(T3113_control_allow_access_after_update_as_user, RemoveDataEnv) +{ + ScopedDBUnlock unlock(USER_ID_1, APP_PASS_1); + ckmc_policy_s policy { nullptr, true }; + + // prepare: add data + { + ScopedAppContext ctx(APP_LABEL_1, USER_ID_1, GROUP_ID_1); + save_data(TEST_ALIAS, TEST_DATA); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_1, GROUP_ID_1); + ckmc_raw_buffer_s* data = nullptr; + assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN, ckmc_get_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + policy.password, &data); + } + + // add data permissions + { + ScopedAppContext ctx(APP_LABEL_1, USER_ID_1, GROUP_ID_1); + assert_positive(ckmc_set_permission, aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + APP_LABEL_2, CKMC_PERMISSION_READ); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_1, GROUP_ID_1); + ckmc_raw_buffer_s* data = nullptr; + assert_positive(ckmc_get_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + policy.password, &data); + ckmc_buffer_free(data); + } + + // update + { + ScopedAppContext ctx(APP_LABEL_1, USER_ID_1, GROUP_ID_1); + ckmc_raw_buffer_s data { (unsigned char*)TEST_DATA, strlen(TEST_DATA) }; + assert_positive(ckmc_update_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + data, policy); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_1, GROUP_ID_1); + ckmc_raw_buffer_s* data = nullptr; + assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN, ckmc_get_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + policy.password, &data); + ckmc_buffer_free(data); + } + + // add data permissions + { + ScopedAppContext ctx(APP_LABEL_1, USER_ID_1, GROUP_ID_1); + assert_positive(ckmc_set_permission, aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + APP_LABEL_2, CKMC_PERMISSION_READ); + } + + // test + { + ScopedAppContext ctx(APP_LABEL_2, USER_ID_1, GROUP_ID_1); + ckmc_raw_buffer_s* data = nullptr; + assert_positive(ckmc_get_data, + aliasWithLabel(APP_LABEL_1, TEST_ALIAS).c_str(), + policy.password, &data); + ckmc_buffer_free(data); + } +} + // tries to read other application data with permission RUNNER_TEST(T3121_control_access_allowed, RemoveDataEnv) { diff --git a/src/ckm/unprivileged/CMakeLists.txt b/src/ckm/unprivileged/CMakeLists.txt index ba699506..58a243d6 100644 --- a/src/ckm/unprivileged/CMakeLists.txt +++ b/src/ckm/unprivileged/CMakeLists.txt @@ -27,6 +27,7 @@ SET(CKM_SOURCES sign-verify.cpp key-wrapping.cpp key-derivation.cpp + update-api.cpp main.cpp ) diff --git a/src/ckm/unprivileged/update-api.cpp b/src/ckm/unprivileged/update-api.cpp new file mode 100644 index 00000000..c2adea44 --- /dev/null +++ b/src/ckm/unprivileged/update-api.cpp @@ -0,0 +1,2173 @@ +/* + * Copyright (c) 2024 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 + * + * + * @file update-api.cpp + * @author Andrei Vakulich (a.vakulich@samsung.com) + * @version 1.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace CKM; + +namespace { + +const char* USER_PASSWORD = "db-password"; + +class OwnerUserEnv : public RemoveDataEnv +{ +public: + void Init() { + RemoveDataEnv::init(""); + error_msg_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASSWORD); + } + void Finish() { + // lock is performed by remove_user_data() in RemoveDataEnv + RemoveDataEnv::finish(); + } +}; + +const PolicyBackend TZ_BACKEND_ID = +#ifdef TZ_BACKEND + PolicyBackend::FORCE_HARDWARE; +#else + PolicyBackend::FORCE_SOFTWARE; +#endif +const PolicyBackend SW_BACKEND_ID = PolicyBackend::FORCE_SOFTWARE; + +Policy TZ_POLICY(Password(), false, TZ_BACKEND_ID); +Policy SW_POLICY(Password("sw-policy"), false, SW_BACKEND_ID); + +const ckmc_policy_s NON_EXPORTABLE_POLICY { nullptr, false }; +const ckmc_policy_s NON_EXPORTABLE_PASSWORD_POLICY_0 { + const_cast("non-exportable-password-0"), false }; +const ckmc_policy_s NON_EXPORTABLE_PASSWORD_POLICY_1 { + const_cast("non-exportable-password-1"), false }; +const ckmc_policy_s EXPORTABLE_POLICY { nullptr, true }; +const ckmc_policy_s EXPORTABLE_PASSWORD_POLICY_0 { + const_cast("exportable-password-1"), true }; +const ckmc_policy_s EXPORTABLE_PASSWORD_POLICY_1 { + const_cast("exportable-password-2"), true }; + +unsigned char WRONG_RAW_DATA[] = "wrong-raw-data"; + +struct KeyCtx +{ + const char* alias; + KeyPtr key; + ckmc_policy_s policy; +}; + +struct AsymmetricKey +{ + KeyCtx privateKey; + KeyCtx publicKey; +}; + +template +void saveUpdateAsymmetricKeyHelper(const char *privateKeyAlias, const char *publicKeyAlias, + const ckmc_policy_s &policy, Keys& keys, Func&& func) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias, publicKeyAlias }; + + assert_positive(ckmc_save_key, privateKeyAlias, + *keys[0].privateKey.key, policy); + assert_positive(ckmc_save_key, publicKeyAlias, + *keys[0].publicKey.key, policy); + + assert_positive(ckmc_update_key, privateKeyAlias, + *keys[1].privateKey.key, policy); + assert_positive(ckmc_update_key, publicKeyAlias, + *keys[1].publicKey.key, policy); + + std::forward(func)(privateKeyAlias, policy.password, + publicKeyAlias, policy.password); + std::forward(func)(privateKeyAlias, policy.password, + keys[1].publicKey.alias, keys[1].publicKey.policy.password); +} + +template +void updateUpdateAsymmetricKeyHelper(const char *privateKeyAlias, const char *publicKeyAlias, + const ckmc_policy_s &policy, Keys& keys, Func&& func) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias, publicKeyAlias }; + + assert_positive(ckmc_update_key, privateKeyAlias, + *keys[0].privateKey.key, policy); + assert_positive(ckmc_update_key, publicKeyAlias, + *keys[0].publicKey.key, policy); + + std::forward(func)(privateKeyAlias, policy.password, + publicKeyAlias, policy.password); + std::forward(func)(privateKeyAlias, policy.password, + keys[0].publicKey.alias, keys[0].publicKey.policy.password); + + assert_positive(ckmc_update_key, privateKeyAlias, + *keys[1].privateKey.key, policy); + assert_positive(ckmc_update_key, publicKeyAlias, + *keys[1].publicKey.key, policy); + + std::forward(func)(privateKeyAlias, policy.password, + publicKeyAlias, policy.password); + std::forward(func)(privateKeyAlias, policy.password, + keys[1].publicKey.alias, keys[1].publicKey.policy.password); +} + +template +void saveUpdateAsymmetricKeyWithAnotherExportabilityHelper( + const char *privateKeyAlias, const char *publicKeyAlias, Keys& keys, Func&& func) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias, publicKeyAlias }; + + assert_positive(ckmc_save_key, privateKeyAlias, + *keys[0].privateKey.key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_save_key, publicKeyAlias, + *keys[0].publicKey.key, NON_EXPORTABLE_POLICY); + + check_self_key_alias_info_list(false, + Info(privateKeyAlias, NON_EXPORTABLE_POLICY, backend()), + Info(publicKeyAlias, NON_EXPORTABLE_POLICY, backend())); + + + assert_positive(ckmc_update_key, privateKeyAlias, + *keys[1].privateKey.key, EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, publicKeyAlias, + *keys[1].publicKey.key, EXPORTABLE_POLICY); + + check_self_key_alias_info_list(false, + Info(privateKeyAlias, EXPORTABLE_POLICY, + CKM::BackendId::SW), + Info(publicKeyAlias, EXPORTABLE_POLICY, + CKM::BackendId::SW)); + + std::forward(func)(privateKeyAlias, EXPORTABLE_POLICY.password, + publicKeyAlias, EXPORTABLE_POLICY.password); + std::forward(func)(privateKeyAlias, NON_EXPORTABLE_POLICY.password, + keys[1].publicKey.alias, keys[1].publicKey.policy.password); + + ckmc_key_s *key = nullptr; + assert_positive(ckmc_get_key, privateKeyAlias, EXPORTABLE_POLICY.password, &key); + auto keyPtr = createKeyPtr(key); + assert_keys_equal(key, keys[1].privateKey.key.get()); +} + +template +void saveUpdateAsymmetricKeyWithAnotherPasswordHelper( + const char *privateKeyAlias, const char *publicKeyAlias, Keys& keys, Func&& func) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias, publicKeyAlias }; + + assert_positive(ckmc_save_key, privateKeyAlias, + *keys[0].privateKey.key, EXPORTABLE_POLICY); + assert_positive(ckmc_save_key, publicKeyAlias, + *keys[0].publicKey.key, EXPORTABLE_POLICY); + + assert_positive(ckmc_update_key, privateKeyAlias, + *keys[1].privateKey.key, EXPORTABLE_PASSWORD_POLICY_0); + assert_positive(ckmc_update_key, publicKeyAlias, + *keys[1].publicKey.key, EXPORTABLE_PASSWORD_POLICY_0); + + std::forward(func)(privateKeyAlias, EXPORTABLE_PASSWORD_POLICY_0.password, + publicKeyAlias, EXPORTABLE_PASSWORD_POLICY_0.password); + std::forward(func)(privateKeyAlias, EXPORTABLE_PASSWORD_POLICY_0.password, + keys[1].publicKey.alias, keys[1].publicKey.policy.password); + + assert_positive(ckmc_update_key, privateKeyAlias, + *keys[2].privateKey.key, EXPORTABLE_PASSWORD_POLICY_1); + assert_positive(ckmc_update_key, publicKeyAlias, + *keys[2].publicKey.key, EXPORTABLE_PASSWORD_POLICY_1); + + std::forward(func)(privateKeyAlias, EXPORTABLE_PASSWORD_POLICY_1.password, + publicKeyAlias, EXPORTABLE_PASSWORD_POLICY_1.password); + std::forward(func)(privateKeyAlias, EXPORTABLE_PASSWORD_POLICY_1.password, + keys[2].publicKey.alias, keys[2].publicKey.policy.password); +} + +template +void saveUpdateAsymmetricKeyWithAnotherBackendHelper( + const char *privateKeyAlias, const char *publicKeyAlias, Keys& keys, Func&& func) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias, publicKeyAlias }; + + ckmSaveKey(*keys[0].privateKey.key, privateKeyAlias, TZ_POLICY); + ckmSaveKey(*keys[0].publicKey.key, publicKeyAlias, TZ_POLICY); + + check_self_key_alias_info_list(false, + Info(privateKeyAlias, TZ_POLICY, backend()), + Info(publicKeyAlias, TZ_POLICY, backend())); + + ckmUpdateKey(*keys[1].privateKey.key, privateKeyAlias, SW_POLICY); + ckmUpdateKey(*keys[1].publicKey.key, publicKeyAlias, SW_POLICY); + + check_self_key_alias_info_list(false, + Info(privateKeyAlias, SW_POLICY, CKM::BackendId::SW), + Info(publicKeyAlias, SW_POLICY, CKM::BackendId::SW)); + + std::forward(func)(privateKeyAlias, SW_POLICY.password.c_str(), + publicKeyAlias, SW_POLICY.password.c_str()); + std::forward(func)(privateKeyAlias, SW_POLICY.password.c_str(), + keys[1].publicKey.alias, keys[1].publicKey.policy.password); + + ckmUpdateKey(*keys[2].privateKey.key, privateKeyAlias, TZ_POLICY); + ckmUpdateKey(*keys[2].publicKey.key, publicKeyAlias, TZ_POLICY); + + check_self_key_alias_info_list(false, + Info(privateKeyAlias, TZ_POLICY, backend()), + Info(publicKeyAlias, TZ_POLICY, backend())); + + std::forward(func)(privateKeyAlias, TZ_POLICY.password.c_str(), + publicKeyAlias, TZ_POLICY.password.c_str()); + std::forward(func)(privateKeyAlias, TZ_POLICY.password.c_str(), + keys[2].publicKey.alias, keys[2].publicKey.policy.password); +} + +template +void saveUpdateAsymmetricKeyWithInvalidParametersHelper( + const char *privateKeyAlias, const ckmc_policy_s &policy, Keys& keys) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias }; + + assert_positive(ckmc_save_key, privateKeyAlias, + *keys[0].privateKey.key, policy); + + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, nullptr, + *keys[1].privateKey.key, policy); + + auto wrongKey = *keys[0].privateKey.key; + wrongKey.key_size = 0; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, privateKeyAlias, + wrongKey, NON_EXPORTABLE_POLICY); + + wrongKey.key_size = keys[0].privateKey.key->key_size; + wrongKey.raw_key = nullptr; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, privateKeyAlias, + wrongKey, NON_EXPORTABLE_POLICY); +} + +template +void saveUpdateAsymmetricKeyWithLockedDBHelper( + const char *privateKeyAlias, Keys& keys) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias }; + + assert_positive(ckmc_save_key, privateKeyAlias, + *keys[0].privateKey.key, NON_EXPORTABLE_POLICY); + + assert_positive(ckmc_lock_user_key, OWNER_USER_ID); + assert_result(CKMC_ERROR_DB_LOCKED, ckmc_update_key, privateKeyAlias, + *keys[1].privateKey.key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASSWORD); +} + +template +void saveUpdateAsymmetricKeyWithWrongKeyHelper( + const char *privateKeyAlias, Keys& keys, ckmc_key_type_e type) +{ + AliasRemover aliasRemovers[] = { privateKeyAlias }; + + assert_positive(ckmc_save_key, privateKeyAlias, + *keys[0].privateKey.key, NON_EXPORTABLE_POLICY); + + ckmc_key_s wrongKey = { + WRONG_RAW_DATA, std::size(WRONG_RAW_DATA), type, nullptr + }; + assert_result(CKMC_ERROR_INVALID_FORMAT, ckmc_update_key, privateKeyAlias, + wrongKey, NON_EXPORTABLE_POLICY); +} + +} // namespace anonymous + +namespace { + +const size_t RSA_KEY_SIZE = 1024; + +std::array rsaKeys = { { + { + KeyCtx{ "RSA_PRIVATE_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "RSA_PUBLIC_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "RSA_PRIVATE_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "RSA_PUBLIC_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "RSA_PRIVATE_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "RSA_PUBLIC_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY } + } +} }; + +const char* RSA_PRIVATE_KEY_ALIAS = "RSA_PRIVATE_KEY"; +const char* RSA_PUBLIC_KEY_ALIAS = "RSA_PUBLIC_KEY"; + +void checkRSAKeysMatching(const char* privateAlias, const char* privatePassword, + const char* publicAlias, const char* publicPassword) +{ + auto plain = create_raw_buffer(createRandomBufferCAPI(86)); + + auto params = createParamListPtr(); + setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_RSA_OAEP); + setParam(params, CKMC_PARAM_ED_OAEP_HASH, CKMC_HASH_SHA1); + + ckmc_raw_buffer_s* encrypted = nullptr; + assert_positive(ckmc_encrypt_data, params.get(), publicAlias, + publicPassword, *plain.get(), &encrypted); + auto encryptedPtr = create_raw_buffer(encrypted); + + ckmc_raw_buffer_s* decrypted = nullptr; + assert_positive(ckmc_decrypt_data, params.get(), privateAlias, + privatePassword, *encrypted, &decrypted); + auto decryptedPtr = create_raw_buffer(decrypted); + + assert_buffers_equal(plain.get(), decrypted); +} + +class RSAKeys +{ +public: + void Init() + { + for (auto& rsaKey : rsaKeys) + { + error_msg_positive(ckmc_create_key_pair_rsa, RSA_KEY_SIZE, + rsaKey.privateKey.alias, rsaKey.publicKey.alias, + rsaKey.privateKey.policy, rsaKey.privateKey.policy); + + ckmc_key_s *key = nullptr; + error_msg_positive(ckmc_get_key, rsaKey.privateKey.alias, + rsaKey.privateKey.policy.password, &key); + rsaKey.privateKey.key = createKeyPtr(key); + + key = nullptr; + error_msg_positive(ckmc_get_key, rsaKey.publicKey.alias, + rsaKey.publicKey.policy.password, &key); + rsaKey.publicKey.key = createKeyPtr(key); + } + } + + void Finish() + { + for (const auto& key : rsaKeys) + { + error_msg_positive(ckmc_remove_alias, key.privateKey.alias); + error_msg_positive(ckmc_remove_alias, key.publicKey.alias); + } + } +}; + +class RSAKeysTestGroup : public RSAKeys, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + RSAKeys::Init(); + } + + void Finish() override + { + RSAKeys::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_RSA_KEYS, RSAKeysTestGroup); + +RUNNER_TEST(TUA_0010_save_update_RSA_key) +{ + saveUpdateAsymmetricKeyHelper(RSA_PRIVATE_KEY_ALIAS, RSA_PUBLIC_KEY_ALIAS, + NON_EXPORTABLE_POLICY, rsaKeys, checkRSAKeysMatching); +} + +RUNNER_TEST(TUA_0011_update_update_RSA_key) +{ + updateUpdateAsymmetricKeyHelper(RSA_PRIVATE_KEY_ALIAS, RSA_PUBLIC_KEY_ALIAS, + NON_EXPORTABLE_POLICY, rsaKeys, checkRSAKeysMatching); +} + +RUNNER_TEST(TUA_0012_save_update_RSA_key_with_another_exportability) +{ + saveUpdateAsymmetricKeyWithAnotherExportabilityHelper(RSA_PRIVATE_KEY_ALIAS, + RSA_PUBLIC_KEY_ALIAS, + rsaKeys, checkRSAKeysMatching); +} + +RUNNER_TEST(TUA_0013_save_update_RSA_key_with_another_password) +{ + saveUpdateAsymmetricKeyWithAnotherPasswordHelper(RSA_PRIVATE_KEY_ALIAS, RSA_PUBLIC_KEY_ALIAS, + rsaKeys, checkRSAKeysMatching); +} + +RUNNER_TEST(TUA_0014_save_update_RSA_key_with_another_backend) +{ + saveUpdateAsymmetricKeyWithAnotherBackendHelper(RSA_PRIVATE_KEY_ALIAS, RSA_PUBLIC_KEY_ALIAS, + rsaKeys, checkRSAKeysMatching); +} + +RUNNER_TEST(TUA_0015_save_update_RSA_key_with_invalid_parameters) +{ + saveUpdateAsymmetricKeyWithInvalidParametersHelper(RSA_PRIVATE_KEY_ALIAS, + NON_EXPORTABLE_POLICY, rsaKeys); +} + +RUNNER_TEST(TUA_0016_save_update_RSA_key_with_locked_db) +{ + saveUpdateAsymmetricKeyWithLockedDBHelper(RSA_PRIVATE_KEY_ALIAS, rsaKeys); +} + +RUNNER_TEST(TUA_0017_save_update_wrong_RSA_key) +{ + saveUpdateAsymmetricKeyWithWrongKeyHelper(RSA_PRIVATE_KEY_ALIAS, rsaKeys, + CKMC_KEY_RSA_PRIVATE); +} + +namespace { + +struct Algo { + ckmc_algo_type_e type; + size_t initVector; +}; + +const Algo KEM_ALGO = { CKMC_ALGO_KEM, 0 }; +const ckmc_kem_type_e KEM_TYPE = ckmc_kem_type_e::CKMC_ML_KEM_768; +const Algo AES_CBC_ALGO = {CKMC_ALGO_AES_CBC, 16}; + +std::array kemKeys = { { + { + KeyCtx{ "KEM_PRIVATE_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "KEM_PUBLIC_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "KEM_PRIVATE_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "KEM_PUBLIC_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "KEM_PRIVATE_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "KEM_PUBLIC_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY } + } +} }; + +const char* KEM_PRIVATE_KEY_ALIAS = "KEM_PRIVATE_KEY"; +const char* KEM_PUBLIC_KEY_ALIAS = "KEM_PUBLIC_KEY"; +const char* ENCAPSULATED_SECRET_ALIAS = "ENCAPSULATED_SECRET"; +const char* DECAPSULATED_SECRET_ALIAS = "DECAPSULATED_SECRET"; + +ParamListPtr getDefaultParams(const Algo &algo) { + ckmc_param_list_h handle = nullptr; + + assert_positive(ckmc_generate_new_params, algo.type, &handle); + auto params = ParamListPtr(handle, ckmc_param_list_free); + + if (algo.initVector) { + setParam(params, CKMC_PARAM_ED_IV, createRandomBufferCAPI(algo.initVector)); + } + + return params; +} + +void checkKEMKeysMatching(const char* privateAlias, const char* privateKeyPassword, + const char* publicAlias, const char* publicKeyPassword) +{ + AliasRemover removers[] = { ENCAPSULATED_SECRET_ALIAS, DECAPSULATED_SECRET_ALIAS }; + + auto params = getDefaultParams(KEM_ALGO); + setParam(params, CKMC_PARAM_KEM_TYPE, KEM_TYPE); + + ckmc_raw_buffer_s *ciphertext = nullptr; + + assert_positive(ckmc_encapsulate_key, + params.get(), + publicAlias, + publicKeyPassword, + ENCAPSULATED_SECRET_ALIAS, + NON_EXPORTABLE_POLICY, + &ciphertext); + + auto ciphertextPtr = create_raw_buffer(ciphertext); + + assert_positive(ckmc_decapsulate_key, + params.get(), + privateAlias, + privateKeyPassword, + DECAPSULATED_SECRET_ALIAS, + NON_EXPORTABLE_POLICY, + ciphertext); + + auto plain = create_raw_buffer(createRandomBufferCAPI(32)); + params = getDefaultParams(AES_CBC_ALGO); + + ckmc_raw_buffer_s *encrypted = nullptr; + assert_positive(ckmc_encrypt_data, + params.get(), + ENCAPSULATED_SECRET_ALIAS, + NON_EXPORTABLE_POLICY.password, + *plain.get(), + &encrypted); + auto encryptedPtr = create_raw_buffer(encrypted); + + ckmc_raw_buffer_s *decrypted = nullptr; + assert_positive(ckmc_decrypt_data, + params.get(), + DECAPSULATED_SECRET_ALIAS, + NON_EXPORTABLE_POLICY.password, + *encrypted, + &decrypted); + auto decryptedPtr = create_raw_buffer(decrypted); + + assert_buffers_equal(plain.get(), decrypted); +} + +class KEMKeys +{ +public: + void Init() + { + for (auto& kemKey : kemKeys) + { + error_msg_positive(ckmc_create_key_pair_kem, KEM_TYPE, + kemKey.privateKey.alias, kemKey.publicKey.alias, + kemKey.privateKey.policy, kemKey.privateKey.policy); + + ckmc_key_s *key = nullptr; + error_msg_positive(ckmc_get_key, kemKey.privateKey.alias, + kemKey.privateKey.policy.password, &key); + kemKey.privateKey.key = createKeyPtr(key); + + key = nullptr; + error_msg_positive(ckmc_get_key, kemKey.publicKey.alias, + kemKey.publicKey.policy.password, &key); + kemKey.publicKey.key = createKeyPtr(key); + } + } + + void Finish() + { + for (const auto& key : kemKeys) + { + error_msg_positive(ckmc_remove_alias, key.privateKey.alias); + error_msg_positive(ckmc_remove_alias, key.publicKey.alias); + } + } +}; + +class KEMKeysTestGroup : public KEMKeys, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + KEMKeys::Init(); + } + + void Finish() override + { + KEMKeys::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_KEM_KEYS, KEMKeysTestGroup); + +RUNNER_TEST(TUA_0020_save_update_KEM_key) +{ + saveUpdateAsymmetricKeyHelper(KEM_PRIVATE_KEY_ALIAS, KEM_PUBLIC_KEY_ALIAS, + NON_EXPORTABLE_POLICY, kemKeys, checkKEMKeysMatching); +} + +RUNNER_TEST(TUA_0021_update_update_KEM_key) +{ + updateUpdateAsymmetricKeyHelper(KEM_PRIVATE_KEY_ALIAS, KEM_PUBLIC_KEY_ALIAS, + NON_EXPORTABLE_POLICY, kemKeys, checkKEMKeysMatching); +} + +RUNNER_TEST(TUA_0022_save_update_KEM_key_with_another_exportability) +{ + saveUpdateAsymmetricKeyWithAnotherExportabilityHelper(KEM_PRIVATE_KEY_ALIAS, + KEM_PUBLIC_KEY_ALIAS, kemKeys, + checkKEMKeysMatching); +} + +RUNNER_TEST(TUA_0023_save_update_KEM_key_with_another_password) +{ + saveUpdateAsymmetricKeyWithAnotherPasswordHelper(KEM_PRIVATE_KEY_ALIAS, KEM_PUBLIC_KEY_ALIAS, + kemKeys, checkKEMKeysMatching); +} + +RUNNER_TEST(TUA_0024_save_update_KEM_key_with_another_backend) +{ + saveUpdateAsymmetricKeyWithAnotherBackendHelper(KEM_PRIVATE_KEY_ALIAS, KEM_PUBLIC_KEY_ALIAS, + kemKeys, checkKEMKeysMatching); +} + +RUNNER_TEST(TUA_0025_save_update_KEM_key_with_invalid_parameters) +{ + saveUpdateAsymmetricKeyWithInvalidParametersHelper(KEM_PRIVATE_KEY_ALIAS, + NON_EXPORTABLE_POLICY, kemKeys); +} + +RUNNER_TEST(TUA_0026_save_update_KEM_key_with_locked_db) +{ + saveUpdateAsymmetricKeyWithLockedDBHelper(KEM_PRIVATE_KEY_ALIAS, kemKeys); +} + +RUNNER_TEST(TUA_0027_save_update_wrong_KEM_key) +{ + saveUpdateAsymmetricKeyWithWrongKeyHelper(KEM_PRIVATE_KEY_ALIAS, kemKeys, + CKMC_KEY_KEM_PRIVATE); +} + +namespace { + +std::array dsaKeys = { { + { + KeyCtx{ "DSA_PRIVATE_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "DSA_PUBLIC_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "DSA_PRIVATE_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "DSA_PUBLIC_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "DSA_PRIVATE_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "DSA_PUBLIC_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY } + } +} }; + +const char* DSA_PRIVATE_KEY_ALIAS = "DSA_PRIVATE_KEY"; +const char* DSA_PUBLIC_KEY_ALIAS = "DSA_PUBLIC_KEY"; + +void checkSignatureVerification(const char* privateAlias, const char* privatePassword, + const char* publicAlias, const char* publicPassword) +{ + ckmc_raw_buffer_s message = prepare_message_buffer("message"); + ckmc_hash_algo_e hashAlgo = CKMC_HASH_SHA1; + ckmc_rsa_padding_algo_e padAlgo = CKMC_PKCS1_PADDING; + ckmc_raw_buffer_s *signature = nullptr; + + assert_positive(ckmc_create_signature, + privateAlias, + privatePassword, + message, + hashAlgo, + padAlgo, + &signature); + + auto signaturePtr = create_raw_buffer(signature); + + assert_positive(ckmc_verify_signature, + publicAlias, + publicPassword, + message, + *signature, + hashAlgo, + padAlgo); +} + +class DSAKeys +{ +public: + void Init() + { + for (auto& keyPair : dsaKeys) + { + error_msg_positive(ckmc_create_key_pair_dsa, m_dsaKeySize, keyPair.privateKey.alias, + keyPair.publicKey.alias, keyPair.privateKey.policy, + keyPair.privateKey.policy); + + ckmc_key_s *key = nullptr; + error_msg_positive(ckmc_get_key, keyPair.privateKey.alias, + keyPair.privateKey.policy.password, &key); + keyPair.privateKey.key = createKeyPtr(key); + + key = nullptr; + error_msg_positive(ckmc_get_key, keyPair.publicKey.alias, + keyPair.publicKey.policy.password, &key); + keyPair.publicKey.key = createKeyPtr(key); + } + } + + void Finish() + { + for (const auto& key : dsaKeys) + { + error_msg_positive(ckmc_remove_alias, key.privateKey.alias); + error_msg_positive(ckmc_remove_alias, key.publicKey.alias); + } + } + +private: + const size_t m_dsaKeySize = 1024; +}; + +class DSAKeysTestGroup : public DSAKeys, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + DSAKeys::Init(); + } + + void Finish() override + { + DSAKeys::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_DSA_KEYS, DSAKeysTestGroup); + +RUNNER_TEST(TUA_0030_save_update_DSA_key) +{ + saveUpdateAsymmetricKeyHelper(DSA_PRIVATE_KEY_ALIAS, DSA_PUBLIC_KEY_ALIAS, + EXPORTABLE_POLICY, dsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0031_update_update_DSA_key) +{ + updateUpdateAsymmetricKeyHelper(DSA_PRIVATE_KEY_ALIAS, DSA_PUBLIC_KEY_ALIAS, + EXPORTABLE_POLICY, dsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0033_save_update_DSA_key_with_another_password) +{ + saveUpdateAsymmetricKeyWithAnotherPasswordHelper(DSA_PRIVATE_KEY_ALIAS, DSA_PUBLIC_KEY_ALIAS, + dsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0035_save_update_DSA_key_with_invalid_parameters) +{ + saveUpdateAsymmetricKeyWithInvalidParametersHelper(DSA_PRIVATE_KEY_ALIAS, + EXPORTABLE_POLICY, dsaKeys); +} + +RUNNER_TEST(TUA_0036_save_update_DSA_key_with_locked_db) +{ + saveUpdateAsymmetricKeyWithLockedDBHelper(DSA_PRIVATE_KEY_ALIAS, dsaKeys); +} + +RUNNER_TEST(TUA_0037_save_update_wrong_DSA_key) +{ + saveUpdateAsymmetricKeyWithWrongKeyHelper(DSA_PRIVATE_KEY_ALIAS, dsaKeys, CKMC_KEY_DSA_PRIVATE); +} + +namespace { + +std::array ecdsaKeys = { { + { + KeyCtx{ "ECDSA_PRIVATE_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "ECDSA_PUBLIC_KEY_0", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "ECDSA_PRIVATE_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "ECDSA_PUBLIC_KEY_1", createKeyPtr(nullptr), EXPORTABLE_POLICY } + }, + { + KeyCtx{ "ECDSA_PRIVATE_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY }, + KeyCtx{ "ECDSA_PUBLIC_KEY_2", createKeyPtr(nullptr), EXPORTABLE_POLICY } + } +} }; + +const char* ECDSA_PRIVATE_KEY_ALIAS = "ECDSA_PRIVATE_KEY_ALIAS"; +const char* ECDSA_PUBLIC_KEY_ALIAS = "ECDSA_PUBLIC_KEY_ALIAS"; + +class ECDSAKeys +{ +public: + void Init() + { + for (auto& keyPair : ecdsaKeys) + { + error_msg_positive(ckmc_create_key_pair_ecdsa, m_ecType, keyPair.privateKey.alias, + keyPair.publicKey.alias, keyPair.privateKey.policy, + keyPair.privateKey.policy); + + ckmc_key_s *key = nullptr; + error_msg_positive(ckmc_get_key, keyPair.privateKey.alias, + keyPair.privateKey.policy.password, &key); + keyPair.privateKey.key = createKeyPtr(key); + + key = nullptr; + error_msg_positive(ckmc_get_key, keyPair.publicKey.alias, + keyPair.publicKey.policy.password, &key); + keyPair.publicKey.key = createKeyPtr(key); + } + } + + void Finish() + { + for (const auto& key : ecdsaKeys) + { + error_msg_positive(ckmc_remove_alias, key.privateKey.alias); + error_msg_positive(ckmc_remove_alias, key.publicKey.alias); + } + } + +private: + const ckmc_ec_type_e m_ecType = CKMC_EC_PRIME192V1; +}; + +class ECDSAKeysTestGroup : public ECDSAKeys, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + ECDSAKeys::Init(); + } + + void Finish() override + { + ECDSAKeys::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_ECDSA_KEYS, ECDSAKeysTestGroup); + +RUNNER_TEST(TUA_0040_save_update_ECDSA_key) +{ + saveUpdateAsymmetricKeyHelper(ECDSA_PRIVATE_KEY_ALIAS, ECDSA_PUBLIC_KEY_ALIAS, + NON_EXPORTABLE_POLICY, ecdsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0041_update_update_ECDSA_key) +{ + updateUpdateAsymmetricKeyHelper(ECDSA_PRIVATE_KEY_ALIAS, ECDSA_PUBLIC_KEY_ALIAS, + NON_EXPORTABLE_POLICY, ecdsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0042_save_update_ECDSA_key_with_another_exportability) +{ + saveUpdateAsymmetricKeyWithAnotherExportabilityHelper( + ECDSA_PRIVATE_KEY_ALIAS, ECDSA_PUBLIC_KEY_ALIAS, ecdsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0043_save_update_ECDSA_key_with_another_password) +{ + saveUpdateAsymmetricKeyWithAnotherPasswordHelper( + ECDSA_PRIVATE_KEY_ALIAS, ECDSA_PUBLIC_KEY_ALIAS, ecdsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0044_save_update_ECDSA_key_with_another_backend) +{ + saveUpdateAsymmetricKeyWithAnotherBackendHelper( + ECDSA_PRIVATE_KEY_ALIAS, ECDSA_PUBLIC_KEY_ALIAS, ecdsaKeys, checkSignatureVerification); +} + +RUNNER_TEST(TUA_0045_save_update_ECDSA_key_with_invalid_parameters) +{ + saveUpdateAsymmetricKeyWithInvalidParametersHelper(ECDSA_PRIVATE_KEY_ALIAS, + NON_EXPORTABLE_POLICY, ecdsaKeys); +} + +RUNNER_TEST(TUA_0046_save_update_ECDSA_key_with_locked_db) +{ + saveUpdateAsymmetricKeyWithLockedDBHelper(ECDSA_PRIVATE_KEY_ALIAS, ecdsaKeys); +} + +RUNNER_TEST(TUA_0047_save_update_wrong_ECDSA_key) +{ + saveUpdateAsymmetricKeyWithWrongKeyHelper(ECDSA_PRIVATE_KEY_ALIAS, ecdsaKeys, + CKMC_KEY_ECDSA_PRIVATE); +} + +namespace { + +std::array aesKeys = { { + { "AES_KEY_0", createKeyPtr(nullptr), NON_EXPORTABLE_POLICY }, + { "AES_KEY_1", createKeyPtr(nullptr), NON_EXPORTABLE_POLICY }, + { "AES_KEY_2", createKeyPtr(nullptr), NON_EXPORTABLE_PASSWORD_POLICY_0 }, + { "AES_KEY_3", createKeyPtr(nullptr), NON_EXPORTABLE_PASSWORD_POLICY_1 } +} }; + +const char* AES_KEY_ALIAS = "AES_KEY"; + +void checkAESKeysMatching(const char* aesKeyAlias1, const char* password1, + const char* aesKeyAlias2, const char* password2) +{ + auto plain = create_raw_buffer(createRandomBufferCAPI(512)); + auto iv = create_raw_buffer(createRandomBufferCAPI(16)); + + auto params = createParamListPtr(); + setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR); + setParam(params, CKMC_PARAM_ED_IV, iv.get()); + + ckmc_raw_buffer_s* encrypted = nullptr; + assert_positive(ckmc_encrypt_data, params.get(), aesKeyAlias1, + password1, *plain.get(), &encrypted); + auto encryptedPtr = create_raw_buffer(encrypted); + + ckmc_raw_buffer_s* decrypted = nullptr; + assert_positive(ckmc_decrypt_data, params.get(), aesKeyAlias2, + password2, *encrypted, &decrypted); + auto decryptedPtr = create_raw_buffer(decrypted); + + assert_buffers_equal(plain.get(), decrypted); +} + +class AESKeys +{ +public: + void Init() + { + for (auto& key : aesKeys) + { + key.key = createKeyPtr(generate_AES_key(m_aesKeyLength, nullptr)); + error_msg_positive(ckmc_save_key, key.alias, *key.key, key.policy); + } + } + + void Finish() + { + for (const auto& key : aesKeys) + { + error_msg_positive(ckmc_remove_alias, key.alias); + } + } + +private: + const size_t m_aesKeyLength = 192; +}; + +class AESKeysTestGroup : public AESKeys, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + AESKeys::Init(); + } + + void Finish() override + { + AESKeys::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_AES_KEYS, AESKeysTestGroup); + +RUNNER_TEST(TUA_0050_save_update_AES_key) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_save_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, AES_KEY_ALIAS, *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + AES_KEY_ALIAS, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0051_update_update_AES_key) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_update_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[0].alias, aesKeys[0].policy.password, + AES_KEY_ALIAS, NON_EXPORTABLE_POLICY.password); + + assert_positive(ckmc_update_key, AES_KEY_ALIAS, *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + AES_KEY_ALIAS, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0052_save_update_AES_key_with_another_exportability) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_save_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + check_self_key_alias_info_list(false, Info(AES_KEY_ALIAS, NON_EXPORTABLE_POLICY, backend())); + + assert_positive(ckmc_update_key, AES_KEY_ALIAS, *aesKeys[1].key, EXPORTABLE_POLICY); + check_self_key_alias_info_list(false, Info(AES_KEY_ALIAS, EXPORTABLE_POLICY, + CKM::BackendId::SW)); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + AES_KEY_ALIAS, EXPORTABLE_POLICY.password); + + ckmc_key_s *key = nullptr; + assert_positive(ckmc_get_key, AES_KEY_ALIAS, EXPORTABLE_POLICY.password, &key); + auto keyPtr = createKeyPtr(key); + assert_keys_equal(key, aesKeys[1].key.get()); +} + +RUNNER_TEST(TUA_0053_save_update_AES_key_with_another_password) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_save_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, AES_KEY_ALIAS, + *aesKeys[2].key, NON_EXPORTABLE_PASSWORD_POLICY_0); + + checkAESKeysMatching(aesKeys[2].alias, aesKeys[2].policy.password, + AES_KEY_ALIAS, NON_EXPORTABLE_PASSWORD_POLICY_0.password); + + assert_positive(ckmc_update_key, AES_KEY_ALIAS, + *aesKeys[3].key, NON_EXPORTABLE_PASSWORD_POLICY_1); + + checkAESKeysMatching(aesKeys[3].alias, aesKeys[3].policy.password, + AES_KEY_ALIAS, NON_EXPORTABLE_PASSWORD_POLICY_1.password); +} + +RUNNER_TEST(TUA_0054_save_update_AES_key_with_another_backend) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + ckmSaveKey(*aesKeys[0].key, AES_KEY_ALIAS, TZ_POLICY); + check_self_key_alias_info_list(false, Info(AES_KEY_ALIAS, TZ_POLICY, backend())); + + ckmUpdateKey(*aesKeys[1].key, AES_KEY_ALIAS, SW_POLICY); + check_self_key_alias_info_list(false, Info(AES_KEY_ALIAS, SW_POLICY, CKM::BackendId::SW)); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + AES_KEY_ALIAS, SW_POLICY.password.c_str()); + + ckmUpdateKey(*aesKeys[2].key, AES_KEY_ALIAS, TZ_POLICY); + check_self_key_alias_info_list(false, Info(AES_KEY_ALIAS, TZ_POLICY, backend())); + + checkAESKeysMatching(aesKeys[2].alias, aesKeys[2].policy.password, + AES_KEY_ALIAS, TZ_POLICY.password.c_str()); +} + +RUNNER_TEST(TUA_0055_save_update_AES_key_with_invalid_parameters) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_save_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, nullptr, + *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + auto wrongAesKey = *aesKeys[0].key; + + wrongAesKey.password = const_cast(USER_PASSWORD); + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, AES_KEY_ALIAS, + wrongAesKey, NON_EXPORTABLE_POLICY); + + wrongAesKey.password = aesKeys[0].key->password; + wrongAesKey.key_size = 0; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, AES_KEY_ALIAS, + wrongAesKey, NON_EXPORTABLE_POLICY); + + wrongAesKey.key_size = aesKeys[0].key->key_size; + wrongAesKey.raw_key = nullptr; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_key, AES_KEY_ALIAS, + wrongAesKey, NON_EXPORTABLE_POLICY); +} + +RUNNER_TEST(TUA_0056_save_update_AES_key_with_locked_db) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_save_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + + assert_positive(ckmc_lock_user_key, OWNER_USER_ID); + assert_result(CKMC_ERROR_DB_LOCKED, ckmc_update_key, AES_KEY_ALIAS, + *aesKeys[1].key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASSWORD); +} + +RUNNER_TEST(TUA_0057_save_update_wrong_AES_key) +{ + AliasRemover aliasRemover(AES_KEY_ALIAS); + + assert_positive(ckmc_save_key, AES_KEY_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + + ckmc_key_s wrongAesKey = { + WRONG_RAW_DATA, std::size(WRONG_RAW_DATA), CKMC_KEY_AES, nullptr + }; + assert_result(CKMC_ERROR_INVALID_FORMAT, ckmc_update_key, AES_KEY_ALIAS, + wrongAesKey, NON_EXPORTABLE_POLICY); +} + +namespace { + +using DataCtx = RawBufferPtr; + +std::array data = { { + create_raw_buffer(createRandomBufferCAPI(32)), + create_raw_buffer(createRandomBufferCAPI(32)) +} }; + +const char* DATA_ALIASES_UPDATED = "secret1"; +const char* DATA_ALIASES_STORED = "secret2"; + +ParamListPtr generateDerivationParams() +{ + const uint64_t U32 = 32; + const ckmc_kdf_prf_e HMAC256 = CKMC_KDF_PRF_HMAC_SHA256; + const ckmc_kbkdf_mode_e COUNTER = CKMC_KBKDF_MODE_COUNTER; + const ckmc_kbkdf_counter_location_e BEFORE = CKMC_KBKDF_COUNTER_BEFORE_FIXED; + const RawBufferPtr CTX = create_raw_buffer(createRandomBufferCAPI(12)); + const RawBufferPtr LAB = create_raw_buffer(createRandomBufferCAPI(16)); + + auto derivationParams = createParamListPtr(); + setParam(derivationParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF); + setParam(derivationParams, CKMC_PARAM_KDF_LEN, U32); + setParam(derivationParams, CKMC_PARAM_KDF_PRF, HMAC256); + setParam(derivationParams, CKMC_PARAM_KBKDF_MODE, COUNTER); + setParam(derivationParams, CKMC_PARAM_KBKDF_COUNTER_LOCATION, BEFORE); + setParam(derivationParams, CKMC_PARAM_KBKDF_CONTEXT, CTX.get()); + setParam(derivationParams, CKMC_PARAM_KBKDF_LABEL, LAB.get()); + + return derivationParams; +} + +ParamListPtr generateEncryptionParams() +{ + ckmc_param_list_h handle = nullptr; + assert_positive(ckmc_generate_new_params, CKMC_ALGO_AES_CBC, &handle); + auto encryptionParams = ParamListPtr(handle, ckmc_param_list_free); + ckmc_raw_buffer_s* DEFAULT_IV = createRandomBufferCAPI(16); + setParam(encryptionParams, CKMC_PARAM_ED_IV, DEFAULT_IV); + return encryptionParams; +} + +void checkDataMatching(const char* dataAlias1, const char* password1, + const char* dataAlias2, const char* password2) +{ + const char* DERIVED_ALIAS1 = "derived1"; + const char* DERIVED_ALIAS2 = "derived2"; + + AliasRemover aliasRemovers[] = { DERIVED_ALIAS1, DERIVED_ALIAS2 }; + + auto derivationParams = generateDerivationParams(); + + assert_positive(ckmc_key_derive, + derivationParams.get(), + dataAlias1, + password1, + DERIVED_ALIAS1, + NON_EXPORTABLE_POLICY); + + assert_positive(ckmc_key_derive, + derivationParams.get(), + dataAlias2, + password2, + DERIVED_ALIAS2, + NON_EXPORTABLE_POLICY); + + const auto randomData = create_raw_buffer(createRandomBufferCAPI(16)); + ckmc_raw_buffer_s* encrypted = nullptr; + auto encryptedPtr = create_raw_buffer(encrypted); + ckmc_raw_buffer_s* decrypted = nullptr; + auto decryptedPtr = create_raw_buffer(decrypted); + + auto encryptionParams = generateEncryptionParams(); + + assert_positive(ckmc_encrypt_data, + encryptionParams.get(), + DERIVED_ALIAS1, + nullptr, + *randomData.get(), + &encrypted); + + assert_positive(ckmc_decrypt_data, + encryptionParams.get(), + DERIVED_ALIAS2, + nullptr, + *encrypted, + &decrypted); + + assert_buffers_equal(randomData.get(), decrypted); +} + +class Data +{ +public: + void Init() + { + error_msg_positive(ckmc_save_data, DATA_ALIASES_STORED, *data[1], NON_EXPORTABLE_POLICY); + } + + void Finish() + { + error_msg_positive(ckmc_remove_alias, DATA_ALIASES_STORED); + } +}; + +class DataTestGroup : public Data, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + Data::Init(); + } + + void Finish() override + { + Data::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_DATA, DataTestGroup); + +RUNNER_TEST(TUA_0060_save_update_data) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + assert_positive(ckmc_save_data, DATA_ALIASES_UPDATED, + *data[0], NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_data, DATA_ALIASES_UPDATED, + *data[1], NON_EXPORTABLE_POLICY); + + checkDataMatching(DATA_ALIASES_UPDATED, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0061_update_update_data) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + assert_positive(ckmc_update_data, DATA_ALIASES_UPDATED, + *data[0], NON_EXPORTABLE_POLICY); + + checkDataMatching(DATA_ALIASES_UPDATED, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_UPDATED, NON_EXPORTABLE_POLICY.password); + + assert_positive(ckmc_update_data, DATA_ALIASES_UPDATED, *data[1], + NON_EXPORTABLE_POLICY); + + checkDataMatching(DATA_ALIASES_UPDATED, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0062_save_update_data_with_another_exportability) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + assert_positive(ckmc_save_data, DATA_ALIASES_UPDATED, *data[0], NON_EXPORTABLE_POLICY); + check_self_data_alias_info_list(false, Info(DATA_ALIASES_UPDATED, NON_EXPORTABLE_POLICY, + backend())); + + assert_positive(ckmc_update_data, DATA_ALIASES_UPDATED, *data[1], EXPORTABLE_POLICY); + check_self_data_alias_info_list(false, Info(DATA_ALIASES_UPDATED, EXPORTABLE_POLICY, + backend())); + + checkDataMatching(DATA_ALIASES_UPDATED, EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + + ckmc_raw_buffer_s *buffer = nullptr; + assert_positive(ckmc_get_data, DATA_ALIASES_UPDATED, EXPORTABLE_POLICY.password, &buffer); + auto bufferPtr = create_raw_buffer(buffer); + assert_buffers_equal(buffer, data[1].get()); +} + +RUNNER_TEST(TUA_0063_save_update_data_with_another_password) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + assert_positive(ckmc_save_data, DATA_ALIASES_UPDATED, + *data[0], NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_data, DATA_ALIASES_UPDATED, + *data[1], NON_EXPORTABLE_PASSWORD_POLICY_0); + + checkDataMatching(DATA_ALIASES_UPDATED, NON_EXPORTABLE_PASSWORD_POLICY_0.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + + assert_positive(ckmc_update_data, DATA_ALIASES_UPDATED, + *data[1], NON_EXPORTABLE_PASSWORD_POLICY_1); + + checkDataMatching(DATA_ALIASES_UPDATED, NON_EXPORTABLE_PASSWORD_POLICY_1.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0064_save_update_data_with_another_backend) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + ckmSaveData(*data[0], DATA_ALIASES_UPDATED, TZ_POLICY); + check_self_data_alias_info_list(false, Info(DATA_ALIASES_UPDATED, TZ_POLICY, backend())); + + ckmUpdateData(*data[1], DATA_ALIASES_UPDATED, SW_POLICY); + check_self_data_alias_info_list(false, Info(DATA_ALIASES_UPDATED, SW_POLICY, + CKM::BackendId::SW)); + + checkDataMatching(DATA_ALIASES_UPDATED, SW_POLICY.password.c_str(), + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + + ckmUpdateData(*data[1], DATA_ALIASES_UPDATED, TZ_POLICY); + check_self_data_alias_info_list(false, Info(DATA_ALIASES_UPDATED, TZ_POLICY, backend())); + + checkDataMatching(DATA_ALIASES_UPDATED, TZ_POLICY.password.c_str(), + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0065_save_update_data_with_invalid_parameters) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + assert_positive(ckmc_save_data, DATA_ALIASES_UPDATED, *data[0], NON_EXPORTABLE_POLICY); + + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_data, + nullptr, *data[1], NON_EXPORTABLE_POLICY); + + auto wrongData = *data[0]; + wrongData.size = 0; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_data, + DATA_ALIASES_UPDATED, wrongData, NON_EXPORTABLE_POLICY); + + wrongData.size = data[0]->size; + wrongData.data = nullptr; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_data, + DATA_ALIASES_UPDATED, wrongData, NON_EXPORTABLE_POLICY); +} + +RUNNER_TEST(TUA_0066_save_update_data_with_locked_db) +{ + AliasRemover aliasRemovers(DATA_ALIASES_UPDATED); + + assert_positive(ckmc_save_data, DATA_ALIASES_UPDATED, *data[0], NON_EXPORTABLE_POLICY); + + assert_positive(ckmc_lock_user_key, OWNER_USER_ID); + assert_result(CKMC_ERROR_DB_LOCKED, ckmc_update_data, DATA_ALIASES_UPDATED, + *data[1], NON_EXPORTABLE_POLICY); + assert_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASSWORD); +} + +namespace { + +struct CertificateAndKeyContext +{ + std::string certRawData; + CertPtr cert; + std::string keyRawData; + KeyPtr key; + const char* keyAlias; + const ckmc_policy_s keyPolicy; +}; + +std::array certificateAndKeyContexts = { { + { + "-----BEGIN CERTIFICATE-----\n" + "MIIDUzCCAxECCQCer/fKcXtJgTALBglghkgBZQMEAwIwgYsxCzAJBgNVBAYTAlBM\n" + "MQ8wDQYDVQQIDAZQb2xhbmQxDzANBgNVBAcMBldhcnNhdzEQMA4GA1UECgwHU2Ft\n" + "c3VuZzEMMAoGA1UECwwDS1NGMRMwEQYDVQQDDAptLmthcnBpdWsyMSUwIwYJKoZI\n" + "hvcNAQkBFhZtLmthcnBpdWsyQHNhbXN1bmcuY29tMCAXDTE0MDkyNjEzNTQwN1oY\n" + "DzIxNDAwOTA1MTM1NDA3WjCBizELMAkGA1UEBhMCUEwxDzANBgNVBAgMBlBvbGFu\n" + "ZDEPMA0GA1UEBwwGV2Fyc2F3MRAwDgYDVQQKDAdTYW1zdW5nMQwwCgYDVQQLDANL\n" + "U0YxEzARBgNVBAMMCm0ua2FycGl1azIxJTAjBgkqhkiG9w0BCQEWFm0ua2FycGl1\n" + "azJAc2Ftc3VuZy5jb20wggG3MIIBKwYHKoZIzjgEATCCAR4CgYEA9Bhh7ZA4onkY\n" + "uDNQbYR4EwkJ6RpD505hB0GF6yppUNp2LanvNcQXcyXY88MB6OdP7Rikbu1H2zP4\n" + "gONCtdxKW58Za7h9bFzYjxcObZsS52F9DP7sv3C4sX4xNWApfhUgbfzKaRCJOkOs\n" + "06tV7teu3G/v26PdI8dlykIuQXQZmH8CFQCHsIV0njb2yC3ggfKz+exH+g5jAQKB\n" + "gBVLYfVCMjUz5XJH+xYU3A8W8rpSLqZKIK2d9mbXqhpz8QK1bvNQUlSRZo+o1ZYV\n" + "mJn3Mx2YuiifHZNKdBNweCqe5a+HV2RSl1Yv/TV9famZKlogGslsmPHUOJMlSIdh\n" + "MfMwVny4/rNtjEtEFE1WnaTr1W6MKH1EBbizVo8fmWFrA4GFAAKBgQCaPjrlkAyX\n" + "kBitWo+w0xZN4OSk13SsCzZ/PG+5zOgMRaFm2XbiC04YsGCi4NFOd9kaiP7w1CsP\n" + "iqG6Vwv0T/VcoxBl/hp6jEqTDSrM6z0ungjDO9wGOdI+jZS0UjVahgC4ZLDHhrOa\n" + "CjfxcHruO3e416b/Rm2CjhOzjKdoSFUWVzALBglghkgBZQMEAwIDLwAwLAIUHa+A\n" + "5xo8O/tPuH9gXkr1mee6kRYCFGNycJ1xkc3nIJaEQOtGfDe7S71A\n" + "-----END CERTIFICATE-----\n", + createCertPtr(nullptr), + "-----BEGIN DSA PRIVATE KEY-----\n" + "MIIBuwIBAAKBgQD0GGHtkDiieRi4M1BthHgTCQnpGkPnTmEHQYXrKmlQ2nYtqe81\n" + "xBdzJdjzwwHo50/tGKRu7UfbM/iA40K13EpbnxlruH1sXNiPFw5tmxLnYX0M/uy/\n" + "cLixfjE1YCl+FSBt/MppEIk6Q6zTq1Xu167cb+/bo90jx2XKQi5BdBmYfwIVAIew\n" + "hXSeNvbILeCB8rP57Ef6DmMBAoGAFUth9UIyNTPlckf7FhTcDxbyulIupkogrZ32\n" + "ZteqGnPxArVu81BSVJFmj6jVlhWYmfczHZi6KJ8dk0p0E3B4Kp7lr4dXZFKXVi/9\n" + "NX19qZkqWiAayWyY8dQ4kyVIh2Ex8zBWfLj+s22MS0QUTVadpOvVbowofUQFuLNW\n" + "jx+ZYWsCgYEAmj465ZAMl5AYrVqPsNMWTeDkpNd0rAs2fzxvuczoDEWhZtl24gtO\n" + "GLBgouDRTnfZGoj+8NQrD4qhulcL9E/1XKMQZf4aeoxKkw0qzOs9Lp4IwzvcBjnS\n" + "Po2UtFI1WoYAuGSwx4azmgo38XB67jt3uNem/0Ztgo4Ts4ynaEhVFlcCFGMH+Z9l\n" + "vonbjii3BYe4AIdkzOvp\n" + "-----END DSA PRIVATE KEY-----\n", + createKeyPtr(nullptr), + "PRIVATE_KEY_0", + NON_EXPORTABLE_POLICY + }, + { + "-----BEGIN CERTIFICATE-----\n" + "MIICijCCAfOgAwIBAgIJAMvaNHQ1ozT8MA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNV\n" + "BAYTAlBMMQ0wCwYDVQQIDARMb2R6MQ0wCwYDVQQHDARMb2R6MRAwDgYDVQQKDAdT\n" + "YW1zdW5nMREwDwYDVQQLDAhTZWN1cml0eTEMMAoGA1UEAwwDQ0tNMB4XDTE0MDcw\n" + "MjEyNDE0N1oXDTE3MDcwMTEyNDE0N1owXjELMAkGA1UEBhMCUEwxDTALBgNVBAgM\n" + "BExvZHoxDTALBgNVBAcMBExvZHoxEDAOBgNVBAoMB1NhbXN1bmcxETAPBgNVBAsM\n" + "CFNlY3VyaXR5MQwwCgYDVQQDDANDS00wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ\n" + "AoGBAMIpv0GRN06MJNco+L8fkVIa7KuDM5EG1HecJODtJGcvjvM0YSOXbCSCxj1k\n" + "7dQkebSDLkoyNZ4K5RWRIPcbjon2huDVtgmK8JAEkrF+J4DyxY602rUzx6YcYryj\n" + "eyNpGSWueCaTbFIKzm8UlWUKW7MBhSas8ObrgLf6fjJbikEJAgMBAAGjUDBOMB0G\n" + "A1UdDgQWBBQuW9DuITahZJ6saVZZI0aBlis5vzAfBgNVHSMEGDAWgBQuW9DuITah\n" + "ZJ6saVZZI0aBlis5vzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAB2X\n" + "GNtJopBJR3dCpzDONknr/c6qcsPVa3nH4c7qzy6F+4bgqa5IObnoF8zUrvD2sMAO\n" + "km3C/N+Qzt8Rb7ORM6U4tlPp1kZ5t6PKjghhNaiYwVm9A/Zm+wyAmRIkQiYDr4MX\n" + "e+bRAkPmJeEWpaav1lvvBnFzGSGJrnSSeWUegGyn\n" + "-----END CERTIFICATE-----\n", + createCertPtr(nullptr), + "-----BEGIN RSA PRIVATE KEY-----\n" + "MIICXQIBAAKBgQDCKb9BkTdOjCTXKPi/H5FSGuyrgzORBtR3nCTg7SRnL47zNGEj\n" + "l2wkgsY9ZO3UJHm0gy5KMjWeCuUVkSD3G46J9obg1bYJivCQBJKxfieA8sWOtNq1\n" + "M8emHGK8o3sjaRklrngmk2xSCs5vFJVlCluzAYUmrPDm64C3+n4yW4pBCQIDAQAB\n" + "AoGAd1IWgiHO3kuLvFome7XXpaB8P27SutZ6rcLcewnhLDRy4g0XgTrmL43abBJh\n" + "gdSkooVXZity/dvuKpHUs2dQ8W8zYiFFsHfu9qqLmLP6SuBPyUCvlUDH5BGfjjxI\n" + "5qGWIowj/qGHKpbQ7uB+Oe2BHwbHao0zFZIkfKqY0mX9U00CQQDwF/4zQcGS1RX/\n" + "229gowTsvSGVmm8cy1jGst6xkueEuOEZ/AVPO1fjavz+nTziUk4E5lZHAj18L6Hl\n" + "iO29LRujAkEAzwbEWVhfTJewCZIFf3sY3ifXhGZhVKDHVzPBNyoft8Z+09DMHTJb\n" + "EYg85MIbR73aUyIWsEci/CPk6LPRNv47YwJAHtQF2NEFqPPhakPjzjXAaSFz0YDN\n" + "6ZWWpZTMEWL6hUkz5iE9EUpeY54WNB8+dRT6XZix1VZNTMfU8uMdG6BSHwJBAKYM\n" + "gm47AGz5eVujwD8op6CACk+KomRzdI+P1lh9s+T+E3mnDiAY5IxiXp0Ix0K6lyN4\n" + "wwPuerQLwi2XFKZsMYsCQQDOiSQFP9PfXh9kFzN6e89LxOdnqC/r9i5GDB3ea8eL\n" + "SCRprpzqOXZvOP1HBAEjsJ6k4f8Dqj1fm+y8ZcgAZUPr\n" + "-----END RSA PRIVATE KEY-----\n", + createKeyPtr(nullptr), + "PRIVATE_KEY_1", + NON_EXPORTABLE_POLICY + } +} }; + +const char* certificateAlias = "CERTIFICATE"; + +class Certificates +{ +public: + void Init() + { + for (auto& certificateAndKeyContext : certificateAndKeyContexts) + { + ckmc_cert_s* cert = nullptr; + error_msg_positive(ckmc_cert_new, + reinterpret_cast(const_cast( + certificateAndKeyContext.certRawData.data())), + certificateAndKeyContext.certRawData.size(), CKMC_FORM_PEM, &cert); + certificateAndKeyContext.cert = createCertPtr(cert); + + ckmc_key_s* key = nullptr; + error_msg_positive(ckmc_key_new, + reinterpret_cast(const_cast( + certificateAndKeyContext.keyRawData.data())), + certificateAndKeyContext.keyRawData.size(), CKMC_KEY_NONE, nullptr, &key); + certificateAndKeyContext.key = createKeyPtr(key); + + error_msg_positive(ckmc_save_key, certificateAndKeyContext.keyAlias, + *certificateAndKeyContext.key, certificateAndKeyContext.keyPolicy); + } + } + + void Finish() + { + for (const auto& certificate : certificateAndKeyContexts) + { + error_msg_positive(ckmc_remove_alias, certificate.keyAlias); + } + } +}; + +class CertificatesTestGroup : public Certificates, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + Certificates::Init(); + } + + void Finish() override + { + Certificates::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_CERT, CertificatesTestGroup); + +RUNNER_TEST(TUA_0070_save_update_cert) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_save_cert, certificateAlias, *certificateAndKeyContexts[0].cert, + NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_cert, certificateAlias, *certificateAndKeyContexts[1].cert, + NON_EXPORTABLE_POLICY); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + certificateAndKeyContexts[1].keyPolicy.password, + certificateAlias, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0071_update_update_cert) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_update_cert, certificateAlias, + *certificateAndKeyContexts[0].cert, NON_EXPORTABLE_POLICY); + + checkSignatureVerification(certificateAndKeyContexts[0].keyAlias, + certificateAndKeyContexts[0].keyPolicy.password, + certificateAlias, NON_EXPORTABLE_POLICY.password); + + assert_positive(ckmc_update_cert, certificateAlias, + *certificateAndKeyContexts[1].cert, NON_EXPORTABLE_POLICY); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + certificateAndKeyContexts[1].keyPolicy.password, + certificateAlias, NON_EXPORTABLE_POLICY.password); +} + +RUNNER_TEST(TUA_0072_save_update_cert_with_another_exportability) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_save_cert, certificateAlias, + *certificateAndKeyContexts[0].cert, NON_EXPORTABLE_POLICY); + check_self_certificate_alias_info_list(false, Info(certificateAlias, + NON_EXPORTABLE_POLICY, + CKM::BackendId::SW)); + + assert_positive(ckmc_update_cert, certificateAlias, + *certificateAndKeyContexts[1].cert, EXPORTABLE_POLICY); + check_self_certificate_alias_info_list(false, Info(certificateAlias, + EXPORTABLE_POLICY, + CKM::BackendId::SW)); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + certificateAndKeyContexts[1].keyPolicy.password, + certificateAlias, EXPORTABLE_POLICY.password); + + ckmc_cert_s *cert = nullptr; + assert_positive(ckmc_get_cert, certificateAlias, EXPORTABLE_POLICY.password, &cert); + auto certPtr = createCertPtr(cert); +} + +RUNNER_TEST(TUA_0073_save_update_cert_with_another_password) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_save_cert, certificateAlias, + *certificateAndKeyContexts[0].cert, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_cert, certificateAlias, *certificateAndKeyContexts[1].cert, + NON_EXPORTABLE_PASSWORD_POLICY_0); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + certificateAndKeyContexts[1].keyPolicy.password, + certificateAlias, NON_EXPORTABLE_PASSWORD_POLICY_0.password); + + assert_positive(ckmc_update_cert, certificateAlias, + *certificateAndKeyContexts[1].cert, NON_EXPORTABLE_PASSWORD_POLICY_1); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + certificateAndKeyContexts[1].keyPolicy.password, + certificateAlias, NON_EXPORTABLE_PASSWORD_POLICY_1.password); +} + +RUNNER_TEST(TUA_0075_save_update_cert_with_invalid_parameters) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_save_cert, certificateAlias, + *certificateAndKeyContexts[0].cert, NON_EXPORTABLE_POLICY); + + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_cert, nullptr, + *certificateAndKeyContexts[1].cert, NON_EXPORTABLE_POLICY); + + auto wrongCert = *certificateAndKeyContexts[1].cert; + wrongCert.cert_size = 0; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_cert, + certificateAlias, wrongCert, NON_EXPORTABLE_POLICY); + + wrongCert.cert_size = certificateAndKeyContexts[1].cert->cert_size; + wrongCert.raw_cert = nullptr; + assert_result(CKMC_ERROR_INVALID_PARAMETER, ckmc_update_cert, + certificateAlias, wrongCert, NON_EXPORTABLE_POLICY); +} + +RUNNER_TEST(TUA_0076_save_update_cert_with_locked_db) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_save_cert, certificateAlias, + *certificateAndKeyContexts[0].cert, NON_EXPORTABLE_POLICY); + + assert_positive(ckmc_lock_user_key, OWNER_USER_ID); + assert_result(CKMC_ERROR_DB_LOCKED, ckmc_update_cert, certificateAlias, + *certificateAndKeyContexts[1].cert, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASSWORD); +} + +RUNNER_TEST(TUA_0077_save_update_wrong_cert) +{ + AliasRemover aliasRemover(certificateAlias); + + assert_positive(ckmc_save_cert, certificateAlias, + *certificateAndKeyContexts[0].cert, NON_EXPORTABLE_POLICY); + + ckmc_cert_s wrongCertificate = { + WRONG_RAW_DATA, std::size(WRONG_RAW_DATA), CKMC_FORM_PEM + }; + assert_result(CKMC_ERROR_INVALID_FORMAT, ckmc_update_cert, certificateAlias, + wrongCertificate, NON_EXPORTABLE_POLICY); +} + +namespace { + +const char* PKCS12_ALIAS = "PKCS12_ALIAS"; +ckmc_pkcs12_s* pkcs12 = nullptr; + +KeyPtr rsaPrivateKey = createKeyPtr(nullptr); + +class PKCS12Archive : public Certificates +{ +public: + void Init() + { + Certificates::Init(); + error_msg_positive(ckmc_create_key_pair_rsa, RSA_KEY_SIZE, + RSA_PRIVATE_KEY_ALIAS, RSA_PUBLIC_KEY_ALIAS, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + + ckmc_key_s *key = nullptr; + error_msg_positive(ckmc_get_key, RSA_PRIVATE_KEY_ALIAS, + EXPORTABLE_POLICY.password, &key); + rsaPrivateKey = createKeyPtr(key); + + error_msg_positive(ckmc_pkcs12_load, CKM_TEST_DIR "/pkcs.p12", nullptr, &pkcs12); + m_pkcs12 = createPKCS12Ptr(pkcs12); + } + + void Finish() + { + Certificates::Finish(); + error_msg_positive(ckmc_remove_alias, RSA_PRIVATE_KEY_ALIAS); + error_msg_positive(ckmc_remove_alias, RSA_PUBLIC_KEY_ALIAS); + } + +private: + PKSC12Ptr m_pkcs12 = createPKCS12Ptr(nullptr); +}; + +class PKCS12TestGroup : public PKCS12Archive, + public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + PKCS12Archive::Init(); + } + + void Finish() override + { + PKCS12Archive::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_PKCS12, PKCS12TestGroup); + +RUNNER_TEST(TUA_0080_save_update_PKCS12_key) +{ + AliasRemover aliasRemover(PKCS12_ALIAS); + + assert_positive(ckmc_save_pkcs12, PKCS12_ALIAS, pkcs12, + NON_EXPORTABLE_POLICY, NON_EXPORTABLE_POLICY); + + auto keyBackup = pkcs12->priv_key; + + pkcs12->priv_key = rsaPrivateKey.get(); + assert_positive(ckmc_update_pkcs12, PKCS12_ALIAS, pkcs12, + NON_EXPORTABLE_POLICY, NON_EXPORTABLE_POLICY); + checkRSAKeysMatching(PKCS12_ALIAS, NON_EXPORTABLE_POLICY.password, + RSA_PUBLIC_KEY_ALIAS, EXPORTABLE_POLICY.password); + + pkcs12->priv_key = keyBackup; +} + +RUNNER_TEST(TUA_0081_save_update_PKCS12_cert) +{ + AliasRemover aliasRemover(PKCS12_ALIAS); + + assert_positive(ckmc_save_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + + auto certBackup = pkcs12->cert; + + pkcs12->cert = certificateAndKeyContexts[0].cert.get(); + assert_positive(ckmc_update_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + checkSignatureVerification(certificateAndKeyContexts[0].keyAlias, EXPORTABLE_POLICY.password, + PKCS12_ALIAS, EXPORTABLE_POLICY.password); + + pkcs12->cert = certBackup; +} + +RUNNER_TEST(TUA_0082_save_update_PKCS12_ca) +{ + AliasRemover aliasRemover = PKCS12_ALIAS; + const char* pkcs12TempAlias = "PKCS12_TEMP"; + + assert_positive(ckmc_save_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + + auto caChainBackup = pkcs12->ca_chain; + + ckmc_pkcs12_s* pkcs12Updated = nullptr; + pkcs12->ca_chain = nullptr; + assert_positive(ckmc_update_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + assert_positive(ckmc_get_pkcs12, PKCS12_ALIAS, nullptr, nullptr, &pkcs12Updated); + auto pkcs12UpdatedPtr = createPKCS12Ptr(pkcs12Updated); + auto length = getListLength(pkcs12Updated->ca_chain); + RUNNER_ASSERT_MSG(length == 0, "ca chain should have zero length, but got length = " + << length); + assert_pkcs12_equal(pkcs12, pkcs12Updated); + + ckmc_cert_list_s** curr = &pkcs12->ca_chain; + const size_t caChainLength = 16; + for (size_t i = 1; i <= caChainLength; ++i) + { + ckmc_cert_list_s* node = new ckmc_cert_list_s(); + node->cert = certificateAndKeyContexts[i % 2].cert.get(); + node->next = nullptr; + *curr = node; + curr = &node->next; + + assert_positive(ckmc_update_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + assert_positive(ckmc_get_pkcs12, PKCS12_ALIAS, nullptr, nullptr, &pkcs12Updated); + pkcs12UpdatedPtr = createPKCS12Ptr(pkcs12Updated); + length = getListLength(pkcs12Updated->ca_chain); + RUNNER_ASSERT_MSG(length == i, "ca chain should have length = " << i + << ", but got length = " << length); + + AliasRemover aliasRemover = pkcs12TempAlias; + + assert_positive(ckmc_save_pkcs12, pkcs12TempAlias, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + ckmc_pkcs12_s* pkcs12Temp = nullptr; + assert_positive(ckmc_get_pkcs12, pkcs12TempAlias, nullptr, nullptr, &pkcs12Temp); + auto pkcs12TempPtr = createPKCS12Ptr(pkcs12Temp); + + assert_pkcs12_equal(pkcs12Temp, pkcs12Updated); + } + + curr = &pkcs12->ca_chain; + for (size_t i = caChainLength; i >= 1; --i) + { + assert_positive(ckmc_update_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + assert_positive(ckmc_get_pkcs12, PKCS12_ALIAS, nullptr, nullptr, &pkcs12Updated); + pkcs12UpdatedPtr = createPKCS12Ptr(pkcs12Updated); + length = getListLength(pkcs12Updated->ca_chain); + RUNNER_ASSERT_MSG(length == i, "ca chain should have length = " << i + << ", but got length = " << length); + + AliasRemover aliasRemover = pkcs12TempAlias; + + assert_positive(ckmc_save_pkcs12, pkcs12TempAlias, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + ckmc_pkcs12_s* pkcs12Temp = nullptr; + assert_positive(ckmc_get_pkcs12, pkcs12TempAlias, nullptr, nullptr, &pkcs12Temp); + auto pkcs12TempPtr = createPKCS12Ptr(pkcs12Temp); + + assert_pkcs12_equal(pkcs12Temp, pkcs12Updated); + + ckmc_cert_list_s* tempNext = (*curr)->next; + delete *curr; + *curr = tempNext; + } + + assert_positive(ckmc_update_pkcs12, PKCS12_ALIAS, pkcs12, + EXPORTABLE_POLICY, EXPORTABLE_POLICY); + assert_positive(ckmc_get_pkcs12, PKCS12_ALIAS, nullptr, nullptr, &pkcs12Updated); + pkcs12UpdatedPtr = createPKCS12Ptr(pkcs12Updated); + length = getListLength(pkcs12Updated->ca_chain); + RUNNER_ASSERT_MSG(length == 0, "ca chain should have zero length, but got length = " + << length); + assert_pkcs12_equal(pkcs12, pkcs12Updated); + + pkcs12->ca_chain = caChainBackup; +} + +namespace { + +const char* ANY_TYPE_ALIAS = "ANY_TYPE_ALIAS"; + +std::vector keys = { }; + +void updatePKCS12(const char* alias, ckmc_pkcs12_s* pkcs12, + const CertificateAndKeyContext& certificateAndKeyContext) +{ + auto keyBackup = pkcs12->priv_key; + auto certBackup = pkcs12->cert; + + pkcs12->priv_key = certificateAndKeyContext.key.get(); + pkcs12->cert = certificateAndKeyContext.cert.get(); + + assert_positive(ckmc_update_pkcs12, alias, pkcs12, + NON_EXPORTABLE_POLICY, NON_EXPORTABLE_POLICY); + check_self_key_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + backend())); + check_self_certificate_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + CKM::BackendId::SW)); + checkSignatureVerification(alias, NON_EXPORTABLE_POLICY.password, + alias, NON_EXPORTABLE_POLICY.password); + checkSignatureVerification(certificateAndKeyContext.keyAlias, + certificateAndKeyContext.keyPolicy.password, + alias, NON_EXPORTABLE_POLICY.password); + + pkcs12->priv_key = keyBackup; + pkcs12->cert = certBackup; +} + +class AllTypes : public AESKeys, public RSAKeys, public DSAKeys, public ECDSAKeys, public KEMKeys, + public Data, public PKCS12Archive +{ +public: + void Init() + { + AESKeys::Init(); + RSAKeys::Init(); + DSAKeys::Init(); + ECDSAKeys::Init(); + KEMKeys::Init(); + Data::Init(); + PKCS12Archive::Init(); + + keys = { + *aesKeys[0].key, + *rsaKeys[0].privateKey.key, + *rsaKeys[0].publicKey.key, + *kemKeys[0].privateKey.key, + *kemKeys[0].publicKey.key, + *dsaKeys[0].privateKey.key, + *dsaKeys[0].publicKey.key, + *ecdsaKeys[0].privateKey.key, + *ecdsaKeys[0].publicKey.key + }; + } + + void Finish() + { + AESKeys::Finish(); + RSAKeys::Finish(); + DSAKeys::Finish(); + ECDSAKeys::Finish(); + KEMKeys::Finish(); + Data::Finish(); + PKCS12Archive::Finish(); + } +}; + +class AllTypesTestGroup : public AllTypes, public DPL::Test::TestGroup, public OwnerUserEnv +{ +public: + void Init() override + { + OwnerUserEnv::Init(); + AllTypes::Init(); + } + + void Finish() override + { + AllTypes::Finish(); + OwnerUserEnv::Finish(); + } +}; + +} // namespace anonymous + +RUNNER_TEST_GROUP_INIT_ENV(CKM_UPDATE_API_DIFFERENT_TYPES, AllTypesTestGroup) + +RUNNER_TEST(TUA_0090_save_any_update_any) +{ + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + // save pkcs12 + updatePKCS12(ANY_TYPE_ALIAS, pkcs12, certificateAndKeyContexts[0]); + + // update pkcs12 with aes key + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, *aesKeys[0].key, NON_EXPORTABLE_POLICY); + check_self_key_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + backend())); + checkAESKeysMatching(aesKeys[0].alias, aesKeys[0].policy.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + ckmc_cert_s *cert = nullptr; + assert_db_alias_unknown(ckmc_get_cert, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &cert); + + // update aes key with certificate + assert_positive(ckmc_update_cert, ANY_TYPE_ALIAS, *certificateAndKeyContexts[0].cert, + NON_EXPORTABLE_POLICY); + check_self_certificate_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + CKM::BackendId::SW)); + checkSignatureVerification(certificateAndKeyContexts[0].keyAlias, + NON_EXPORTABLE_POLICY.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + ckmc_key_s *key = nullptr; + assert_db_alias_unknown(ckmc_get_key, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &key); + + // update certificate with kem key + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, + *kemKeys[0].privateKey.key, NON_EXPORTABLE_POLICY); + check_self_key_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + backend())); + checkKEMKeysMatching(ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, + kemKeys[0].publicKey.alias, kemKeys[0].publicKey.policy.password); + assert_db_alias_unknown(ckmc_get_cert, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &cert); + + // update kem key with data + assert_positive(ckmc_update_data, ANY_TYPE_ALIAS, + *data[1], NON_EXPORTABLE_POLICY); + check_self_data_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + backend())); + checkDataMatching(ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + assert_db_alias_unknown(ckmc_get_key, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &key); + + // update kem key with pkcs12 + updatePKCS12(ANY_TYPE_ALIAS, pkcs12, certificateAndKeyContexts[1]); + + // update pkcs12 with data + assert_positive(ckmc_update_data, ANY_TYPE_ALIAS, + *data[1], NON_EXPORTABLE_POLICY); + check_self_data_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + backend())); + checkDataMatching(ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + assert_db_alias_unknown(ckmc_get_key, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &key); + assert_db_alias_unknown(ckmc_get_cert, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &cert); + + // update data with cert + assert_positive(ckmc_update_cert, ANY_TYPE_ALIAS, *certificateAndKeyContexts[1].cert, + NON_EXPORTABLE_POLICY); + check_self_certificate_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + CKM::BackendId::SW)); + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + NON_EXPORTABLE_POLICY.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + ckmc_raw_buffer_s* buffer = NULL; + assert_db_alias_unknown(ckmc_get_data, ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY.password, &buffer); + + // update cert with ecdsa key + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, *ecdsaKeys[0].privateKey.key, + NON_EXPORTABLE_POLICY); + check_self_key_alias_info_list(false, Info(ANY_TYPE_ALIAS, + NON_EXPORTABLE_POLICY, + backend())); + checkSignatureVerification(ANY_TYPE_ALIAS, EXPORTABLE_POLICY.password, + ecdsaKeys[0].publicKey.alias, + ecdsaKeys[0].publicKey.policy.password); + assert_db_alias_unknown(ckmc_get_cert, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &cert); + + // update ecdsa key with pkcs12 + updatePKCS12(ANY_TYPE_ALIAS, pkcs12, certificateAndKeyContexts[0]); +} + +RUNNER_TEST(TUA_0091_save_any_update_AES_key) +{ + for (const auto& key : keys) + { + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_key, ANY_TYPE_ALIAS, key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + } + + for (const auto& rawData : data) + { + AliasRemover aliasRemovers(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_data, ANY_TYPE_ALIAS, + *rawData, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + } + + for (const auto& certificateAndKeyContext : certificateAndKeyContexts) + { + AliasRemover aliasRemovers(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_cert, ANY_TYPE_ALIAS, + *certificateAndKeyContext.cert, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + } + + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_pkcs12, ANY_TYPE_ALIAS, pkcs12, + NON_EXPORTABLE_POLICY, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_key, ANY_TYPE_ALIAS, *aesKeys[1].key, NON_EXPORTABLE_POLICY); + + checkAESKeysMatching(aesKeys[1].alias, aesKeys[1].policy.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + + ckmc_cert_s *cert = nullptr; + assert_db_alias_unknown(ckmc_get_cert, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &cert); +} + +RUNNER_TEST(TUA_0092_save_any_update_data) +{ + for (const auto& key : keys) + { + AliasRemover aliasRemovers(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_key, ANY_TYPE_ALIAS, + key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_data, ANY_TYPE_ALIAS, + *data[1], NON_EXPORTABLE_POLICY); + + checkDataMatching(ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + } + + for (const auto& certificateAndKeyContext : certificateAndKeyContexts) + { + AliasRemover aliasRemovers(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_cert, ANY_TYPE_ALIAS, + *certificateAndKeyContext.cert, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_data, ANY_TYPE_ALIAS, + *data[1], NON_EXPORTABLE_POLICY); + + checkDataMatching(ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + } + + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_pkcs12, ANY_TYPE_ALIAS, pkcs12, + NON_EXPORTABLE_POLICY, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_data, ANY_TYPE_ALIAS, + *data[1], NON_EXPORTABLE_POLICY); + + checkDataMatching(ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, + DATA_ALIASES_STORED, NON_EXPORTABLE_POLICY.password); + + ckmc_key_s *key = nullptr; + assert_db_alias_unknown(ckmc_get_key, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &key); + ckmc_cert_s *cert = nullptr; + assert_db_alias_unknown(ckmc_get_cert, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &cert); +} + +RUNNER_TEST(TUA_0093_save_any_update_cert) +{ + for (const auto& key : keys) + { + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_key, ANY_TYPE_ALIAS, + key, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_cert, ANY_TYPE_ALIAS, *certificateAndKeyContexts[1].cert, + NON_EXPORTABLE_POLICY); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + NON_EXPORTABLE_POLICY.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + } + + for (const auto& rawData : data) + { + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_data, ANY_TYPE_ALIAS, + *rawData, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_cert, ANY_TYPE_ALIAS, *certificateAndKeyContexts[1].cert, + NON_EXPORTABLE_POLICY); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + NON_EXPORTABLE_POLICY.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + } + + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_pkcs12, ANY_TYPE_ALIAS, pkcs12, + NON_EXPORTABLE_POLICY, NON_EXPORTABLE_POLICY); + assert_positive(ckmc_update_cert, ANY_TYPE_ALIAS, *certificateAndKeyContexts[1].cert, + NON_EXPORTABLE_POLICY); + + checkSignatureVerification(certificateAndKeyContexts[1].keyAlias, + NON_EXPORTABLE_POLICY.password, + ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password); + + ckmc_key_s *key = nullptr; + assert_db_alias_unknown(ckmc_get_key, ANY_TYPE_ALIAS, NON_EXPORTABLE_POLICY.password, &key); +} + +RUNNER_TEST(TUA_0094_save_any_update_PKCS12) +{ + for (const auto& key : keys) + { + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_key, ANY_TYPE_ALIAS, key, NON_EXPORTABLE_POLICY); + + updatePKCS12(ANY_TYPE_ALIAS, pkcs12, certificateAndKeyContexts[0]); + } + + for (const auto& rawData : data) + { + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_data, ANY_TYPE_ALIAS, + *rawData, NON_EXPORTABLE_POLICY); + + updatePKCS12(ANY_TYPE_ALIAS, pkcs12, certificateAndKeyContexts[0]); + } + + for (const auto& certificateAndKeyContext : certificateAndKeyContexts) + { + AliasRemover aliasRemover(ANY_TYPE_ALIAS); + + assert_positive(ckmc_save_cert, ANY_TYPE_ALIAS, + *certificateAndKeyContext.cert, NON_EXPORTABLE_POLICY); + + updatePKCS12(ANY_TYPE_ALIAS, pkcs12, certificateAndKeyContexts[0]); + } +}