From c4e617959182391f558bf339f512e32b38cad285 Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Fri, 24 Feb 2023 09:58:28 +0100 Subject: [PATCH] E2EE: PBKDF API implementation Tests included Change-Id: I4cbe3363690ff116a8c26dba3e6bfca8d9e0dad5 --- src/e2ee-adaptation-layer/CMakeLists.txt | 1 + .../e2ee-adaptation-layer.cpp | 39 ++++++-- src/e2ee-adaptation-layer/tests.cpp | 100 ++++++++++++++++++++- 3 files changed, 131 insertions(+), 9 deletions(-) diff --git a/src/e2ee-adaptation-layer/CMakeLists.txt b/src/e2ee-adaptation-layer/CMakeLists.txt index 1971096..03cff11 100644 --- a/src/e2ee-adaptation-layer/CMakeLists.txt +++ b/src/e2ee-adaptation-layer/CMakeLists.txt @@ -21,6 +21,7 @@ SET(TARGET_E2EE_ADAPTATION_LAYER "e2ee-adaptation-layer") PKG_CHECK_MODULES(E2EE_ADAPTATION_LAYER_DEP REQUIRED key-manager # >=0.1.48 + openssl1.1 ) SET(E2EE_ADAPTATION_LAYER_SOURCES diff --git a/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp b/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp index d5b39ec..73d068e 100644 --- a/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp +++ b/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include namespace { @@ -26,6 +28,7 @@ namespace { const char* const LABEL = "label"; const char* const CONTEXT = "context"; const char* const SECRET_ALIAS = "temporary_shared_e2ee_secret"; +constexpr size_t ITERATIONS = 1000; typedef std::unique_ptr ParamsPtr; @@ -153,14 +156,36 @@ int ckmew_key_agreement(const char *private_key_alias, return ckmc_key_derive(kbkdf_params.get(), SECRET_ALIAS, nullptr, new_key_alias, unexportable); } -int ckmew_key_derive_pbkdf2(const char * /*password*/, - const unsigned char * /*salt*/, - size_t /*salt_len*/, - size_t /*new_key_len*/, - const char * /*new_key_alias*/) +int ckmew_key_derive_pbkdf2(const char *password, + const unsigned char *salt, + size_t salt_len, + size_t new_key_len, + const char *new_key_alias) { - // TODO - return CKMC_ERROR_NONE; + if (password == nullptr || salt == nullptr || new_key_alias == nullptr || new_key_len == 0) + return CKMC_ERROR_INVALID_PARAMETER; + + unsigned char derived[new_key_len]; + + if (1 != PKCS5_PBKDF2_HMAC_SHA1(password, + strlen(password), + salt, + salt_len, + ITERATIONS, + new_key_len, + derived)) + return CKMC_ERROR_SERVER_ERROR; + + ckmc_key_s* key = nullptr; + int ret = ckmc_key_new(derived, new_key_len, CKMC_KEY_AES, nullptr, &key); + if (ret != CKMC_ERROR_NONE) + return ret; + + ckmc_policy_s unexportable { nullptr, false }; + ret = ckmc_save_key(new_key_alias, *key, unexportable); + ckmc_key_free(key); + + return ret; } int ckmew_get_ocf_cert_chain(char ** /*cert_chain*/, size_t * /*cert_chain_len*/) diff --git a/src/e2ee-adaptation-layer/tests.cpp b/src/e2ee-adaptation-layer/tests.cpp index ff743fd..e60d543 100644 --- a/src/e2ee-adaptation-layer/tests.cpp +++ b/src/e2ee-adaptation-layer/tests.cpp @@ -37,6 +37,11 @@ const KeyAliasPair PEERS2 = { "peer2_ec_private", "peer2_ec_public" }; const KeyAliasPair WRONG = { "wrong_ec_private", "wrong_ec_public" }; const KeyAliasPair RSA = { "rsa_private", "rsa_public" }; +const char* const DERIVED = "derived"; + +constexpr size_t SALT_LEN = 16; +const unsigned char SALT[SALT_LEN] = {}; + const ckmc_policy_s UNEXPORTABLE { nullptr, false }; const ckmc_policy_s EXPORTABLE { nullptr, true }; @@ -147,8 +152,6 @@ RUNNER_TEST(TEAL_0010_key_agreement_positive) RUNNER_TEST(TEAL_0020_key_agreement_wrong_arguments) { - const char* const DERIVED = "derived"; - auto pub_key = getKey(PEERS.pub); auto invalid = [](const char* prv, @@ -206,6 +209,99 @@ RUNNER_TEST(TEAL_0030_key_agreement_wrong_aliases) DERIVED); } +RUNNER_TEST(TEAL_1000_pbkdf_positive) +{ + constexpr size_t KEY_LEN = 32; + + auto plain = create_raw_buffer(createRandomBufferCAPI(512)); + auto iv = create_raw_buffer(createRandomBufferCAPI(16)); + auto salt = create_raw_buffer(createRandomBufferCAPI(SALT_LEN)); + + auto params = createParamListPtr(); + setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR); + setParam(params, CKMC_PARAM_ED_IV, iv.get()); + + assert_positive(ckmew_key_derive_pbkdf2, "password", salt->data, salt->size, KEY_LEN, DERIVED); + auto remover1 = AliasRemover(DERIVED); + + ckmc_raw_buffer_s* encrypted = nullptr; + assert_positive(ckmc_encrypt_data, params.get(), DERIVED, "", *plain.get(), &encrypted); + auto encryptedPtr = create_raw_buffer(encrypted); + + auto deriveAndDecrypt = [&encryptedPtr, ¶ms](const char* password, + const unsigned char* salt, + size_t salt_len, + size_t key_len) + { + const char* const DERIVED2 = "derived2"; + assert_positive(ckmew_key_derive_pbkdf2, password, salt, salt_len, key_len, DERIVED2); + auto remover = AliasRemover(DERIVED2); + + ckmc_raw_buffer_s* decrypted = nullptr; + assert_positive(ckmc_decrypt_data, + params.get(), + DERIVED2, + "", + *encryptedPtr.get(), + &decrypted); + + return create_raw_buffer(decrypted); + }; + + RawBufferPtr decrypted; + decrypted = deriveAndDecrypt("password", salt->data, salt->size, KEY_LEN); + assert_buffers_equal(plain.get(), decrypted.get()); + + decrypted = deriveAndDecrypt("wrong", salt->data, salt->size, KEY_LEN); + assert_buffers_equal(plain.get(), decrypted.get(), false); + + decrypted = deriveAndDecrypt("password", salt->data, salt->size, KEY_LEN - 8); + assert_buffers_equal(plain.get(), decrypted.get(), false); + + decrypted = deriveAndDecrypt("password", salt->data, salt->size - 1, KEY_LEN); + assert_buffers_equal(plain.get(), decrypted.get(), false); + + decrypted = deriveAndDecrypt("password", plain->data, salt->size, KEY_LEN); + assert_buffers_equal(plain.get(), decrypted.get(), false); +} + +RUNNER_TEST(TEAL_1010_pbkdf_invalid_arguments) +{ + assert_invalid_param(ckmew_key_derive_pbkdf2, nullptr, SALT, SALT_LEN, 32, DERIVED); + assert_invalid_param(ckmew_key_derive_pbkdf2, "password", nullptr, SALT_LEN, 32, DERIVED); + assert_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, nullptr); + assert_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 0, DERIVED); + + auto invalidFormat = [&](size_t key_len) { + assert_result(CKMC_ERROR_INVALID_FORMAT, + ckmew_key_derive_pbkdf2, + "password", + SALT, + SALT_LEN, + key_len, + DERIVED); + }; + invalidFormat(64); + invalidFormat(31); + invalidFormat(8); + invalidFormat(1); +} + +RUNNER_TEST(TEAL_1020_pbkdf_wrong_alias) +{ + assert_positive(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, DERIVED); + + auto remover = AliasRemover(DERIVED); + + assert_result(CKMC_ERROR_DB_ALIAS_EXISTS, + ckmew_key_derive_pbkdf2, + "password", + SALT, + SALT_LEN, + 32, + DERIVED); +} + int main(int argc, char *argv[]) { return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv); -- 2.7.4