Add ML-KEM derive hybrid tests 40/315340/19
authorJakub Wlostowski <j.wlostowski@samsung.com>
Tue, 30 Jul 2024 08:19:39 +0000 (10:19 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Thu, 29 Aug 2024 17:45:59 +0000 (19:45 +0200)
Change-Id: Ic1e09cc65f9d5afad44df70e2b9119bb66ee7580

src/ckm/unprivileged/kem-testcases.cpp

index 088c20c2ed4003c212d6619f4141bfad0ba71111..9b5093a62e9113a3ee4e566eaa1b527cdbb22174 100644 (file)
@@ -41,6 +41,13 @@ CKM::Alias public_key_alias_second = "kem-pub-second";
 CKM::Alias new_alias = "kem-test-new";
 CKM::Alias encapsulated_secret_alias = "kem-shared-secret-encaps";
 CKM::Alias decapsulated_secret_alias = "kem-shared-secret-decaps";
+CKM::Alias encapsulated_secret_alias_second = "kem-shared-secret-encaps-second";
+CKM::Alias decapsulated_secret_alias_second = "kem-shared-secret-decaps-second";
+CKM::Alias derived_secret_alias = "kem-derived-secret";
+CKM::Alias derived_secret_alias_second = "kem-derived-secret-second";
+CKM::Alias aes256_key_alias = "aes256-key";
+CKM::Alias aes128_key_first_alias = "aes128-first-key";
+CKM::Alias aes128_key_second_alias = "aes128-second-key";
 
 const ckmc_policy_s UNEXPORTABLE { nullptr, false };
 const ckmc_policy_s EXPORTABLE { nullptr, true };
@@ -48,6 +55,8 @@ const ckmc_policy_s UNEXPORTABLE_PW { const_cast<char*>(PASSWORD), false };
 const ckmc_policy_s EXPORTABLE_PW { const_cast<char*>(PASSWORD), true };
 
 ParamListPtr kem_params_768;
+ParamListPtr kem_params_1024;
+ParamListPtr derive_params;
 ckmc_raw_buffer_s* DEFAULT_IV = nullptr;
 ckmc_kem_type_e kem_type_768 = ckmc_kem_type_e::CKMC_ML_KEM_768;
 
@@ -56,6 +65,11 @@ std::map<ckmc_kem_type_e, std::pair<CKM::Alias, CKM::Alias>> kem_types_keys_alia
        {ckmc_kem_type_e::CKMC_ML_KEM_1024, {private_key_alias_second, public_key_alias_second}},
 };
 
