--- /dev/null
+/*
+ * 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
+ */
+
+#include <dpl/test/test_runner.h>
+
+#include <ckmc/ckmc-manager.h>
+#include <ckmc/ckmc-extended.h>
+#include <ckmc/ckmc-control.h>
+#include <ckmc/ckmc-type.h>
+#include <ckmc/ckmc-error.h>
+#include <ckm-common.h>
+
+const char* PASSWORD = "test-password";
+const char* USER_PASS = "user-pass";
+
+CKM::Alias private_key_alias = "kem-priv-alias";
+CKM::Alias public_key_alias = "kem-pub-alias";
+CKM::Alias private_key_alias_second = "kem-priv-second";
+CKM::Alias public_key_alias_second = "kem-pub-second";
+CKM::Alias new_alias = "kem-test-new";
+
+ckmc_kem_type_e kem_type_768 = ckmc_kem_type_e::CKMC_ML_KEM_768;
+
+const ckmc_policy_s UNEXPORTABLE { nullptr, false };
+const ckmc_policy_s EXPORTABLE { nullptr, true };
+const ckmc_policy_s UNEXPORTABLE_PW { const_cast<char*>(PASSWORD), false };
+const ckmc_policy_s EXPORTABLE_PW { const_cast<char*>(PASSWORD), true };
+
+void remove_keys_aliases()
+{
+ ckmc_remove_alias(private_key_alias.c_str());
+ ckmc_remove_alias(public_key_alias.c_str());
+ ckmc_remove_alias(private_key_alias_second.c_str());
+ ckmc_remove_alias(public_key_alias_second.c_str());
+ ckmc_remove_alias(new_alias.c_str());
+}
+
+class KemCreateKeypairGroupFixture : public DPL::Test::TestGroup
+{
+public:
+ void Init() override
+ {
+ assert_positive(ckmc_remove_user_data, OWNER_USER_ID);
+ assert_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASS);
+ }
+
+ void Finish() override
+ {
+ assert_positive(ckmc_lock_user_key, OWNER_USER_ID);
+ assert_positive(ckmc_remove_user_data, OWNER_USER_ID);
+ }
+};
+
+class KemCreateKeypairFixture
+{
+public:
+ virtual void init(const std::string&)
+ {
+ }
+
+ virtual void finish()
+ {
+ remove_keys_aliases();
+ }
+};
+
+RUNNER_TEST_GROUP_INIT_ENV(CKMC_CREATE_KEYPAIR_KEM, KemCreateKeypairGroupFixture);
+
+RUNNER_TEST(KEM_create_key, KemCreateKeypairFixture)
+{
+ /*
+ First element in pair - private key length in bytes
+ Second element in pair - public key length in bytes
+ Source: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.ipd.pdf
+ Table 3. Sizes (in bytes) of keys and ciphertexts of ML-KEM
+ */
+ std::map<ckmc_kem_type_e, std::pair<size_t, size_t>> kem_types_sizes = {
+ {ckmc_kem_type_e::CKMC_ML_KEM_768, {2400, 1184}},
+ {ckmc_kem_type_e::CKMC_ML_KEM_1024, {3168, 1568}},
+ };
+
+ for (const auto& [kem_type, kem_key_sizes] : kem_types_sizes)
+ {
+ AliasRemover removers[] = {private_key_alias.c_str(), public_key_alias.c_str()};
+
+ size_t current_aliases_num = count_aliases(ALIAS_KEY);
+
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+#ifdef TZ_BACKEND
+ UNEXPORTABLE_PW, EXPORTABLE
+#else
+ EXPORTABLE_PW, EXPORTABLE
+#endif
+ );
+
+ size_t actual_cnt = count_aliases(ALIAS_KEY);
+ RUNNER_ASSERT_MSG(
+ (current_aliases_num + 2) == actual_cnt,
+ "Error: expecting " << (current_aliases_num + 2) << " aliases, while found " << actual_cnt);
+
+#ifndef TZ_BACKEND
+ ckmc_key_s *private_key;
+ assert_positive(ckmc_get_key,
+ private_key_alias.c_str(),
+ PASSWORD,
+ &private_key);
+
+ assert_key_type_equal(CKMC_KEY_KEM_PRIVATE, private_key->key_type);
+ assert_key_valid(private_key, kem_key_sizes.first);
+
+ ckmc_key_free(private_key);
+#endif
+
+ ckmc_key_s *public_key;
+ assert_positive(ckmc_get_key,
+ public_key_alias.c_str(),
+ nullptr,
+ &public_key);
+
+ assert_key_type_equal(CKMC_KEY_KEM_PUBLIC, public_key->key_type);
+ assert_key_valid(public_key, kem_key_sizes.second);
+
+ ckmc_key_free(public_key);
+ }
+}
+
+RUNNER_TEST(KEM_create_keypair_random_keys, KemCreateKeypairFixture)
+{
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ EXPORTABLE,
+ EXPORTABLE);
+
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias_second.c_str(),
+ public_key_alias_second.c_str(),
+ EXPORTABLE_PW,
+ EXPORTABLE_PW);
+
+ ckmc_key_s *private_key_first;
+ assert_positive(ckmc_get_key,
+ private_key_alias.c_str(),
+ nullptr,
+ &private_key_first);
+ ckmc_key_s *public_key_first;
+ assert_positive(ckmc_get_key,
+ public_key_alias.c_str(),
+ nullptr,
+ &public_key_first);
+
+ ckmc_key_s *private_key_second;
+ assert_positive(ckmc_get_key,
+ private_key_alias_second.c_str(),
+ PASSWORD,
+ &private_key_second);
+ ckmc_key_s *public_key_second;
+ assert_positive(ckmc_get_key,
+ public_key_alias_second.c_str(),
+ PASSWORD,
+ &public_key_second);
+
+ assert_keys_equal(private_key_first, private_key_second, false);
+
+ assert_keys_equal(public_key_first, public_key_second, false);
+
+ ckmc_key_free(private_key_first);
+ ckmc_key_free(private_key_second);
+ ckmc_key_free(public_key_first);
+ ckmc_key_free(public_key_second);
+}
+
+RUNNER_TEST(KEM_create_keypair_alias_exists, KemCreateKeypairFixture)
+{
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+
+ // on next attempt to generate keys with the same alias, expect fail (alias exists)
+ assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+
+ // check case when only one alias exists
+ assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmc_create_key_pair_kem,
+ kem_type_768,
+ new_alias.c_str(),
+ public_key_alias.c_str(),
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ new_alias.c_str(),
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+}
+
+RUNNER_TEST(KEM_create_keypair_invalid_parameter, KemCreateKeypairFixture)
+{
+ ckmc_kem_type_e invalid_kem_type = static_cast<ckmc_kem_type_e>(5);
+ assert_invalid_param(ckmc_create_key_pair_kem,
+ invalid_kem_type,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+ assert_invalid_param(ckmc_create_key_pair_kem,
+ kem_type_768,
+ nullptr,
+ public_key_alias.c_str(),
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+ assert_invalid_param(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ nullptr,
+ UNEXPORTABLE_PW,
+ EXPORTABLE);
+}
+
+RUNNER_TEST(KEM_create_keypair_invalid_password, KemCreateKeypairFixture)
+{
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ EXPORTABLE_PW,
+ EXPORTABLE_PW);
+
+ ckmc_key_s *private_key;
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_get_key,
+ private_key_alias.c_str(),
+ "invalidpassword",
+ &private_key);
+
+ ckmc_key_s *public_key;
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_get_key,
+ public_key_alias.c_str(),
+ "invalidpassword",
+ &public_key);
+}
+
+RUNNER_TEST(KEM_create_remove_keys, KemCreateKeypairFixture)
+{
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ UNEXPORTABLE,
+ UNEXPORTABLE);
+
+ ckmc_remove_alias(private_key_alias.c_str());
+ ckmc_remove_alias(public_key_alias.c_str());
+
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type_768,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ UNEXPORTABLE_PW,
+ UNEXPORTABLE_PW);
+
+ ckmc_remove_alias(private_key_alias.c_str());
+ ckmc_remove_alias(public_key_alias.c_str());
+}
+
+RUNNER_TEST(KEM_save_get_key, KemCreateKeypairFixture)
+{
+ for (const auto& kem_type : {ckmc_kem_type_e::CKMC_ML_KEM_768, ckmc_kem_type_e::CKMC_ML_KEM_1024})
+ {
+ AliasRemover removers[] = {private_key_alias.c_str(), public_key_alias.c_str(),
+ private_key_alias_second.c_str(), public_key_alias_second.c_str()};
+
+ assert_positive(ckmc_create_key_pair_kem,
+ kem_type,
+ private_key_alias.c_str(),
+ public_key_alias.c_str(),
+ EXPORTABLE_PW,
+ EXPORTABLE);
+
+ ckmc_key_s *private_key = nullptr;
+ assert_positive(ckmc_get_key,
+ private_key_alias.c_str(),
+ PASSWORD,
+ &private_key);
+ assert_positive(ckmc_save_key,
+ private_key_alias_second.c_str(),
+ *private_key,
+ EXPORTABLE);
+
+ ckmc_key_s *private_key_second = nullptr;
+ assert_positive(ckmc_get_key,
+ private_key_alias_second.c_str(),
+ nullptr,
+ &private_key_second);
+
+ assert_keys_equal(private_key, private_key_second);
+
+ ckmc_key_s *public_key = nullptr;
+ assert_positive(ckmc_get_key,
+ public_key_alias.c_str(),
+ nullptr,
+ &public_key);
+ assert_positive(ckmc_save_key,
+ public_key_alias_second.c_str(),
+ *public_key,
+ EXPORTABLE_PW);
+
+ ckmc_key_s *public_key_second = nullptr;
+ assert_positive(ckmc_get_key,
+ public_key_alias_second.c_str(),
+ PASSWORD,
+ &public_key_second);
+
+ assert_keys_equal(public_key, public_key_second);
+
+ ckmc_key_free(private_key);
+ ckmc_key_free(private_key_second);
+ ckmc_key_free(public_key);
+ ckmc_key_free(public_key_second);
+ }
+}