Add ML-KEM (en/de)capsulation tests 79/315079/20
authorJakub Wlostowski <j.wlostowski@samsung.com>
Wed, 24 Jul 2024 11:59:40 +0000 (13:59 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Thu, 29 Aug 2024 17:45:49 +0000 (19:45 +0200)
Change-Id: I521649fb59a464c7cf96fb08682d44ff1abde71d

src/ckm/unprivileged/kem-testcases.cpp

index a77ebbf39b1d9f0fae2a12301b57b5fc9bdf9a11..088c20c2ed4003c212d6619f4141bfad0ba71111 100644 (file)
 const char* PASSWORD = "test-password";
 const char* USER_PASS = "user-pass";
 
+struct Algo {
+       ckmc_algo_type_e type;
+       size_t initVector;
+};
+
+const Algo KEM_ALGO = {CKMC_ALGO_KEM, 0};
+const Algo AES_CBC_ALGO = {CKMC_ALGO_AES_CBC, 16};
+
 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;
+CKM::Alias encapsulated_secret_alias = "kem-shared-secret-encaps";
+CKM::Alias decapsulated_secret_alias = "kem-shared-secret-decaps";
 
 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 };
 
+ParamListPtr kem_params_768;
+ckmc_raw_buffer_s* DEFAULT_IV = nullptr;
+ckmc_kem_type_e kem_type_768 = ckmc_kem_type_e::CKMC_ML_KEM_768;
+
+std::map<ckmc_kem_type_e, std::pair<CKM::Alias, CKM::Alias>> kem_types_keys_aliases = {
+       {ckmc_kem_type_e::CKMC_ML_KEM_768, {private_key_alias, public_key_alias}},
+       {ckmc_kem_type_e::CKMC_ML_KEM_1024, {private_key_alias_second, public_key_alias_second}},
+};
+
+ParamListPtr getDefaultParams(const Algo &algo) {
+       ckmc_param_list_h handle = nullptr;
+
+       assert_positive(ckmc_generate_new_params, algo.type, &handle);
+       ParamListPtr params = ParamListPtr(handle, ckmc_param_list_free);
+
+       if (algo.initVector) {
+               DEFAULT_IV = createRandomBufferCAPI(algo.initVector);
+               setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
+       }
+
+       return params;
+}
+
+void assert_encaps_decaps_positive(ParamListPtr params,
+                                                                  CKM::Alias private_key_alias,
+                                                                  CKM::Alias public_key_alias,
+                                                                  CKM::Alias encapsulated_secret_alias,
+                                                                  CKM::Alias decapsulated_secret_alias,
+                                                                  ckmc_policy_s encapsulated_secret_policy,
+                                                                  ckmc_policy_s decapsulated_secret_policy) {
+       ckmc_raw_buffer_s *ciphertext = nullptr;
+       assert_positive(ckmc_encapsulate_key,
+                                       params.get(),
+                                       public_key_alias.c_str(),
+                                       nullptr,
+                                       encapsulated_secret_alias.c_str(),
+                                       encapsulated_secret_policy,
+                                       &ciphertext);
+
+       assert_positive(ckmc_decapsulate_key,
+                                       params.get(),
+                                       private_key_alias.c_str(),
+                                       PASSWORD,
+                                       decapsulated_secret_alias.c_str(),
+                                       decapsulated_secret_policy,
+                                       ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
 void remove_keys_aliases()
 {
        ckmc_remove_alias(private_key_alias.c_str());
@@ -77,6 +135,57 @@ public:
        }
 };
 
+class KemEncapsDecapsGroupFixture : 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);
+
+               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);
+       }
+
+       void Finish() override
+       {
+               remove_keys_aliases();
+
+               assert_positive(ckmc_lock_user_key, OWNER_USER_ID);
+               assert_positive(ckmc_remove_user_data, OWNER_USER_ID);
+       }
+};
+
+class KemEncapsDecapsFixture
+{
+public:
+       virtual void init(const std::string&)
+       {
+       }
+
+       virtual void finish()
+       {
+               ckmc_remove_alias(encapsulated_secret_alias.c_str());
+               ckmc_remove_alias(decapsulated_secret_alias.c_str());
+       }
+};
+
 RUNNER_TEST_GROUP_INIT_ENV(CKMC_CREATE_KEYPAIR_KEM, KemCreateKeypairGroupFixture);
 
 RUNNER_TEST(KEM_create_key, KemCreateKeypairFixture)
@@ -350,3 +459,343 @@ RUNNER_TEST(KEM_save_get_key, KemCreateKeypairFixture)
                ckmc_key_free(public_key_second);
        }
 }