+std::array<std::pair<CKM::Alias, CKM::Alias>, 2> kem_types_encaps_decaps_aliases = {{
+       {encapsulated_secret_alias, decapsulated_secret_alias},
+       {encapsulated_secret_alias_second, decapsulated_secret_alias_second}
+}};
+
 ParamListPtr getDefaultParams(const Algo &algo) {
        ckmc_param_list_h handle = nullptr;
 
@@ -70,6 +84,22 @@ ParamListPtr getDefaultParams(const Algo &algo) {
        return params;
 }
 
+ParamListPtr getDefaultDeriveParams() {
+       ParamListPtr derive_params = createParamListPtr();
+       RawBufferPtr context = create_raw_buffer(createRandomBufferCAPI(12));
+       RawBufferPtr label = create_raw_buffer(createRandomBufferCAPI(16));
+
+       setParam(derive_params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+       setParam(derive_params, CKMC_PARAM_KDF_LEN, 32);
+       setParam(derive_params, CKMC_PARAM_KDF_PRF, CKMC_KDF_PRF_HMAC_SHA256);
+       setParam(derive_params, CKMC_PARAM_KBKDF_MODE, CKMC_KBKDF_MODE_COUNTER);
+       setParam(derive_params, CKMC_PARAM_KBKDF_COUNTER_LOCATION, CKMC_KBKDF_COUNTER_BEFORE_FIXED);
+       setParam(derive_params, CKMC_PARAM_KBKDF_CONTEXT, context.get());
+       setParam(derive_params, CKMC_PARAM_KBKDF_LABEL, label.get());
+
+       return derive_params;
+}
+
 void assert_encaps_decaps_positive(ParamListPtr params,
                                                                   CKM::Alias private_key_alias,
                                                                   CKM::Alias public_key_alias,
@@ -97,6 +127,20 @@ void assert_encaps_decaps_positive(ParamListPtr params,
        ckmc_buffer_free(ciphertext);
 }
 
+template <typename T>
+void assert_invalid_derivation_params(ckmc_param_name_e param_name, T value) {
+       ParamListPtr params = getDefaultDeriveParams();
+       setParam(params, param_name, value);
+       assert_invalid_param(ckmc_key_derive_hybrid,
+                                                params.get(),
+                                                encapsulated_secret_alias.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                nullptr,
+                                                derived_secret_alias.c_str(),
+                                                EXPORTABLE_PW);
+}
+
 void remove_keys_aliases()
 {
        ckmc_remove_alias(private_key_alias.c_str());
@@ -106,6 +150,49 @@ void remove_keys_aliases()
        ckmc_remove_alias(new_alias.c_str());
 }
 
+void get_params_create_keys()
+{
+       kem_params_768 = getDefaultParams(KEM_ALGO);
+       setParam(kem_params_768, CKMC_PARAM_KEM_TYPE,
+                        ckmc_kem_type_e::CKMC_ML_KEM_768);
+
+       kem_params_1024 = getDefaultParams(KEM_ALGO);
+       setParam(kem_params_1024, CKMC_PARAM_KEM_TYPE,
+                        ckmc_kem_type_e::CKMC_ML_KEM_1024);
+
+       assert_positive(ckmc_create_key_pair_kem,
+                                       ckmc_kem_type_e::CKMC_ML_KEM_768,
+                                       private_key_alias.c_str(),
+                                       public_key_alias.c_str(),
+                                       UNEXPORTABLE_PW,
+                                       UNEXPORTABLE);
+
+       assert_positive(ckmc_create_key_pair_kem,
+                                       ckmc_kem_type_e::CKMC_ML_KEM_1024,
+                                       private_key_alias_second.c_str(),
+                                       public_key_alias_second.c_str(),
+                                       UNEXPORTABLE_PW,
+                                       UNEXPORTABLE);
+}
+
+ckmc_key_s* divideAesKey(ckmc_key_s* aes256_key, int sizeInBits, int startingBit)
+{
+       int sizeInBytes = sizeInBits / 8;
+       int startingByte = startingBit / 8;
+       unsigned char new_raw_key[sizeInBytes];
+       memcpy(new_raw_key, aes256_key->raw_key + startingByte, sizeInBytes);
+
+       ckmc_key_s *new_key = nullptr;
+       assert_positive(ckmc_key_new,
+                                       new_raw_key,
+                                       sizeInBytes,
+                                       CKMC_KEY_AES,
+                                       nullptr,
+                                       &new_key);
+
+       return new_key;
+}
+
 class KemCreateKeypairGroupFixture : public DPL::Test::TestGroup
 {
 public:
@@ -143,24 +230,7 @@ public:
                assert_positive(ckmc_remove_user_data, OWNER_USER_ID);
                assert_positive(ckmc_unlock_user_key, OWNER_USER_ID, USER_PASS);
 
-               kem_params_768 = getDefaultParams(KEM_ALGO);
-               setParam(kem_params_768,
-                                CKMC_PARAM_KEM_TYPE,
-                                ckmc_kem_type_e::CKMC_ML_KEM_768);
-
-               assert_positive(ckmc_create_key_pair_kem,
-                                               ckmc_kem_type_e::CKMC_ML_KEM_768,
-                                               private_key_alias.c_str(),
-                                               public_key_alias.c_str(),
-                                               UNEXPORTABLE_PW,
-                                               UNEXPORTABLE);
-
-               assert_positive(ckmc_create_key_pair_kem,
-                                               ckmc_kem_type_e::CKMC_ML_KEM_1024,
-                                               private_key_alias_second.c_str(),
-                                               public_key_alias_second.c_str(),
-                                               UNEXPORTABLE_PW,
-                                               UNEXPORTABLE);
+               get_params_create_keys();
        }
 
        void Finish() override
@@ -186,6 +256,65 @@ public:
        }
 };
 
+class KemDeriveHybridGroupFixture : 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);
+
+               get_params_create_keys();
+
+               assert_encaps_decaps_positive(kem_params_768,
+                                                                         private_key_alias,
+                                                                         public_key_alias,
+                                                                         encapsulated_secret_alias,
+                                                                         decapsulated_secret_alias,
+                                                                         UNEXPORTABLE_PW,
+                                                                         UNEXPORTABLE);
+
+               assert_encaps_decaps_positive(kem_params_1024,
+                                                                         private_key_alias_second,
+                                                                         public_key_alias_second,
+                                                                         encapsulated_secret_alias_second,
+                                                                         decapsulated_secret_alias_second,
+                                                                         UNEXPORTABLE_PW,
+                                                                         UNEXPORTABLE);
+
+               derive_params = getDefaultDeriveParams();
+       }
+
+       void Finish() override
+       {
+               remove_keys_aliases();
+               ckmc_remove_alias(encapsulated_secret_alias.c_str());
+               ckmc_remove_alias(decapsulated_secret_alias.c_str());
+               ckmc_remove_alias(encapsulated_secret_alias_second.c_str());
+               ckmc_remove_alias(decapsulated_secret_alias_second.c_str());
+
+               assert_positive(ckmc_lock_user_key, OWNER_USER_ID);
+               assert_positive(ckmc_remove_user_data, OWNER_USER_ID);
+       }
+};
+
+class KemDeriveHybridFixture
+{
+public:
+       virtual void init(const std::string&)
+       {
+       }
+
+       virtual void finish()
+       {
+               ckmc_remove_alias(derived_secret_alias.c_str());
+               ckmc_remove_alias(derived_secret_alias_second.c_str());
+               ckmc_remove_alias(aes256_key_alias.c_str());
+               ckmc_remove_alias(aes128_key_first_alias.c_str());
+               ckmc_remove_alias(aes128_key_second_alias.c_str());
+       }
+};
+
 RUNNER_TEST_GROUP_INIT_ENV(CKMC_CREATE_KEYPAIR_KEM, KemCreateKeypairGroupFixture);
 
 RUNNER_TEST(KEM_create_key, KemCreateKeypairFixture)
@@ -799,3 +928,306 @@ RUNNER_TEST(KEM_encaps_decaps_create_keys_mismatch, KemEncapsDecapsFixture)
 
        ckmc_buffer_free(ciphertext);
 }
+
+RUNNER_TEST_GROUP_INIT_ENV(CKMC_DERIVE_HYBRID_KEM, KemDeriveHybridGroupFixture);
+
+RUNNER_TEST(KEM_derive_hybrid_create_key, KemDeriveHybridFixture)
+{
+       for (const auto& keys : kem_types_encaps_decaps_aliases)
+       {
+               CKM::Alias encapsulated_secret_alias = keys.first;
+               CKM::Alias decapsulated_secret_alias = keys.second;
+               AliasRemover removers[] = {derived_secret_alias.c_str()};
+
+               size_t current_aliases_num = count_aliases(ALIAS_KEY);
+               assert_positive(ckmc_key_derive_hybrid,
+                                               derive_params.get(),
+                                               encapsulated_secret_alias.c_str(),
+                                               PASSWORD,
+                                               decapsulated_secret_alias.c_str(),
+                                               nullptr,
+                                               derived_secret_alias.c_str(),
+                                               EXPORTABLE_PW);
+
+               size_t actual_cnt = count_aliases(ALIAS_KEY);
+               RUNNER_ASSERT_MSG(
+                               (current_aliases_num + 1) == actual_cnt,
+                               "Error: expecting " << (current_aliases_num + 1) << " aliases, while found " << actual_cnt);
+
+#ifndef TZ_BACKEND
+               ckmc_key_s *derived_secret = nullptr;
+               assert_positive(ckmc_get_key,
+                                               derived_secret_alias.c_str(),
+                                               PASSWORD,
+                                               &derived_secret);
+
+               assert_key_type_equal(CKMC_KEY_AES, derived_secret->key_type);
+               assert_key_valid(derived_secret, 32);
+
+               ckmc_key_free(derived_secret);
+#endif
+       }
+}
+
+RUNNER_TEST(KEM_derive_hybrid_keys_equal, KemDeriveHybridFixture)
+{
+       for (const auto& keys : kem_types_encaps_decaps_aliases)
+       {
+               CKM::Alias encapsulated_secret_alias = keys.first;
+               CKM::Alias decapsulated_secret_alias = keys.second;
+               AliasRemover removers[] = {derived_secret_alias.c_str(), derived_secret_alias_second.c_str()};
+
+               assert_positive(ckmc_key_derive_hybrid,
+                                               derive_params.get(),
+                                               encapsulated_secret_alias.c_str(),
+                                               PASSWORD,
+                                               decapsulated_secret_alias.c_str(),
+                                               nullptr,
+                                               derived_secret_alias.c_str(),
+                                               EXPORTABLE_PW);
+
+               assert_positive(ckmc_key_derive_hybrid,
+                                               derive_params.get(),
+                                               encapsulated_secret_alias.c_str(),
+                                               PASSWORD,
+                                               decapsulated_secret_alias.c_str(),
+                                               nullptr,
+                                               derived_secret_alias_second.c_str(),
+                                               EXPORTABLE);
+
+#ifdef TZ_BACKEND
+               ckmc_raw_buffer_s *encrypted = nullptr;
+               ckmc_raw_buffer_s *decrypted = nullptr;
+               ckmc_raw_buffer_s *dataToEncrypt = createRandomBufferCAPI(32);
+               ParamListPtr params = getDefaultParams(AES_CBC_ALGO);
+               assert_positive(ckmc_encrypt_data,
+                                               params.get(),
+                                               derived_secret_alias.c_str(),
+                                               PASSWORD,
+                                               *dataToEncrypt,
+                                               &encrypted);
+
+               assert_positive(ckmc_decrypt_data,
+                                               params.get(),
+                                               derived_secret_alias_second.c_str(),
+                                               nullptr,
+                                               *encrypted,
+                                               &decrypted);
+
+               assert_buffers_equal(dataToEncrypt, decrypted);
+
+               ckmc_buffer_free(dataToEncrypt);
+               ckmc_buffer_free(encrypted);
+               ckmc_buffer_free(decrypted);
+#else
+               ckmc_key_s *derived_secret_first = nullptr;
+               assert_positive(ckmc_get_key,
+                                               derived_secret_alias.c_str(),
+                                               PASSWORD,
+                                               &derived_secret_first);
+
+               ckmc_key_s *derived_secret_second = nullptr;
+               assert_positive(ckmc_get_key,
+                                               derived_secret_alias_second.c_str(),
+                                               nullptr,
+                                               &derived_secret_second);
+
+               assert_keys_equal(derived_secret_first, derived_secret_second);
+
+               ckmc_key_free(derived_secret_first);
+               ckmc_key_free(derived_secret_second);
+#endif
+       }
+}
+
+RUNNER_TEST(KEM_derive_hybrid_invalid_parameter, KemDeriveHybridFixture)
+{
+       assert_invalid_param(ckmc_key_derive_hybrid,
+                                                nullptr,
+                                                encapsulated_secret_alias.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                nullptr,
+                                                derived_secret_alias_second.c_str(),
+                                                EXPORTABLE_PW);
+
+       assert_invalid_param(ckmc_key_derive_hybrid,
+                                                derive_params.get(),
+                                                nullptr,
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                nullptr,
+                                                derived_secret_alias_second.c_str(),
+                                                EXPORTABLE_PW);
+
+       assert_invalid_param(ckmc_key_derive_hybrid,
+                                                derive_params.get(),
+                                                encapsulated_secret_alias.c_str(),
+                                                PASSWORD,
+                                                nullptr,
+                                                nullptr,
+                                                derived_secret_alias_second.c_str(),
+                                                EXPORTABLE_PW);
+
+       assert_invalid_param(ckmc_key_derive_hybrid,
+                                                derive_params.get(),
+                                                encapsulated_secret_alias.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                nullptr,
+                                                nullptr,
+                                                EXPORTABLE_PW);
+}
+
+RUNNER_TEST(KEM_derive_hybrid_invalid_password, KemDeriveHybridFixture)
+{
+       assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+                                 ckmc_key_derive_hybrid,
+                                 derive_params.get(),
+                                 encapsulated_secret_alias.c_str(),
+                                 "invalidpassword",
+                                 decapsulated_secret_alias.c_str(),
+                                 nullptr,
+                                 derived_secret_alias_second.c_str(),
+                                 EXPORTABLE_PW);
+
+       assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+                                 ckmc_key_derive_hybrid,
+                                 derive_params.get(),
+                                 encapsulated_secret_alias.c_str(),
+                                 PASSWORD,
+                                 decapsulated_secret_alias.c_str(),
+                                 "invalidpassword",
+                                 derived_secret_alias_second.c_str(),
+                                 EXPORTABLE_PW);
+}
+
+RUNNER_TEST(KEM_derive_hybrid_alias_exists, KemDeriveHybridFixture)
+{
+       assert_positive(ckmc_key_derive_hybrid,
+                                       derive_params.get(),
+                                       encapsulated_secret_alias.c_str(),
+                                       PASSWORD,
+                                       decapsulated_secret_alias.c_str(),
+                                       nullptr,
+                                       derived_secret_alias.c_str(),
+                                       UNEXPORTABLE);
+
+       // on next attempt to generate key with the same alias, expect fail (alias exists)
+       assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+                                 ckmc_key_derive_hybrid,
+                                 derive_params.get(),
+                                 encapsulated_secret_alias.c_str(),
+                                 PASSWORD,
+                                 decapsulated_secret_alias.c_str(),
+                                 nullptr,
+                                 derived_secret_alias.c_str(),
+                                 UNEXPORTABLE_PW);
+}
+
+RUNNER_TEST(KEM_derive_hybrid_alias_unknown, KemDeriveHybridFixture)
+{
+       // check case when en/decapsulated keys aliases do not exist
+       assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                                 ckmc_key_derive_hybrid,
+                                 derive_params.get(),
+                                 "new-alias",
+                                 PASSWORD,
+                                 decapsulated_secret_alias.c_str(),
+                                 nullptr,
+                                 derived_secret_alias.c_str(),
+                                 EXPORTABLE_PW);
+
+       assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                                 ckmc_key_derive_hybrid,
+                                 derive_params.get(),
+                                 encapsulated_secret_alias.c_str(),
+                                 PASSWORD,
+                                 "new-alias",
+                                 nullptr,
+                                 derived_secret_alias.c_str(),
+                                 EXPORTABLE_PW);
+}
+
+RUNNER_TEST(KEM_derive_hybrid_invalid_alias, KemDeriveHybridFixture)
+{
+       assert_invalid_param(ckmc_key_derive_hybrid,
+                                                derive_params.get(),
+                                                encapsulated_secret_alias.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                nullptr,
+                                                "derive hybrid invalid alias",
+                                                EXPORTABLE_PW);
+}
+
+RUNNER_TEST(KEM_derive_hybrid_invalid_derivation_parameters, KemDeriveHybridFixture)
+{
+       assert_invalid_derivation_params(CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KEM);
+       assert_invalid_derivation_params(CKMC_PARAM_KDF_LEN, 0);
+       assert_invalid_derivation_params(CKMC_PARAM_KDF_PRF, static_cast<ckmc_param_name_e>(5));
+       assert_invalid_derivation_params(CKMC_PARAM_KBKDF_MODE, static_cast<ckmc_param_name_e>(5));
+       assert_invalid_derivation_params(CKMC_PARAM_KBKDF_COUNTER_LOCATION, static_cast<ckmc_param_name_e>(5));
+}
+
+RUNNER_TEST(KEM_derive_hybrid_check_derived_keys, KemDeriveHybridFixture)
+{
+       assert_positive(ckmc_create_key_aes,
+                                       256,
+                                       aes256_key_alias.c_str(),
+                                       EXPORTABLE_PW);
+
+       ckmc_key_s *aes_key = nullptr;
+       assert_positive(ckmc_get_key,
+                                       aes256_key_alias.c_str(),
+                                       PASSWORD,
+                                       &aes_key);
+
+       assert_positive(ckmc_key_derive,
+                                       derive_params.get(),
+                                       aes256_key_alias.c_str(),
+                                       PASSWORD,
+                                       derived_secret_alias.c_str(),
+                                       EXPORTABLE_PW);
+
+       ckmc_key_s *derived_secret_first = nullptr;
+       assert_positive(ckmc_get_key,
+                                       derived_secret_alias.c_str(),
+                                       PASSWORD,
+                                       &derived_secret_first);
+
+       ckmc_key_s* aes_key_first_part = divideAesKey(aes_key, 128, 0);
+       assert_positive(ckmc_save_key,
+                                       aes128_key_first_alias.c_str(),
+                                       *aes_key_first_part,
+                                       EXPORTABLE);
+
+       ckmc_key_s* aes_key_second_part = divideAesKey(aes_key, 128, 128);
+       assert_positive(ckmc_save_key,
+                                       aes128_key_second_alias.c_str(),
+                                       *aes_key_second_part,
+                                       EXPORTABLE);
+
+       assert_positive(ckmc_key_derive_hybrid,
+                                       derive_params.get(),
+                                       aes128_key_first_alias.c_str(),
+                                       nullptr,
+                                       aes128_key_second_alias.c_str(),
+                                       nullptr,
+                                       derived_secret_alias_second.c_str(),
+                                       EXPORTABLE_PW);
+
+       ckmc_key_s *derived_secret_second = nullptr;
+       assert_positive(ckmc_get_key,
+                                       derived_secret_alias_second.c_str(),
+                                       PASSWORD,
+                                       &derived_secret_second);
+
+       assert_keys_equal(derived_secret_first, derived_secret_second);
+
+       ckmc_key_free(aes_key);
+       ckmc_key_free(derived_secret_first);
+       ckmc_key_free(derived_secret_second);
+       ckmc_key_free(aes_key_first_part);
+       ckmc_key_free(aes_key_second_part);
+}