+
+RUNNER_TEST_GROUP_INIT_ENV(CKMC_ENCAPS_DECAPS_KEM, KemEncapsDecapsGroupFixture);
+
+RUNNER_TEST(KEM_encaps_decaps_check_keys, KemEncapsDecapsFixture)
+{
+       for (const auto& [kem_type, keys] : kem_types_keys_aliases)
+       {
+               CKM::Alias private_key_alias = keys.first;
+               CKM::Alias public_key_alias = keys.second;
+
+               ParamListPtr params = getDefaultParams(KEM_ALGO);
+               setParam(params, CKMC_PARAM_KEM_TYPE, kem_type);
+
+               AliasRemover removers[] = {encapsulated_secret_alias.c_str(), decapsulated_secret_alias.c_str()};
+
+               size_t current_aliases_num = count_aliases(ALIAS_KEY);
+
+               assert_encaps_decaps_positive(params,
+                                                                         private_key_alias,
+                                                                         public_key_alias,
+                                                                         encapsulated_secret_alias,
+                                                                         decapsulated_secret_alias,
+#ifdef TZ_BACKEND
+                                                                         UNEXPORTABLE_PW, UNEXPORTABLE
+#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);
+
+#ifdef TZ_BACKEND
+               ckmc_raw_buffer_s *encrypted = nullptr;
+               ckmc_raw_buffer_s *decrypted = nullptr;
+               ckmc_raw_buffer_s *dataToEncrypt = createRandomBufferCAPI(32);
+               params = getDefaultParams(AES_CBC_ALGO);
+               assert_positive(ckmc_encrypt_data,
+                                               params.get(),
+                                               encapsulated_secret_alias.c_str(),
+                                               PASSWORD,
+                                               *dataToEncrypt,
+                                               &encrypted);
+
+               assert_positive(ckmc_decrypt_data,
+                                               params.get(),
+                                               decapsulated_secret_alias.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 *encapsulated_secret = nullptr;
+               assert_positive(ckmc_get_key,
+                                               encapsulated_secret_alias.c_str(),
+                                               PASSWORD,
+                                               &encapsulated_secret);
+
+               assert_key_type_equal(CKMC_KEY_AES, encapsulated_secret->key_type);
+               assert_key_valid(encapsulated_secret, 32);
+
+               ckmc_key_s *decapsulated_secret = nullptr;
+               assert_positive(ckmc_get_key,
+                                               decapsulated_secret_alias.c_str(),
+                                               nullptr,
+                                               &decapsulated_secret);
+
+               assert_key_type_equal(CKMC_KEY_AES, decapsulated_secret->key_type);
+               assert_key_valid(decapsulated_secret, 32);
+
+               assert_keys_equal(encapsulated_secret, decapsulated_secret);
+
+               ckmc_key_free(encapsulated_secret);
+               ckmc_key_free(decapsulated_secret);
+#endif
+       }
+}
+
+RUNNER_TEST(KEM_encaps_decaps_invalid_parameter, KemEncapsDecapsFixture)
+{
+       ParamListPtr aes_cbc_params = getDefaultParams(AES_CBC_ALGO);
+
+       ckmc_raw_buffer_s *ciphertext;
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                nullptr,
+                                                public_key_alias.c_str(),
+                                                nullptr,
+                                                encapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                kem_params_768.get(),
+                                                nullptr,
+                                                nullptr,
+                                                encapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                kem_params_768.get(),
+                                                public_key_alias.c_str(),
+                                                nullptr,
+                                                nullptr,
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                kem_params_768.get(),
+                                                private_key_alias.c_str(),
+                                                PASSWORD,
+                                                encapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                aes_cbc_params.get(),
+                                                public_key_alias.c_str(),
+                                                nullptr,
+                                                encapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       ciphertext = createRandomBufferCAPI(1);
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                nullptr,
+                                                private_key_alias.c_str(),
+                                                nullptr,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_768.get(),
+                                                nullptr,
+                                                nullptr,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_768.get(),
+                                                private_key_alias.c_str(),
+                                                nullptr,
+                                                nullptr,
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_768.get(),
+                                                private_key_alias.c_str(),
+                                                nullptr,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                nullptr);
+
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_768.get(),
+                                                public_key_alias.c_str(),
+                                                nullptr,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                aes_cbc_params.get(),
+                                                private_key_alias.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
+RUNNER_TEST(KEM_encaps_decaps_invalid_password, KemEncapsDecapsFixture)
+{
+       ckmc_raw_buffer_s *ciphertext;
+       assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+                                 ckmc_encapsulate_key,
+                                 kem_params_768.get(),
+                                 public_key_alias.c_str(),
+                                 "invalidpassword",
+                                 encapsulated_secret_alias.c_str(),
+                                 UNEXPORTABLE,
+                                 &ciphertext);
+
+       ciphertext = createRandomBufferCAPI(1);
+       assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+                                 ckmc_decapsulate_key,
+                                 kem_params_768.get(),
+                                 private_key_alias.c_str(),
+                                 "invalidpassword",
+                                 decapsulated_secret_alias.c_str(),
+                                 UNEXPORTABLE,
+                                 ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
+RUNNER_TEST(KEM_encaps_decaps_alias_exists, KemEncapsDecapsFixture)
+{
+       assert_encaps_decaps_positive(kem_params_768,
+                                                                 private_key_alias,
+                                                                 public_key_alias,
+                                                                 encapsulated_secret_alias,
+                                                                 decapsulated_secret_alias,
+                                                                 UNEXPORTABLE_PW,
+                                                                 UNEXPORTABLE);
+
+       // on next attempt to generate keys with the same alias, expect fail (alias exists)
+       ckmc_raw_buffer_s *ciphertext = nullptr;
+       assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+                                 ckmc_encapsulate_key,
+                                 kem_params_768.get(),
+                                 public_key_alias.c_str(),
+                                 nullptr,
+                                 encapsulated_secret_alias.c_str(),
+                                 UNEXPORTABLE,
+                                 &ciphertext);
+
+       ciphertext = createRandomBufferCAPI(1);
+       assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+                                 ckmc_decapsulate_key,
+                                 kem_params_768.get(),
+                                 private_key_alias.c_str(),
+                                 PASSWORD,
+                                 decapsulated_secret_alias.c_str(),
+                                 UNEXPORTABLE,
+                                 ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
+RUNNER_TEST(KEM_encaps_decaps_alias_unknown, KemEncapsDecapsFixture)
+{
+       // check case when private/public keys aliases do not exist
+       ckmc_raw_buffer_s *ciphertext;
+       assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                                 ckmc_encapsulate_key,
+                                 kem_params_768.get(),
+                                 new_alias.c_str(),
+                                 nullptr,
+                                 encapsulated_secret_alias.c_str(),
+                                 UNEXPORTABLE,
+                                 &ciphertext);
+
+       ciphertext = createRandomBufferCAPI(1);
+       assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+                                 ckmc_decapsulate_key,
+                                 kem_params_768.get(),
+                                 new_alias.c_str(),
+                                 PASSWORD,
+                                 decapsulated_secret_alias.c_str(),
+                                 UNEXPORTABLE,
+                                 ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
+RUNNER_TEST(KEM_encaps_decaps_invalid_alias, KemEncapsDecapsFixture)
+{
+       ckmc_raw_buffer_s *ciphertext;
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                kem_params_768.get(),
+                                                public_key_alias.c_str(),
+                                                nullptr,
+                                                "encaps invalid alias",
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       ciphertext = createRandomBufferCAPI(1);
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_768.get(),
+                                                private_key_alias.c_str(),
+                                                PASSWORD,
+                                                "decaps invalid alias",
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
+RUNNER_TEST(KEM_encaps_decaps_kem_type_mismatch, KemEncapsDecapsFixture)
+{
+       ckmc_raw_buffer_s *ciphertext = nullptr;
+       assert_positive(ckmc_encapsulate_key,
+                                       kem_params_768.get(),
+                                       public_key_alias.c_str(),
+                                       nullptr,
+                                       encapsulated_secret_alias.c_str(),
+                                       UNEXPORTABLE,
+                                       &ciphertext);
+
+       ParamListPtr kem_params_1024 = getDefaultParams(KEM_ALGO);
+       setParam(kem_params_1024,
+                        CKMC_PARAM_KEM_TYPE,
+                        ckmc_kem_type_e::CKMC_ML_KEM_1024);
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_1024.get(),
+                                                private_key_alias.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}
+
+RUNNER_TEST(KEM_encaps_decaps_create_keys_mismatch, KemEncapsDecapsFixture)
+{
+       // check case when en/decapsulation KEM type differs from private/public key KEM type
+       ckmc_raw_buffer_s *ciphertext = nullptr;
+       assert_invalid_param(ckmc_encapsulate_key,
+                                                kem_params_768.get(),
+                                                public_key_alias_second.c_str(),
+                                                nullptr,
+                                                encapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                &ciphertext);
+
+       ciphertext = createRandomBufferCAPI(1);
+       assert_invalid_param(ckmc_decapsulate_key,
+                                                kem_params_768.get(),
+                                                private_key_alias_second.c_str(),
+                                                PASSWORD,
+                                                decapsulated_secret_alias.c_str(),
+                                                UNEXPORTABLE,
+                                                ciphertext);
+
+       ckmc_buffer_free(ciphertext);
+}