SET(BUILD_YACA ON)
SET(BUILD_NETHER ON)
SET(BUILD_ODE ON)
+ SET(BUILD_E2EE_ADAPTATION_LAYER ON)
ENDIF(BUILD_ALL_TESTS)
# If supported for the target machine, emit position-independent code,suitable
SET(TARGET_CKM_PRIVILEGED_TESTS "ckm-privileged-tests")
SET(TARGET_CKMI_TESTS "ckm-integration-tests")
SET(COMMON_TARGET_TEST "tests-common")
+SET(TARGET_E2EE_TESTS "e2ee-tests")
############################# subdirectories ##################################
<filesystem path="/usr/bin/security-manager-tests" exec_label="System::Privileged" />
<filesystem path="/usr/bin/cynara-tests" exec_label="_" />
<filesystem path="/usr/bin/ckm-tests" exec_label="User" />
+ <filesystem path="/usr/bin/e2ee-tests" exec_label="User" />
<filesystem path="/usr/bin/ckm-privileged-tests" exec_label="System::Privileged" />
<filesystem path="/usr/bin/nether-tests" exec_label="System::Privileged" />
<filesystem path="/usr/bin/libteec-tests" exec_label="System::Privileged" />
BuildRequires: pkgconfig(libcap)
BuildRequires: pkgconfig(libsmack)
BuildRequires: pkgconfig(security-manager)
-BuildRequires: pkgconfig(key-manager)
+BuildRequires: pkgconfig(key-manager) >= 0.1.49
BuildRequires: key-manager-initial-values
BuildRequires: util-linux
BuildRequires: pkgconfig(yaca)
BuildRequires: pkgconfig(libgum) >= 1.0.5
BuildRequires: pkgconfig(security-privilege-manager)
BuildRequires: pkgconfig(libsystemd)
+BuildRequires: pkgconfig(device-certificate-manager) >= 2.1
BuildRequires: openssl1.1
Requires: gdb
Requires: diffutils
/usr/bin/yaca-test
/usr/bin/nether-tests
/usr/bin/ode-tests
+/usr/bin/e2ee-tests
%{ckm_test_dir}/*
/etc/security-tests
/usr/lib/security-tests/cynara-tests/plugins/single-policy/*
IF(BUILD_ODE)
ADD_SUBDIRECTORY(ode)
ENDIF(BUILD_ODE)
+
+IF(BUILD_E2EE_ADAPTATION_LAYER)
+ ADD_SUBDIRECTORY(e2ee-adaptation-layer)
+ENDIF(BUILD_E2EE_ADAPTATION_LAYER)
PKG_CHECK_MODULES(CKM_TEST_COMMON_DEP
REQUIRED
openssl1.1
- key-manager
+ key-manager>=0.1.49
libtzplatform-config
)
* @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
* @version 1.0
*/
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <cstdlib>
#include <string>
#include <fstream>
#include <sys/smack.h>
#include <fcntl.h>
#include <unistd.h>
#include <unordered_map>
+#include <tzplatform_config.h>
const std::string SMACK_USER_APP_PREFIX = "User::Pkg::";
const char *SYSTEM_LABEL = ckmc_owner_id_system;
return ParamListPtr(list, ckmc_param_list_free);
}
-void assert_buffers_equal(const ckmc_raw_buffer_s b1, const ckmc_raw_buffer_s b2, bool equal)
+void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
+{
+ int ret = ckmc_param_list_set_buffer(params.get(), name, buffer);
+ RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
+ "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
+}
+
+void setParam(ParamListPtr& params, ckmc_param_name_e name, uint64_t integer)
+{
+ int ret = ckmc_param_list_set_integer(params.get(), name, integer);
+ RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
+ "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
+}
+
+void assert_buffers_equal(const ckmc_raw_buffer_s* b1, const ckmc_raw_buffer_s* b2, bool equal)
{
if(equal) {
- RUNNER_ASSERT_MSG(b1.size == b2.size, "Buffer size differs: " << b1.size << "!=" << b2.size);
- RUNNER_ASSERT_MSG(0 == memcmp(b1.data, b2.data, b1.size), "Buffer contents differ");
+ RUNNER_ASSERT_MSG(b1->size == b2->size,
+ "Buffer size differs: " << b1->size << "!=" << b2->size);
+ RUNNER_ASSERT_MSG(0 == memcmp(b1->data, b2->data, b1->size), "Buffer contents differ");
} else {
- RUNNER_ASSERT_MSG(b1.size != b2.size || 0 != memcmp(b1.data, b2.data, b1.size),
+ RUNNER_ASSERT_MSG(b1->size != b2->size || 0 != memcmp(b1->data, b2->data, b1->size),
"Buffers should be different");
}
}
}
return CKM::Policy();
}
+
+void require_default_user(char *argv[])
+{
+ uid_t expected_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+ if (expected_uid != geteuid()) {
+ std::string userStr("owner");
+ const char* user = tzplatform_getenv(TZ_SYS_DEFAULT_USER);
+ if (user)
+ userStr = user;
+
+ std::cerr << argv[0] << " should be executed as " << userStr << ". Aborting" << std::endl;
+ exit(-1);
+ }
+}
#include <ckm/ckm-manager-async.h>
#include <ckmc/ckmc-type.h>
#include <ckmc/ckmc-error.h>
+#include <ckmc/ckmc-manager.h>
#include <tests_common.h>
#include <sys/types.h>
return size;
}
-// scoped free
-typedef std::unique_ptr<char, void (*)(void *)> CharPtr;
-
std::string getLabel();
// returns process owner id
std::string getOwnerIdFromSelf();
typedef std::shared_ptr<struct __ckmc_param_list> ParamListPtr;
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_buffers_equal(const ckmc_raw_buffer_s* b1, const ckmc_raw_buffer_s* b2, bool equal=true);
RawBufferPtr create_raw_buffer(ckmc_raw_buffer_s* buffer);
RUNNER_ASSERT_MSG(false, "Unexpected exception");
}
}
+
+class AliasRemover
+{
+public:
+ AliasRemover(const char* alias) : alias(alias) {}
+ ~AliasRemover() {
+ ckmc_remove_alias(alias);
+ }
+
+ AliasRemover(AliasRemover&& other) {
+ alias = other.alias;
+ other.alias = nullptr;
+ }
+
+ AliasRemover& operator=(AliasRemover&& other) {
+ if (&other == this)
+ return *this;
+
+ alias = other.alias;
+ other.alias = nullptr;
+ }
+
+private:
+ const char* alias;
+};
+
+void require_default_user(char *argv[]);
encryption-decryption-env.cpp
encryption-decryption.cpp
sign-verify.cpp
+ key-wrapping.cpp
+ key-derivation.cpp
main.cpp
)
ckmc_raw_buffer_s* got = NULL;
int ret = ckmc_param_list_get_buffer(list, name, &got);
RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE, "No such buffer param: " << name);
- assert_buffers_equal(expected, *got);
+ assert_buffers_equal(&expected, got);
}
void assert_param_count(ckmc_param_list_h list, size_t expected)
CKMCReadableError(temp));
RUNNER_ASSERT_MSG(
- CKMC_ERROR_INVALID_PARAMETER == (temp = ckmc_save_data("data4", testData3, test_policy3)),
+ CKMC_ERROR_NONE == (temp = ckmc_save_data("data4", testData3, test_policy3)),
CKMCReadableError(temp));
size_t actual_cnt = count_aliases(ALIAS_DATA);
RUNNER_ASSERT_MSG(
- (current_aliases_num+3) == actual_cnt,
- "Error: expecting " << (current_aliases_num+3) << " aliases, while found " << actual_cnt);
+ (current_aliases_num+4) == actual_cnt,
+ "Error: expecting " << (current_aliases_num+4) << " aliases, while found " << actual_cnt);
ckmc_raw_buffer_s *testData4;
RUNNER_ASSERT_MSG(
PolicyBackend m_backend;
};
-
-void setParam(ParamListPtr& params, ckmc_param_name_e name, ckmc_raw_buffer_s* buffer)
-{
- int ret = ckmc_param_list_set_buffer(params.get(), name, buffer);
- RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
- "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
-}
-
-void setParam(ParamListPtr& params, ckmc_param_name_e name, int integer)
-{
- int ret = ckmc_param_list_set_integer(params.get(), name, integer);
- RUNNER_ASSERT_MSG(ret == CKMC_ERROR_NONE,
- "Failed to set param " << name << " error: " << CKMCErrorToString(ret));
-}
-
struct EncryptionResult
{
RawBufferPtr encrypted;
RawBufferPtr tmpDec = create_raw_buffer(decrypted);
// check
- assert_buffers_equal(*PLAIN_DATA.get(), *tmpDec.get());
+ assert_buffers_equal(PLAIN_DATA.get(), tmpDec.get());
tmpDec.reset();
decrypted = nullptr;
&decryptedTmp);
decrypted = create_raw_buffer(decryptedTmp);
- assert_buffers_equal(*PLAIN_DATA.get(), *decrypted.get());
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted.get());
}
void testIntegrity(const Algo& algo)
&decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted);
- assert_buffers_equal(*PLAIN_DATA.get(), *decrypted, false);
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted, false);
}
void testCtrEncryptionInvalidLength(const Algo& algo)
encryptedTmp = nullptr;
};
// invalid counter size
- setParam(params, CKMC_PARAM_ED_CTR_LEN, -1);
- test();
- setParam(params, CKMC_PARAM_ED_CTR_LEN, 0);
+ setParam(params, CKMC_PARAM_ED_CTR_LEN, 0ULL);
test();
setParam(params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN+1);
test();
decrypted = nullptr;
};
// invalid counter size
- setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, -1);
- test();
- setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 0);
+ setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 0ULL);
test();
setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, CTR_DEFAULT_LEN+1);
test();
&decrypted);
ckmc_buffer_free(decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted);
- assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted);
};
// invalid counter size
setParam(ret.params, CKMC_PARAM_ED_CTR_LEN, 1);
&decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted);
- assert_buffers_equal(*BIG_DATA.get(), *decrypted);
+ assert_buffers_equal(BIG_DATA.get(), decrypted);
}
void testEncryptDecryptDifferentKeys(const Algo& algo, bool success)
&decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted);
- assert_buffers_equal(*PLAIN_DATA.get(), *decrypted, false);
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted, false);
} else {
assert_crypto_result(EncryptionError::INVALID_PARAM,
apiDecrypt,
&decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted);
- assert_buffers_equal(*plain.get(), *decrypted);
+ assert_buffers_equal(plain.get(), decrypted);
}
void testRsaDataTooLong(const Algo& algo, size_t dataSize)
&decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted);
- assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted);
});
}
&decrypted);
RawBufferPtr tmp = create_raw_buffer(decrypted); // guarantees deletion
- assert_buffers_equal(*PLAIN_DATA.get(), *decrypted);
+ assert_buffers_equal(PLAIN_DATA.get(), decrypted);
});
}
--- /dev/null
+/*
+ * Copyright (c) 2023 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 <string>
+#include <vector>
+#include <unordered_map>
+
+#include <dpl/test/test_runner.h>
+#include <ckm-common.h>
+#include <ckmc/ckmc-manager.h>
+#include <ckmc/ckmc-control.h>
+
+namespace {
+
+const char* PASSWORD = "test-password";
+const uid_t UID = 5001;
+
+struct KeyAliasPair
+{
+ std::string prv;
+ std::string pub;
+};
+
+const KeyAliasPair OURS = { "our_ec_private", "our_ec_public" };
+const KeyAliasPair PEERS = { "peer_ec_private", "peer_ec_public" };
+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 std::string DERIVED = "derived";
+const std::string SECRET = "secret";
+
+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 };
+
+constexpr ckmc_kdf_prf_e HMAC256 = CKMC_KDF_PRF_HMAC_SHA256;
+constexpr ckmc_kdf_prf_e HMAC384 = CKMC_KDF_PRF_HMAC_SHA384;
+constexpr ckmc_kdf_prf_e HMAC512 = CKMC_KDF_PRF_HMAC_SHA512;
+constexpr ckmc_kbkdf_counter_location_e BEFORE = CKMC_KBKDF_COUNTER_BEFORE_FIXED;
+constexpr ckmc_kbkdf_counter_location_e AFTER = CKMC_KBKDF_COUNTER_AFTER_FIXED;
+constexpr ckmc_kbkdf_counter_location_e MIDDLE = CKMC_KBKDF_COUNTER_MIDDLE_FIXED;
+constexpr ckmc_kbkdf_mode_e COUNTER = CKMC_KBKDF_MODE_COUNTER;
+constexpr uint64_t U0 = 0;
+constexpr uint64_t U1 = 1;
+constexpr uint64_t U7 = 7;
+constexpr uint64_t U8 = 8;
+constexpr uint64_t U16 = 16;
+constexpr uint64_t U24 = 24;
+constexpr uint64_t U32 = 32;
+constexpr uint64_t U64 = 64;
+
+const RawBufferPtr LAB = create_raw_buffer(createRandomBufferCAPI(16));
+const RawBufferPtr CTX = create_raw_buffer(createRandomBufferCAPI(12));
+const RawBufferPtr FIX = create_raw_buffer(createRandomBufferCAPI(36));
+const RawBufferPtr ONE = create_raw_buffer(createRandomBufferCAPI(1));
+
+class EcdhGroupFixture: public DPL::Test::TestGroup
+{
+private:
+ void GenerateEC(ckmc_ec_type_e curve,
+ const KeyAliasPair& pair,
+ const ckmc_policy_s& policy_prv,
+ const ckmc_policy_s& policy_pub)
+ {
+ assert_positive(ckmc_create_key_pair_ecdsa,
+ curve,
+ pair.prv.c_str(),
+ pair.pub.c_str(),
+ policy_prv,
+ policy_pub);
+ }
+
+public:
+ void Init() override
+ {
+ remove_user_data(UID);
+ assert_positive(ckmc_unlock_user_key, UID, "db-pass");
+
+ GenerateEC(CKMC_EC_PRIME256V1, OURS, UNEXPORTABLE, EXPORTABLE);
+ GenerateEC(CKMC_EC_PRIME256V1, PEERS, UNEXPORTABLE_PW, EXPORTABLE);
+ GenerateEC(CKMC_EC_PRIME256V1, PEERS2, EXPORTABLE, EXPORTABLE);
+ GenerateEC(CKMC_EC_PRIME192V1, WRONG, UNEXPORTABLE, EXPORTABLE);
+
+ assert_positive(ckmc_create_key_pair_rsa,
+ 1024,
+ RSA.prv.c_str(),
+ RSA.pub.c_str(),
+ UNEXPORTABLE,
+ EXPORTABLE);
+ }
+
+ void Finish() override
+ {
+ int ret = ckmc_lock_user_key(UID);
+ if (ret != CKMC_ERROR_NONE)
+ RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
+ remove_user_data(UID);
+ }
+};
+
+struct DerivedFixture
+{
+ void init(const std::string&)
+ {
+ }
+
+ void finish()
+ {
+ ckmc_remove_alias(DERIVED.c_str());
+ }
+};
+
+RawBufferPtr getPublicKey(const std::string& pub_alias)
+{
+ ckmc_key_s *pubKey = nullptr;
+ assert_positive(ckmc_get_key, pub_alias.c_str(), "", &pubKey);
+
+ ckmc_raw_buffer_s* pubBuffer = nullptr;
+ assert_positive(ckmc_buffer_new, pubKey->raw_key, pubKey->key_size, &pubBuffer);
+ ckmc_key_free(pubKey);
+
+ return create_raw_buffer(pubBuffer);
+}
+
+ParamListPtr getDefaultECDHParams(const std::string& pubAlias)
+{
+ auto ecdhParams = createParamListPtr();
+ setParam(ecdhParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
+ auto pubKey = getPublicKey(pubAlias);
+ setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, pubKey.get());
+ return ecdhParams;
+}
+
+void deriveEcdh(const std::string& prvAlias,
+ const std::string& prvPass,
+ const std::string& pubAlias,
+ const std::string& derivedAlias,
+ const ckmc_policy_s& derivedPolicy,
+ int expected)
+{
+ auto ecdhParams = getDefaultECDHParams(pubAlias);
+
+ assert_result(expected,
+ ckmc_key_derive,
+ ecdhParams.get(),
+ prvAlias.c_str(),
+ prvPass.c_str(),
+ derivedAlias.c_str(),
+ derivedPolicy);
+}
+
+RawBufferPtr deriveEcdhAndGet(const std::string& prvAlias,
+ const std::string& prvPass,
+ const std::string& pubAlias,
+ const std::string& derivedAlias,
+ const ckmc_policy_s& derivedPolicy)
+{
+ deriveEcdh(prvAlias, prvPass, pubAlias, derivedAlias, derivedPolicy, CKMC_ERROR_NONE);
+
+ ckmc_raw_buffer_s *derivedBuffer = nullptr;
+ assert_positive(ckmc_get_data, derivedAlias.c_str(), derivedPolicy.password, &derivedBuffer);
+
+ ckmc_remove_alias(derivedAlias.c_str());
+
+ return create_raw_buffer(derivedBuffer);
+}
+
+void invalidDerive(const ParamListPtr& params)
+{
+ assert_invalid_param(ckmc_key_derive,
+ params.get(),
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+}
+
+
+class KbkdfParamTester {
+public:
+ void Ok(const uint64_t* len,
+ const ckmc_kdf_prf_e* prf,
+ const ckmc_kbkdf_mode_e* mode,
+ const ckmc_kbkdf_counter_location_e* location,
+ const RawBufferPtr context,
+ const RawBufferPtr label,
+ const RawBufferPtr fixed,
+ const uint64_t* rlen,
+ const uint64_t* llen,
+ bool noSeparator = false)
+ {
+ return Test(true, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator);
+ }
+
+ void Fail(const uint64_t* len,
+ const ckmc_kdf_prf_e* prf,
+ const ckmc_kbkdf_mode_e* mode,
+ const ckmc_kbkdf_counter_location_e* location,
+ const RawBufferPtr context,
+ const RawBufferPtr label,
+ const RawBufferPtr fixed,
+ const uint64_t* rlen,
+ const uint64_t* llen,
+ bool noSeparator = false)
+ {
+ return Test(
+ false, len, prf, mode, location, context, label, fixed, rlen, llen, noSeparator);
+ }
+private:
+ void Test(bool ok,
+ const uint64_t* len,
+ const ckmc_kdf_prf_e* prf,
+ const ckmc_kbkdf_mode_e* mode,
+ const ckmc_kbkdf_counter_location_e* location,
+ const RawBufferPtr context,
+ const RawBufferPtr label,
+ const RawBufferPtr fixed,
+ const uint64_t* rlen,
+ const uint64_t* llen,
+ bool noSeparator = false)
+ {
+ auto derive = createParamListPtr();
+ setParam(derive, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+ if (len)
+ setParam(derive, CKMC_PARAM_KDF_LEN, *len);
+ if (prf)
+ setParam(derive, CKMC_PARAM_KDF_PRF, *prf);
+ if (mode)
+ setParam(derive, CKMC_PARAM_KBKDF_MODE, *mode);
+ if (location)
+ setParam(derive, CKMC_PARAM_KBKDF_COUNTER_LOCATION, *location);
+ if (context)
+ setParam(derive, CKMC_PARAM_KBKDF_CONTEXT, context.get());
+ if (label)
+ setParam(derive, CKMC_PARAM_KBKDF_LABEL, label.get());
+ if (fixed)
+ setParam(derive, CKMC_PARAM_KBKDF_FIXED_INPUT, fixed.get());
+ if (rlen)
+ setParam(derive, CKMC_PARAM_KBKDF_RLEN, *rlen);
+ if (llen)
+ setParam(derive, CKMC_PARAM_KBKDF_LLEN, *llen);
+ if (noSeparator)
+ setParam(derive, CKMC_PARAM_KBKDF_NO_SEPARATOR, 1);
+
+ if (ok) {
+ assert_positive(ckmc_key_derive,
+ derive.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ ckmc_key_s *derived = nullptr;
+ assert_positive(ckmc_get_key, DERIVED.c_str(), "", &derived);
+ size_t derived_size = derived->key_size;
+ ckmc_key_free(derived);
+
+ RUNNER_ASSERT(derived_size == *len);
+
+ assert_positive(ckmc_remove_alias, DERIVED.c_str());
+ } else {
+ assert_result(CKMC_ERROR_INVALID_PARAMETER,
+ ckmc_key_derive,
+ derive.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+ }
+ }
+};
+
+ParamListPtr getDefaultKBKDFParams()
+{
+ auto kbkdfParams = createParamListPtr();
+ setParam(kbkdfParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+ setParam(kbkdfParams, CKMC_PARAM_KDF_LEN, 32);
+ setParam(kbkdfParams, CKMC_PARAM_KDF_PRF, CKMC_KDF_PRF_HMAC_SHA256);
+ setParam(kbkdfParams, CKMC_PARAM_KBKDF_MODE, CKMC_KBKDF_MODE_COUNTER);
+ setParam(kbkdfParams, CKMC_PARAM_KBKDF_LABEL, LAB.get());
+ setParam(kbkdfParams, CKMC_PARAM_KBKDF_CONTEXT, CTX.get());
+ setParam(kbkdfParams, CKMC_PARAM_KBKDF_COUNTER_LOCATION, CKMC_KBKDF_COUNTER_BEFORE_FIXED);
+ return kbkdfParams;
+}
+
+} // namespace anonymous
+
+RUNNER_TEST_GROUP_INIT_ENV(CKM_DERIVE_ECDH, EcdhGroupFixture);
+
+RUNNER_TEST(TECDH_0010_positive, DerivedFixture)
+{
+ auto ourDerived = deriveEcdhAndGet(OURS.prv, "", PEERS.pub, DERIVED, EXPORTABLE);
+ auto peerDerived = deriveEcdhAndGet(PEERS.prv, PASSWORD, OURS.pub, DERIVED, EXPORTABLE_PW);
+
+ assert_buffers_equal(ourDerived.get(), peerDerived.get());
+
+ auto wrongDerived = deriveEcdhAndGet(OURS.prv, "", PEERS2.pub, DERIVED, EXPORTABLE);
+
+ assert_buffers_equal(ourDerived.get(), wrongDerived.get(), false);
+}
+
+RUNNER_TEST(TECDH_0020_missing_arguments, DerivedFixture)
+{
+ auto ecdhParams = getDefaultECDHParams(PEERS.pub);
+
+ assert_invalid_param(ckmc_key_derive,
+ nullptr,
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ assert_invalid_param(ckmc_key_derive,
+ ecdhParams.get(),
+ nullptr,
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ assert_invalid_param(ckmc_key_derive,
+ ecdhParams.get(),
+ OURS.prv.c_str(),
+ "",
+ nullptr,
+ EXPORTABLE);
+}
+
+RUNNER_TEST(TECDH_0030_unknown_alias, DerivedFixture)
+{
+ auto ecdhParams = getDefaultECDHParams(PEERS.pub);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_key_derive,
+ ecdhParams.get(),
+ "nonexistent-alias",
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+}
+
+RUNNER_TEST(TECDH_0040_alias_exists, DerivedFixture)
+{
+ auto ecdhParams = getDefaultECDHParams(PEERS.pub);
+
+ assert_positive(ckmc_key_derive,
+ ecdhParams.get(),
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmc_key_derive,
+ ecdhParams.get(),
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+}
+
+RUNNER_TEST(TECDH_0050_derived_password, DerivedFixture)
+{
+ auto ecdhParams = getDefaultECDHParams(PEERS.pub);
+
+ assert_positive(ckmc_key_derive,
+ ecdhParams.get(),
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE_PW);
+
+ ckmc_raw_buffer_s *derived = nullptr;
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), "", &derived);
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), "pw", &derived);
+
+ assert_positive(ckmc_remove_alias, DERIVED.c_str());
+
+ assert_positive(ckmc_key_derive,
+ ecdhParams.get(),
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), "pw", &derived);
+ assert_result(
+ CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), PASSWORD, &derived);
+}
+
+RUNNER_TEST(TECDH_0050_derived_unexportable, DerivedFixture)
+{
+ auto ecdhParams = getDefaultECDHParams(PEERS.pub);
+
+ assert_positive(ckmc_key_derive,
+ ecdhParams.get(),
+ OURS.prv.c_str(),
+ "",
+ DERIVED.c_str(),
+ UNEXPORTABLE);
+
+ ckmc_raw_buffer_s *derived = nullptr;
+ assert_result(CKMC_ERROR_NOT_EXPORTABLE, ckmc_get_data, DERIVED.c_str(), "", &derived);
+}
+
+RUNNER_TEST(TECDH_0100_wrong_parameters, DerivedFixture)
+{
+ auto ecdhParams = createParamListPtr();
+
+ // no algo
+ invalidDerive(ecdhParams);
+
+ // no pubkey
+ setParam(ecdhParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
+ invalidDerive(ecdhParams);
+
+ // garbage pubkey
+ ckmc_raw_buffer_s* garbage = createRandomBufferCAPI(1);
+ auto buffer = create_raw_buffer(garbage);
+ setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, buffer.get());
+ invalidDerive(ecdhParams);
+
+ // private key instead of pubkey
+ buffer = getPublicKey(PEERS2.prv);
+ setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, buffer.get());
+ invalidDerive(ecdhParams);
+
+ // wrong algo
+ buffer = getPublicKey(OURS.pub);
+ setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, buffer.get());
+ setParam(ecdhParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+ invalidDerive(ecdhParams);
+}
+
+RUNNER_TEST(TECDH_0200_wrong_password, DerivedFixture)
+{
+ deriveEcdh(PEERS.prv, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_AUTHENTICATION_FAILED);
+ deriveEcdh(OURS.prv,
+ UNEXPORTABLE_PW.password,
+ PEERS.pub,
+ DERIVED,
+ UNEXPORTABLE,
+ CKMC_ERROR_AUTHENTICATION_FAILED);
+}
+
+RUNNER_TEST(TECDH_0210_different_curves, DerivedFixture)
+{
+ deriveEcdh(OURS.prv, "", WRONG.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
+ deriveEcdh(WRONG.prv, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
+}
+
+RUNNER_TEST(TECDH_0220_different_key_types, DerivedFixture)
+{
+ deriveEcdh(OURS.prv, "", RSA.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
+ deriveEcdh(RSA.prv, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
+}
+
+RUNNER_TEST(TECDH_0230_public_instead_of_private, DerivedFixture)
+{
+ deriveEcdh(OURS.pub, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
+}
+
+RUNNER_TEST(TECDH_0230_wrong_key_types, DerivedFixture)
+{
+ deriveEcdh(RSA.prv, "", RSA.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
+}
+
+
+class KbkdfGroupFixture: public DPL::Test::TestGroup
+{
+public:
+ void Init() override
+ {
+ remove_user_data(UID);
+ assert_positive(ckmc_unlock_user_key, UID, "db-pass");
+
+ ckmc_raw_buffer_s* secret = createRandomBufferCAPI(12);
+
+ assert_positive(ckmc_save_data, SECRET.c_str(), *secret, UNEXPORTABLE);
+ }
+
+ void Finish() override
+ {
+ int ret = ckmc_lock_user_key(UID);
+ if (ret != CKMC_ERROR_NONE)
+ RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
+ remove_user_data(UID);
+ }
+};
+
+RUNNER_TEST_GROUP_INIT_ENV(CKM_DERIVE_KBKDF, KbkdfGroupFixture);
+
+RUNNER_TEST(TKBKDF_0010_positive, DerivedFixture)
+{
+ KbkdfParamTester test;
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ test.Ok(&U16, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Ok(&U24, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ test.Ok(&U32, &HMAC384, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Ok(&U32, &HMAC512, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &AFTER, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Ok(&U32, &HMAC256, &COUNTER, &MIDDLE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, ONE, LAB, nullptr, nullptr, nullptr);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, ONE, nullptr, nullptr, nullptr);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, nullptr, FIX, nullptr, nullptr);
+ test.Ok(&U32, &HMAC256, &COUNTER, &AFTER, nullptr, nullptr, FIX, nullptr, nullptr);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, nullptr, ONE, nullptr, nullptr);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U32, nullptr);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U24, nullptr);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U16, nullptr);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U8, nullptr);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U32);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U24);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U16);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U8);
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U0);
+
+ test.Ok(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr, true);
+ test.Ok(&U32, &HMAC256, &COUNTER, &MIDDLE, CTX, LAB, nullptr, nullptr, nullptr, true);
+}
+
+RUNNER_TEST(TKBKDF_0020_derive_from_derived, DerivedFixture)
+{
+ auto kbkdfParams = getDefaultKBKDFParams();
+ assert_positive(ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ UNEXPORTABLE);
+
+ assert_positive(ckmc_key_derive,
+ kbkdfParams.get(),
+ DERIVED.c_str(),
+ "",
+ "derived2",
+ EXPORTABLE);
+
+ ckmc_key_s *derived2 = nullptr;
+ assert_positive(ckmc_get_key, "derived2", "", &derived2);
+ ckmc_key_free(derived2);
+}
+
+RUNNER_TEST(TKBKDF_0030_unknown_alias, DerivedFixture)
+{
+ auto kbkdfParams = getDefaultKBKDFParams();
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_key_derive,
+ kbkdfParams.get(),
+ "nonexistent-alias",
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+}
+
+RUNNER_TEST(TKBKDF_0040_wrong_password, DerivedFixture)
+{
+ auto kbkdfParams = getDefaultKBKDFParams();
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "wrong-password",
+ DERIVED.c_str(),
+ EXPORTABLE);
+}
+
+RUNNER_TEST(TKBKDF_0050_alias_exists, DerivedFixture)
+{
+ auto kbkdfParams = getDefaultKBKDFParams();
+ assert_positive(ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+}
+
+RUNNER_TEST(TKBKDF_0060_derived_password, DerivedFixture)
+{
+ auto kbkdfParams = getDefaultKBKDFParams();
+ assert_positive(ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE);
+
+ ckmc_key_s *derived = nullptr;
+ assert_result(
+ CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_key, DERIVED.c_str(), PASSWORD, &derived);
+
+ assert_positive(ckmc_remove_alias, DERIVED.c_str());
+
+ assert_positive(ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ EXPORTABLE_PW);
+
+ assert_result(
+ CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_key, DERIVED.c_str(), "", &derived);
+ assert_positive(ckmc_get_key, DERIVED.c_str(), PASSWORD, &derived);
+ ckmc_key_free(derived);
+}
+
+RUNNER_TEST(TKBKDF_0070_unexportable, DerivedFixture)
+{
+ auto kbkdfParams = getDefaultKBKDFParams();
+ assert_positive(ckmc_key_derive,
+ kbkdfParams.get(),
+ SECRET.c_str(),
+ "",
+ DERIVED.c_str(),
+ UNEXPORTABLE);
+
+ ckmc_key_s *derived = nullptr;
+ assert_result(CKMC_ERROR_NOT_EXPORTABLE, ckmc_get_key, DERIVED.c_str(), "", &derived);
+}
+
+RUNNER_TEST(TKBKDF_0100_wrong_params, DerivedFixture)
+{
+ KbkdfParamTester test;
+
+ // missing parameters
+ test.Fail(nullptr, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, nullptr, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, nullptr, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, nullptr, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, nullptr, nullptr, nullptr, nullptr);
+
+ // conflicting parameters
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, FIX, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, nullptr, LAB, FIX, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, nullptr, FIX, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, &U32);
+ test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, &U0);
+ test.Fail(&U32, &HMAC256, &COUNTER, &MIDDLE, nullptr, nullptr, FIX, nullptr, nullptr, true);
+
+ // invalid values
+ test.Fail(&U0, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U1, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U8, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U64, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ auto wrongPrf1 = static_cast<ckmc_kdf_prf_e>(0);
+ auto wrongPrf2 = static_cast<ckmc_kdf_prf_e>(4);
+ test.Fail(&U32, &wrongPrf1, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &wrongPrf2, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ auto wrongMode1 = static_cast<ckmc_kbkdf_mode_e>(0);
+ auto wrongMode2 = static_cast<ckmc_kbkdf_mode_e>(2);
+ test.Fail(&U32, &HMAC256, &wrongMode1, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &wrongMode2, &BEFORE, CTX, LAB, nullptr, nullptr, nullptr);
+
+ auto wrongLocation1 = static_cast<ckmc_kbkdf_counter_location_e>(0);
+ auto wrongLocation2 = static_cast<ckmc_kbkdf_counter_location_e>(4);
+ test.Fail(&U32, &HMAC256, &COUNTER, &wrongLocation1, CTX, LAB, nullptr, nullptr, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &wrongLocation2, CTX, LAB, nullptr, nullptr, nullptr);
+
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U0, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U1, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U7, nullptr);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, &U64, nullptr);
+
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U1);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U7);
+ test.Fail(&U32, &HMAC256, &COUNTER, &BEFORE, CTX, LAB, nullptr, nullptr, &U64);
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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 <string>
+
+#include <dpl/test/test_runner.h>
+#include <ckm-common.h>
+#include <ckmc/ckmc-manager.h>
+#include <ckmc/ckmc-control.h>
+
+using namespace CKM;
+namespace {
+
+const uid_t UID = 5001;
+ckmc_raw_buffer_s* DEFAULT_IV = nullptr;
+
+const Alias AES_KEY_128_ALIAS = "AES-gen-test-128";
+const Alias AES_KEY_192_ALIAS = "AES-gen-test-192";
+const Alias AES_KEY_256_ALIAS = "AES-gen-test-256";
+const Alias AES_KEY_128_PASS_ALIAS = "AES-gen-test-128-pass";
+const Alias AES_KEY_UNEXP_PASS_ALIAS = "AES-gen-test-128-unexp-pass";
+const Alias AES_KEY_UNEXP_ALIAS = "AES-gen-test-128-unexp";
+const Alias RSA_KEY_1024_PRV_ALIAS = "RSA-gen-test-1024-prv";
+const Alias RSA_KEY_1024_PUB_ALIAS = "RSA-gen-test-1024-pub";
+const Alias RSA_KEY_2048_PRV_ALIAS = "RSA-gen-test-2048-prv";
+const Alias RSA_KEY_2048_PUB_ALIAS = "RSA-gen-test-2048-pub";
+const Alias RSA_KEY_4096_PRV_ALIAS = "RSA-gen-test-4096-prv";
+const Alias RSA_KEY_4096_PUB_ALIAS = "RSA-gen-test-4096-pub";
+
+const Alias IMP_AES_CTR = "imp-AES-CTR";
+const Alias IMP_AES_CTR_PASS = "imp-AES-CTR-p";
+const Alias IMPORTED_ALIAS = "imported-key-1";
+
+const char* KEY_PASSWORD = "test-pass-1";
+const ckmc_policy_s EXPORTABLE = {nullptr, 1};
+const ckmc_policy_s EXPORTABLE_PASS = {const_cast<char*>(KEY_PASSWORD), 1};
+const ckmc_policy_s UNEXPORTABLE = {nullptr, 0};
+const ckmc_policy_s UNEXPORTABLE_PASS = {const_cast<char*>(KEY_PASSWORD), 0};
+
+struct Algo {
+ ckmc_algo_type_e type;
+ size_t initVector;
+};
+const Algo AES_CTR_ALGO = {CKMC_ALGO_AES_CTR, 16};
+const Algo AES_CBC_ALGO = {CKMC_ALGO_AES_CBC, 16};
+const Algo AES_GCM_ALGO = {CKMC_ALGO_AES_GCM, 16};
+const Algo AES_CFB_ALGO = {CKMC_ALGO_AES_CFB, 16};
+const Algo RSA_OAEP_ALGO = {CKMC_ALGO_RSA_OAEP, 0};
+
+void importKey(const Algo &algo,
+ int buffLen,
+ const Alias &wrappingKeyAlias,
+ const char* wrappingKeyPass,
+ const Alias &importedKeyAlias,
+ const ckmc_policy_s &importedKeyPolicy);
+
+class GroupFixture: public DPL::Test::TestGroup{
+public:
+ void Init() override {
+ remove_user_data(UID);
+ int ret = ckmc_unlock_user_key(UID,"db-pass");
+ if (ret != CKMC_ERROR_NONE)
+ RUNNER_ERROR_MSG("DB unlock failed: " <<CKMCErrorToString(ret));
+
+ assert_positive(ckmc_create_key_pair_rsa,
+ 1024,
+ RSA_KEY_1024_PRV_ALIAS.c_str(),
+ RSA_KEY_1024_PUB_ALIAS.c_str(),
+ EXPORTABLE,
+ EXPORTABLE);
+
+ assert_positive(ckmc_create_key_pair_rsa,
+ 2048,
+ RSA_KEY_2048_PRV_ALIAS.c_str(),
+ RSA_KEY_2048_PUB_ALIAS.c_str(),
+ EXPORTABLE,
+ EXPORTABLE);
+
+ assert_positive(ckmc_create_key_pair_rsa,
+ 4096,
+ RSA_KEY_4096_PRV_ALIAS.c_str(),
+ RSA_KEY_4096_PUB_ALIAS.c_str(),
+ EXPORTABLE,
+ EXPORTABLE);
+
+ assert_positive(ckmc_create_key_aes, 128, AES_KEY_128_ALIAS.c_str(), EXPORTABLE);
+ assert_positive(ckmc_create_key_aes, 192, AES_KEY_192_ALIAS.c_str(), EXPORTABLE);
+ assert_positive(ckmc_create_key_aes, 256, AES_KEY_256_ALIAS.c_str(), EXPORTABLE);
+ assert_positive(ckmc_create_key_aes, 128, AES_KEY_128_PASS_ALIAS.c_str(), EXPORTABLE_PASS);
+ assert_positive(ckmc_create_key_aes, 128, AES_KEY_UNEXP_ALIAS.c_str(), UNEXPORTABLE);
+ assert_positive(ckmc_create_key_aes, 128, AES_KEY_UNEXP_PASS_ALIAS.c_str(), UNEXPORTABLE_PASS);
+
+ importKey(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, IMP_AES_CTR, EXPORTABLE);
+ importKey(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, IMP_AES_CTR_PASS, EXPORTABLE_PASS);
+ }
+ void Finish() override {
+ int ret = ckmc_lock_user_key(UID);
+ if (ret != CKMC_ERROR_NONE)
+ RUNNER_ERROR_MSG("DB lock failed: " <<CKMCErrorToString(ret));
+
+ remove_user_data(UID);
+ ckmc_buffer_free(DEFAULT_IV);
+
+ ckmc_remove_key(RSA_KEY_1024_PRV_ALIAS.c_str());
+ ckmc_remove_key(RSA_KEY_1024_PUB_ALIAS.c_str());
+ ckmc_remove_key(RSA_KEY_2048_PRV_ALIAS.c_str());
+ ckmc_remove_key(RSA_KEY_2048_PUB_ALIAS.c_str());
+ ckmc_remove_key(RSA_KEY_4096_PRV_ALIAS.c_str());
+ ckmc_remove_key(RSA_KEY_4096_PUB_ALIAS.c_str());
+ ckmc_remove_key(AES_KEY_128_ALIAS.c_str());
+ ckmc_remove_key(AES_KEY_192_ALIAS.c_str());
+ ckmc_remove_key(AES_KEY_256_ALIAS.c_str());
+ ckmc_remove_key(AES_KEY_128_PASS_ALIAS.c_str());
+ ckmc_remove_key(AES_KEY_UNEXP_ALIAS.c_str());
+ ckmc_remove_key(AES_KEY_UNEXP_PASS_ALIAS.c_str());
+
+ ckmc_remove_key(IMP_AES_CTR.c_str());
+ ckmc_remove_key(IMP_AES_CTR_PASS.c_str());
+ }
+};
+
+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.type == CKMC_ALGO_RSA_OAEP)
+ return params;
+
+ DEFAULT_IV = createRandomBufferCAPI(algo.initVector);
+ setParam(params, CKMC_PARAM_ED_IV, DEFAULT_IV);
+ return params;
+}
+
+RawBufferPtr encryptAndImport(const ParamListPtr ¶ms,
+ int buffLen,
+ const Alias &wrappingKeyAlias,
+ const char* wrappingKeyPass,
+ const Alias &importedKeyAlias,
+ const ckmc_policy_s &importedKeyPolicy){
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(buffLen));
+
+ ckmc_raw_buffer_s *encrypted = nullptr;
+ ckmc_key_s *aesKey = nullptr;
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_positive(ckmc_import_wrapped_key,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ importedKeyAlias.c_str(),
+ aesKey,
+ importedKeyPolicy);
+
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+ return plainData;
+}
+void testInvalidAlgoParameters(const ParamListPtr &invalidParams, const Algo &algo){
+ ParamListPtr params = getDefaultParams(algo);
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(32));
+
+ ckmc_raw_buffer_s *encrypted = nullptr;
+ ckmc_key_s *aesKey = nullptr;
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ invalidParams.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ EXPORTABLE);
+
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+}
+void testImportInvalidBuffLen(const Algo &algo,
+ int buffLen,
+ const Alias &wrappingKeyAlias){
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(buffLen));
+
+ ckmc_raw_buffer_s *encrypted = nullptr;
+ ckmc_key_s *aesKey = nullptr;
+
+ ParamListPtr params = getDefaultParams(algo);
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ nullptr,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ EXPORTABLE);
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+}
+
+void testImportValidArgs(const Algo &algo, int buffLen, const Alias &wrappingKeyAlias){
+ ckmc_key_s *ppkey = nullptr;
+ ckmc_raw_buffer_s *finalData = nullptr;
+
+ ParamListPtr params = getDefaultParams(algo);
+
+ RawBufferPtr plainData = encryptAndImport(params,
+ buffLen,
+ wrappingKeyAlias,
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ EXPORTABLE);
+
+ assert_positive(ckmc_get_key, IMPORTED_ALIAS.c_str(), nullptr, &ppkey);
+ assert_positive(ckmc_buffer_new, ppkey->raw_key, ppkey->key_size, &finalData);
+ assert_buffers_equal(plainData.get(), finalData);
+
+ ckmc_buffer_free(finalData);
+ ckmc_key_free(ppkey);
+ ckmc_remove_key(IMPORTED_ALIAS.c_str());
+}
+
+void testBadWrappedKey(const Algo &algo){
+ ParamListPtr params = getDefaultParams(algo);
+ ckmc_key_s *wrongKey = generate_AES_key(128, nullptr);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ wrongKey,
+ EXPORTABLE);
+
+ ckmc_key_free(wrongKey);
+}
+
+void testExportableImported(const Algo &algo,
+ int buffLen,
+ const Alias &wrappingKeyAlias,
+ const char* wrappingKeyPass,
+ const ckmc_policy_s &importedKeyPolicy,
+ const char* importedKeyPass){
+ ckmc_key_s *ppkey = nullptr;
+ ckmc_raw_buffer_s* finalData = nullptr;
+
+ ParamListPtr params = getDefaultParams(algo);
+
+ RawBufferPtr plainData = encryptAndImport(params,
+ buffLen,
+ wrappingKeyAlias,
+ wrappingKeyPass,
+ IMPORTED_ALIAS.c_str(),
+ importedKeyPolicy);
+
+ assert_positive(ckmc_get_key,
+ IMPORTED_ALIAS.c_str(),
+ importedKeyPass,
+ &ppkey);
+
+ assert_positive(ckmc_buffer_new,
+ ppkey->raw_key,
+ ppkey->key_size,
+ &finalData);
+
+ assert_buffers_equal(plainData.get(), finalData);
+
+ ckmc_buffer_free(finalData);
+ ckmc_key_free(ppkey);
+ ckmc_remove_key(IMPORTED_ALIAS.c_str());
+}
+
+void testUnEXPORTABLEImported(const Algo &algo,
+ int buffLen,
+ const Alias &wrappingKeyAlias,
+ const char* wrappingKeyPass,
+ const ckmc_policy_s &importedKeyPolicy,
+ const char* importedKeyPass){
+ ckmc_key_s *ppkey = nullptr;
+ ParamListPtr params = getDefaultParams(algo);
+
+ RawBufferPtr plainData = encryptAndImport(params,
+ buffLen,
+ wrappingKeyAlias,
+ wrappingKeyPass,
+ IMPORTED_ALIAS.c_str(),
+ importedKeyPolicy);
+
+ assert_result(CKMC_ERROR_NOT_EXPORTABLE,
+ ckmc_get_key,
+ IMPORTED_ALIAS.c_str(),
+ importedKeyPass,
+ &ppkey);
+ ckmc_key_free(ppkey);
+ ckmc_remove_key(IMPORTED_ALIAS.c_str());
+}
+
+void importKey(const Algo &algo,
+ int buffLen,
+ const Alias &wrappingKeyAlias,
+ const char* wrappingKeyPass,
+ const Alias &importedKeyAlias,
+ const ckmc_policy_s &importedKeyPolicy){
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(buffLen));
+
+ ckmc_key_s *aesKey = nullptr;
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ ParamListPtr params = getDefaultParams(algo);
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_positive(ckmc_import_wrapped_key,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ importedKeyAlias.c_str(),
+ aesKey,
+ importedKeyPolicy);
+
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+}
+
+void testImportExportValidArgs(const Algo &algo,
+ int buffLen,
+ const Alias &wrappingKeyAlias,
+ const char* wrappingKeyPass,
+ const ckmc_policy_s &importedKeyPolicy,
+ const char* importedKeyPass){
+ ckmc_key_s *ppkey = nullptr;
+ ckmc_raw_buffer_s* finalData = nullptr;
+ ckmc_raw_buffer_s* decrypted = nullptr;
+
+ ParamListPtr params = getDefaultParams(algo);
+
+ RawBufferPtr plainData = encryptAndImport(params,
+ buffLen,
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ IMPORTED_ALIAS,
+ importedKeyPolicy);
+
+ assert_positive(ckmc_export_wrapped_key,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ IMPORTED_ALIAS.c_str(),
+ importedKeyPass,
+ &ppkey);
+
+ assert_positive(ckmc_buffer_new,
+ ppkey->raw_key,
+ ppkey->key_size,
+ &finalData);
+
+ assert_positive(ckmc_decrypt_data,
+ params.get(),
+ wrappingKeyAlias.c_str(),
+ wrappingKeyPass,
+ *finalData,
+ &decrypted);
+
+ assert_buffers_equal(plainData.get(), decrypted);
+
+ ckmc_buffer_free(finalData);
+ ckmc_buffer_free(decrypted);
+ ckmc_key_free(ppkey);
+ ckmc_remove_key(IMPORTED_ALIAS.c_str());
+}
+
+} //END OF THE NAMESPACE
+
+RUNNER_TEST_GROUP_INIT_ENV(CKM_KEY_WRAPPING, GroupFixture);
+
+RUNNER_TEST(TKW_NO_ADDED_ALGO){
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(32));
+
+ ckmc_key_s *aesKey = nullptr;
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ ParamListPtr params = getDefaultParams(AES_CBC_ALGO);
+
+ ckmc_param_list_h handle = nullptr;
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ handle,
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ EXPORTABLE);
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+}
+
+RUNNER_TEST(TKW_WRONG_ALGO_PARAMS){
+ ckmc_param_list_h handle = nullptr;
+ assert_positive(ckmc_generate_new_params, AES_CTR_ALGO.type, &handle);
+ ParamListPtr invalidParams = ParamListPtr(handle, ckmc_param_list_free);
+ ckmc_raw_buffer_s *initVec = createRandomBufferCAPI(8);
+ setParam(invalidParams, CKMC_PARAM_ED_IV, initVec);
+
+ testInvalidAlgoParameters(invalidParams, AES_CTR_ALGO);
+
+ ckmc_buffer_free(initVec);
+ invalidParams.reset();
+ assert_positive(ckmc_generate_new_params, AES_GCM_ALGO.type, &handle);
+ invalidParams = ParamListPtr(handle, ckmc_param_list_free);
+ initVec = createRandomBufferCAPI(16);
+ setParam(invalidParams, CKMC_PARAM_ED_IV, initVec);
+ setParam(invalidParams, CKMC_PARAM_ED_TAG_LEN, 130);
+
+ testInvalidAlgoParameters(invalidParams, AES_GCM_ALGO);
+
+ ckmc_buffer_free(initVec);
+}
+
+RUNNER_TEST(TKW_WRONG_PASS_WRAPPING_KEY){
+ int buffLen = 32;
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(buffLen));
+
+ ckmc_key_s *aesKey = nullptr;
+ ckmc_raw_buffer_s* encrypted = nullptr;
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ AES_KEY_128_PASS_ALIAS.c_str(),
+ KEY_PASSWORD,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_PASS_ALIAS.c_str(),
+ "wrong_password",
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ UNEXPORTABLE);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_PASS_ALIAS.c_str(),
+ "",
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ UNEXPORTABLE);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ "non_empty_password",
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ UNEXPORTABLE);
+
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+}
+
+RUNNER_TEST(TKW_UNKNOWN_ALIAS_WRAPPING_KEY){
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+ ckmc_key_s *key = generate_AES_key(128, nullptr);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_import_wrapped_key,
+ params.get(),
+ "unknown_alias",
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ key,
+ EXPORTABLE);
+
+ ckmc_key_free(key);
+}
+
+RUNNER_TEST(TKW_EXISTING_ALIAS_WRAPPING_KEY){
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+ ckmc_key_s *key = generate_AES_key(128, nullptr);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ key,
+ EXPORTABLE);
+
+ ckmc_key_free(key);
+}
+
+RUNNER_TEST(TKW_INVALID_ALIAS_IMPORT){
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+ ckmc_key_s *key = generate_AES_key(128, nullptr);
+ Alias invalidAlias = "invalid alias";
+
+ assert_result(CKMC_ERROR_PERMISSION_DENIED,
+ ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ invalidAlias.c_str(),
+ key,
+ EXPORTABLE);
+
+ ckmc_key_free(key);
+}
+
+RUNNER_TEST(TKW_BAD_WRAPPED_KEY){
+ testBadWrappedKey(AES_CBC_ALGO);
+ testBadWrappedKey(AES_GCM_ALGO);
+ testBadWrappedKey(RSA_OAEP_ALGO);
+}
+
+RUNNER_TEST(TKW_NULL_PARAMETER){
+ RawBufferPtr plainData = create_raw_buffer(createRandomBufferCAPI(16));
+
+ ckmc_key_s *aesKey = nullptr;
+ ckmc_raw_buffer_s* encrypted = nullptr;
+
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+
+ assert_positive(ckmc_encrypt_data,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ *plainData.get(),
+ &encrypted);
+
+ assert_positive(ckmc_key_new,
+ encrypted->data,
+ encrypted->size,
+ CKMC_KEY_AES,
+ nullptr,
+ &aesKey);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ nullptr,
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ EXPORTABLE);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ params.get(),
+ nullptr,
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ aesKey,
+ EXPORTABLE);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ nullptr,
+ aesKey,
+ EXPORTABLE);
+
+ assert_invalid_param(ckmc_import_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMPORTED_ALIAS.c_str(),
+ nullptr,
+ EXPORTABLE);
+ ckmc_buffer_free(encrypted);
+ ckmc_key_free(aesKey);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CTR_128){
+ testImportValidArgs(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_CTR_ALGO, 24, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_CTR_ALGO, 32, AES_KEY_128_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CBC_128){
+ testImportValidArgs(AES_CBC_ALGO, 16, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_CBC_ALGO, 24, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_CBC_ALGO, 32, AES_KEY_128_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_GCM_128){
+ testImportValidArgs(AES_GCM_ALGO, 16, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_GCM_ALGO, 24, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_GCM_ALGO, 32, AES_KEY_128_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CFB_128){
+ testImportValidArgs(AES_CFB_ALGO, 16, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_CFB_ALGO, 24, AES_KEY_128_ALIAS);
+ testImportValidArgs(AES_CFB_ALGO, 32, AES_KEY_128_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CTR_192){
+ testImportValidArgs(AES_CTR_ALGO, 16, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_CTR_ALGO, 24, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_CTR_ALGO, 32, AES_KEY_192_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CBC_192){
+ testImportValidArgs(AES_CBC_ALGO, 16, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_CBC_ALGO, 24, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_CBC_ALGO, 32, AES_KEY_192_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_GCM_192){
+ testImportValidArgs(AES_GCM_ALGO, 16, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_GCM_ALGO, 24, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_GCM_ALGO, 32, AES_KEY_192_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CFB_192){
+ testImportValidArgs(AES_CFB_ALGO, 16, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_CFB_ALGO, 24, AES_KEY_192_ALIAS);
+ testImportValidArgs(AES_CFB_ALGO, 32, AES_KEY_192_ALIAS);
+}
+RUNNER_TEST(TKW_VALID_ARGS_AES_CTR_256){
+ testImportValidArgs(AES_CTR_ALGO, 16, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_CTR_ALGO, 24, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_CTR_ALGO, 32, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CBC_256){
+ testImportValidArgs(AES_CBC_ALGO, 16, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_CBC_ALGO, 24, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_CBC_ALGO, 32, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_GCM_256){
+ testImportValidArgs(AES_GCM_ALGO, 16, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_GCM_ALGO, 24, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_GCM_ALGO, 32, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_AES_CFB_256){
+ testImportValidArgs(AES_CFB_ALGO, 16, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_CFB_ALGO, 24, AES_KEY_256_ALIAS);
+ testImportValidArgs(AES_CFB_ALGO, 32, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_AES_CTR_INVALID_BUFF_LENGTH){
+ testImportInvalidBuffLen(AES_CTR_ALGO, 8, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 12, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 128, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 8, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 12, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 128, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 8, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 12, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_CTR_ALGO, 128, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_AES_CBC_INVALID_BUFF_LENGTH){
+ testImportInvalidBuffLen(AES_CBC_ALGO, 8, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 12, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 128, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 8, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 12, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 128, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 8, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 12, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_CBC_ALGO, 128, AES_KEY_256_ALIAS);
+}
+RUNNER_TEST(TKW_AES_GCM_INVALID_BUFF_LENGTH){
+ testImportInvalidBuffLen(AES_GCM_ALGO, 8, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 12, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 128, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 8, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 12, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 128, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 8, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 12, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_GCM_ALGO, 128, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_AES_CFB_INVALID_BUFF_LENGTH){
+ testImportInvalidBuffLen(AES_CFB_ALGO, 8, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 12, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 128, AES_KEY_128_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 8, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 12, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 128, AES_KEY_192_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 8, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 12, AES_KEY_256_ALIAS);
+ testImportInvalidBuffLen(AES_CFB_ALGO, 128, AES_KEY_256_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_RSA_OAEP_1024){
+ testImportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_1024_PRV_ALIAS);
+ testImportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_1024_PRV_ALIAS);
+ testImportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_1024_PRV_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_RSA_OAEP_2048){
+ testImportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_2048_PRV_ALIAS);
+ testImportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_2048_PRV_ALIAS);
+ testImportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_2048_PRV_ALIAS);
+}
+
+RUNNER_TEST(TKW_VALID_ARGS_RSA_OAEP_4096){
+ testImportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_4096_PRV_ALIAS);
+ testImportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_4096_PRV_ALIAS);
+ testImportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_4096_PRV_ALIAS);
+}
+
+RUNNER_TEST(TKW_RSAOAEP_INVALID_BUFF_LENGTH){
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 8, RSA_KEY_1024_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 12, RSA_KEY_1024_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 82, RSA_KEY_1024_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 8, RSA_KEY_2048_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 12, RSA_KEY_2048_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 82, RSA_KEY_2048_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 8, RSA_KEY_4096_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 12, RSA_KEY_4096_PRV_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 82, RSA_KEY_4096_PRV_ALIAS);
+}
+
+RUNNER_TEST(TKW_WRONG_TYPE_WRAPPING_KEY){
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 16, RSA_KEY_1024_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 24, RSA_KEY_1024_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 32, RSA_KEY_1024_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 16, RSA_KEY_2048_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 24, RSA_KEY_2048_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 32, RSA_KEY_2048_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 16, RSA_KEY_4096_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 24, RSA_KEY_4096_PUB_ALIAS);
+ testImportInvalidBuffLen(RSA_OAEP_ALGO, 32, RSA_KEY_4096_PUB_ALIAS);
+}
+
+RUNNER_TEST(TKW_DIF_POLICIES_EXPORTABLE_IMPORTED){
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testExportableImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_DIF_POLICIES_UNEXPORTABLE_IMPORTED){
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, UNEXPORTABLE, nullptr);
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, UNEXPORTABLE, nullptr);
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_ALIAS, nullptr, UNEXPORTABLE, nullptr);
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_PASS_ALIAS, KEY_PASSWORD, UNEXPORTABLE, nullptr);
+
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, UNEXPORTABLE_PASS, KEY_PASSWORD);
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, UNEXPORTABLE_PASS, KEY_PASSWORD);
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_ALIAS, nullptr, UNEXPORTABLE_PASS, KEY_PASSWORD);
+ testUnEXPORTABLEImported(AES_CTR_ALGO, 16, AES_KEY_UNEXP_PASS_ALIAS, KEY_PASSWORD, UNEXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_EXPORT_IMPORTED_KEY){
+ ckmc_key_s *ppkey = nullptr;
+
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+ assert_positive(ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ ckmc_key_free(ppkey);
+}
+
+RUNNER_TEST(TKW_NO_ADDED_ALGO_EXPORT){
+ ckmc_key_s *ppkey = nullptr;
+ ckmc_param_list_h handle = nullptr;
+
+ assert_invalid_param(ckmc_export_wrapped_key,
+ handle,
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ ckmc_key_free(ppkey);
+}
+
+RUNNER_TEST(TKW_EXPORT_UNKNOWN_WRAPPING_KEY_ALIAS){
+ ckmc_key_s *ppkey = nullptr;
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_export_wrapped_key,
+ params.get(),
+ "unknown_alias",
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ ckmc_key_free(ppkey);
+}
+
+RUNNER_TEST(TKW_EXPORT_UNKNOWN_IMPORTED_KEY_ALIAS){
+ ckmc_key_s *ppkey = nullptr;
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+ Alias alias = "non_existing_alias";
+
+ assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ alias.c_str(),
+ nullptr,
+ &ppkey);
+
+ ckmc_key_free(ppkey);
+}
+
+RUNNER_TEST(TKW_EXPORT_AUTHENTICATION_FAILED){
+ ckmc_key_s *ppkey = nullptr;
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_PASS_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_PASS_ALIAS.c_str(),
+ "wrong_password",
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR_PASS.c_str(),
+ nullptr,
+ &ppkey);
+
+ assert_result(CKMC_ERROR_AUTHENTICATION_FAILED,
+ ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR_PASS.c_str(),
+ "wrong_password",
+ &ppkey);
+
+ ckmc_key_free(ppkey);
+}
+
+RUNNER_TEST(TKW_EXPORT_NULL_PARAMETER){
+ ckmc_key_s *ppkey = nullptr;
+ ParamListPtr params = getDefaultParams(AES_CTR_ALGO);
+
+ assert_invalid_param(ckmc_export_wrapped_key,
+ nullptr,
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ assert_invalid_param(ckmc_export_wrapped_key,
+ params.get(),
+ nullptr,
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ &ppkey);
+
+ assert_invalid_param(ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ nullptr,
+ nullptr,
+ &ppkey);
+
+ assert_invalid_param(ckmc_export_wrapped_key,
+ params.get(),
+ AES_KEY_128_ALIAS.c_str(),
+ nullptr,
+ IMP_AES_CTR.c_str(),
+ nullptr,
+ nullptr);
+
+ ckmc_key_free(ppkey);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_CTR){
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_CTR_PASS){
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_CTR_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CTR_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_CBC){
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_CBC_PASS){
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_CBC_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CBC_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_GCM){
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_GCM_PASS){
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_GCM_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_GCM_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_CFB){
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_128_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_192_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_256_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_AES_CFB_PASS){
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(AES_CFB_ALGO, 16, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 24, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(AES_CFB_ALGO, 32, AES_KEY_128_PASS_ALIAS, KEY_PASSWORD, EXPORTABLE_PASS, KEY_PASSWORD);
+}
+
+RUNNER_TEST(TKW_IMPORT_EXPORT_RSA_OAEP){
+ testImportExportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_1024_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_1024_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_1024_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_2048_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_2048_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_2048_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_4096_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_4096_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_4096_PRV_ALIAS, nullptr, EXPORTABLE, nullptr);
+
+ testImportExportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_1024_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_1024_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_1024_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_2048_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_2048_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_2048_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 16, RSA_KEY_4096_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 24, RSA_KEY_4096_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+ testImportExportValidArgs(RSA_OAEP_ALGO, 32, RSA_KEY_4096_PRV_ALIAS, nullptr, EXPORTABLE_PASS, KEY_PASSWORD);
+}
* See the License for the specific language governing permissions and
* limitations under the License
*/
-#include <unistd.h>
-#include <sys/types.h>
#include <fstream>
#include <iostream>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
-#include <tzplatform_config.h>
-
namespace {
const int USER_APP = 5001;
CKM_API_ERROR_NOT_EXPORTABLE == (temp = manager->getKey("appkey4", CKM::Password(), key)),
"Error=" << CKM::APICodeToString(temp));
RUNNER_ASSERT_MSG(
- CKM_API_ERROR_INPUT_PARAM == (temp = manager->saveData("data3", buffer, notExportable)),
+ CKM_API_SUCCESS == (temp = manager->saveData("data3", buffer, notExportable)),
"Error=" << CKM::APICodeToString(temp));
}
int main(int argc, char *argv[])
{
- uid_t expected_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
- if (expected_uid != geteuid()) {
- std::string userStr("owner");
- const char* user = tzplatform_getenv(TZ_SYS_DEFAULT_USER);
- if (user)
- userStr = user;
-
- std::cerr << argv[0] << " should be executed as " << userStr << ". Aborting" << std::endl;
- return -1;
- }
+ require_default_user(argv);
int exitCode = DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
--- /dev/null
+# Copyright (c) 2023 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(FindPkgConfig)
+
+
+# Adaptation layer
+SET(TARGET_E2EE_ADAPTATION_LAYER "e2ee-adaptation-layer")
+
+PKG_CHECK_MODULES(E2EE_ADAPTATION_LAYER_DEP
+ REQUIRED
+ key-manager>=0.1.49
+ device-certificate-manager>=2.1
+ openssl1.1
+)
+
+SET(E2EE_ADAPTATION_LAYER_SOURCES
+ e2ee-adaptation-layer.cpp
+)
+
+ADD_LIBRARY(${TARGET_E2EE_ADAPTATION_LAYER}
+ STATIC ${E2EE_ADAPTATION_LAYER_SOURCES}
+)
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_E2EE_ADAPTATION_LAYER}
+ SYSTEM PUBLIC ${E2EE_ADAPTATION_LAYER_DEP_INCLUDE_DIRS}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_E2EE_ADAPTATION_LAYER}
+ ${E2EE_ADAPTATION_LAYER_DEP_LIBRARIES}
+)
+
+
+# Tests
+SET(E2EE_TESTS_SOURCES
+ tests.cpp
+)
+
+ADD_EXECUTABLE(${TARGET_E2EE_TESTS} ${E2EE_TESTS_SOURCES})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_E2EE_TESTS}
+ PRIVATE ${PROJECT_SOURCE_DIR}/src/common
+ PRIVATE ${PROJECT_SOURCE_DIR}/src/ckm
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_E2EE_TESTS}
+ ${TARGET_E2EE_ADAPTATION_LAYER}
+ ${TARGET_CKM_TEST_COMMON}
+)
+
+INSTALL(TARGETS ${TARGET_E2EE_TESTS}
+ DESTINATION /usr/bin
+)
--- /dev/null
+/*
+ * Copyright (c) 2023 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 "e2ee-adaptation-layer.h"
+
+#include <cstring>
+#include <cstdlib>
+
+#include <memory>
+
+#include <openssl/evp.h>
+
+#include <ckmc/ckmc-manager.h>
+#include <device_certificate_manager.h>
+
+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<struct __ckmc_param_list, decltype(&ckmc_param_list_free)> ParamsPtr;
+typedef std::unique_ptr<void, decltype(&dcm_free_key_context)> DcmCtxPtr;
+typedef std::unique_ptr<ckmc_raw_buffer_s, decltype(&ckmc_buffer_free)> BufferPtr;
+typedef std::unique_ptr<ckmc_key_s, decltype(&ckmc_key_free)> KeyPtr;
+typedef std::unique_ptr<dcm_e2ee_bundle_s, decltype(&dcm_e2ee_free_bundle)> BundlePtr;
+
+std::tuple<ParamsPtr, int> makeParams()
+{
+ ckmc_param_list_h params = nullptr;
+ int ret = ckmc_param_list_new(¶ms);
+ return std::make_tuple(ParamsPtr(params, ckmc_param_list_free), ret);
+}
+
+std::tuple<BufferPtr, int> makeBuffer(const unsigned char* data, size_t size)
+{
+ ckmc_raw_buffer_s* buffer = nullptr;
+ int ret = ckmc_buffer_new(const_cast<unsigned char*>(data), size, &buffer);
+ return std::make_tuple(BufferPtr(buffer, ckmc_buffer_free), ret);
+}
+
+class AliasRemover
+{
+public:
+ AliasRemover(const char *alias) : alias(alias) {}
+ ~AliasRemover() {
+ ckmc_remove_alias(alias);
+ }
+
+private:
+ const char* alias;
+};
+
+std::tuple<DcmCtxPtr, int> getOcfContext()
+{
+ void* ocf_ctx = nullptr;
+ int ret = dcm_create_key_context(nullptr, nullptr, "ECDSA", &ocf_ctx);
+ return std::make_tuple(DcmCtxPtr(ocf_ctx, dcm_free_key_context), ret);
+}
+
+} // anonymous namespace
+
+int ckmew_key_agreement(const char *private_key_alias,
+ const unsigned char *raw_public_key,
+ size_t raw_public_key_len,
+ const char *new_key_alias)
+{
+ if (private_key_alias == nullptr || raw_public_key == nullptr || raw_public_key_len == 0 ||
+ new_key_alias == nullptr)
+ return CKMC_ERROR_INVALID_PARAMETER;
+
+ ckmc_policy_s unexportable { nullptr, false };
+
+ auto [ecdh_params, ret] = makeParams();
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ ret = ckmc_param_list_set_integer(ecdh_params.get(), CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ auto [peers_public, ret2] = makeBuffer(raw_public_key, raw_public_key_len);
+ if (ret2 != CKMC_ERROR_NONE)
+ return ret2;
+
+ ret = ckmc_param_list_set_buffer(ecdh_params.get(), CKMC_PARAM_ECDH_PUBKEY, peers_public.get());
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ // derive shared secret
+ ret = ckmc_key_derive(ecdh_params.get(),
+ private_key_alias,
+ nullptr,
+ SECRET_ALIAS,
+ unexportable);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ // delete secret
+ AliasRemover remover(SECRET_ALIAS);
+
+ // set KBKDF params
+ auto [kbkdf_params, ret3] = makeParams();
+ if (ret3 != CKMC_ERROR_NONE)
+ return ret3;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params.get(), CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params.get(),
+ CKMC_PARAM_KDF_PRF,
+ CKMC_KDF_PRF_HMAC_SHA256);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params.get(),
+ CKMC_PARAM_KBKDF_MODE,
+ CKMC_KBKDF_MODE_COUNTER);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params.get(),
+ CKMC_PARAM_KBKDF_COUNTER_LOCATION,
+ CKMC_KBKDF_COUNTER_BEFORE_FIXED);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ auto [label_buf, ret4] = makeBuffer(reinterpret_cast<const unsigned char*>(LABEL),
+ strlen(LABEL));
+ if (ret4 != CKMC_ERROR_NONE)
+ return ret4;
+
+ ret = ckmc_param_list_set_buffer(kbkdf_params.get(), CKMC_PARAM_KBKDF_LABEL, label_buf.get());
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ auto [context_buf, ret5] = makeBuffer(reinterpret_cast<const unsigned char*>(CONTEXT),
+ strlen(CONTEXT));
+ if (ret5 != CKMC_ERROR_NONE)
+ return ret5;
+
+ ret = ckmc_param_list_set_buffer(kbkdf_params.get(),
+ CKMC_PARAM_KBKDF_CONTEXT,
+ context_buf.get());
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params.get(), CKMC_PARAM_KDF_LEN, 32);
+ if (ret != CKMC_ERROR_NONE)
+ return ret;
+
+ // derive symmetric key
+ 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)
+{
+ 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)
+{
+ auto [ocf, ret] = getOcfContext();
+ if (ret != DCM_ERROR_NONE)
+ return ret;
+
+ return dcm_get_certificate_chain(ocf.get(), cert_chain, cert_chain_len);
+}
+
+int ckmew_sign_with_ocf(const char *public_key_alias,
+ ckmc_raw_buffer_s **message_buf,
+ ckmc_raw_buffer_s **signature_buf)
+{
+ if (public_key_alias == nullptr || message_buf == nullptr || signature_buf == nullptr)
+ return DCM_ERROR_INVALID_PARAMETER;
+
+ // get ocf context
+ auto [ocf, ret] = getOcfContext();
+ if (ret != DCM_ERROR_NONE)
+ return ret;
+
+ // get device public key
+ ckmc_key_s* device_pub_key = nullptr;
+ ret = ckmc_get_key(public_key_alias, nullptr, &device_pub_key);
+ if (ret != CKMC_ERROR_NONE)
+ return ret; // This is a CKM error!
+
+ KeyPtr device_pub_key_ptr(device_pub_key, ckmc_key_free);
+
+ // pack & sign device public key
+ dcm_e2ee_bundle_h bundle = nullptr;
+ unsigned char* signature = nullptr;
+ size_t signature_len = 0;
+ ret = dcm_e2ee_create_signed_bundle(ocf.get(),
+ DCM_DIGEST_SHA256,
+ device_pub_key->raw_key,
+ device_pub_key->key_size,
+ &bundle,
+ reinterpret_cast<char**>(&signature),
+ &signature_len);
+ if (ret != DCM_ERROR_NONE)
+ return ret;
+
+ BundlePtr bundle_ptr(bundle, dcm_e2ee_free_bundle);
+ auto [signature_ptr, ret2] = makeBuffer(signature, signature_len);
+ if (ret2 != CKMC_ERROR_NONE)
+ return ret2; // This is a CKM error!
+
+ const unsigned char* message = nullptr;
+ size_t message_len = 0;
+ ret = dcm_e2ee_get_bundle_message(bundle, &message, &message_len);
+ if (ret != DCM_ERROR_NONE)
+ return ret;
+
+ ret = ckmc_buffer_new(const_cast<unsigned char*>(message), message_len, message_buf);
+ if (ret != CKMC_ERROR_NONE)
+ return ret; // This is a CKM error!
+
+ *signature_buf = signature_ptr.release();
+
+ return DCM_ERROR_NONE;
+}
--- /dev/null
+/*
+ * Copyright (c) 2023 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
+ */
+
+#pragma once
+
+#include <stddef.h>
+#include <ckmc/ckmc-type.h>
+
+/**
+ * @brief Derives a common symmetric key using ECDH and KBKDF.
+ *
+ * @since_tizen 7.5
+ *
+ * @remarks The derived key will be a symmetric one. It will be stored as a #CKMC_KEY_AES.
+ * @remarks The function first generates a shared secret using ECDH and temporarily stores it in
+ * key-manager. Then it derives a symmetric key from it, stores it in key-manager too and
+ * removes the shared secret.
+ * @remarks Shared secret length and KBKDF algorithm parameters are fixed in the code.
+ * @remarks To simplify the API, it is assumed that the private key alias does not use a custom
+ * password.
+ *
+ * @param[in] private_key_alias Alias of the private key to be used in ECDH
+ * @param[in] raw_public_key Peer's public key in DER format to be used in ECDH
+ * @param[in] raw_public_key_len Length of the @a raw_public_key
+ * @param[in] new_key_alias The name under which the new key will be known in key-manager
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ *
+ * @retval #CKMC_ERROR_NONE Successful
+ * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid (@a private_key_alias = NULL,
+ * @a raw_public_key = NULL, @a new_key_alias = NULL)
+ * @retval #CKMC_ERROR_DB_LOCKED A user is not logged in to key-manager
+ * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN @a private_key_alias does not exist
+ * @retval #CKMC_ERROR_DB_ALIAS_EXISTS @a new_key_alias already exists
+ * @retval #CKMC_ERROR_INVALID_FORMAT The format of @a raw_public_key is not valid
+ * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error
+ * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager
+ * @retval #CKMC_ERROR_AUTHENTICATION_FAILED Secret decryption failed because @a private_key_alias
+ * needed a password and none was given
+ * @retval #CKMC_ERROR_SERVER_ERROR Unknown error
+ *
+ * @pre User is already logged in to key-manager.
+ *
+ * @see ckmc_key_derive()
+ */
+int ckmew_key_agreement(const char *private_key_alias,
+ const unsigned char *raw_public_key,
+ size_t raw_public_key_len,
+ const char *new_key_alias);
+
+/**
+ * @brief Derives a symmetric key from a password using PBKFD2 and stores it in key-manager
+ *
+ * @since_tizen 7.5
+ *
+ * @remarks The password is temporarily stored in key-manager. It is deleted after key derivation
+ * is performed.
+ * @remarks The key-manager's policy for storing the derived key is fixed in the code.
+ * @remarks The number of PBKDF2 iteration is fixed in the code.
+ *
+ * @param[in] password The password to derive the key from
+ * @param[in] salt The salt used for PBKDF2
+ * @param[in] salt_len Length of the @a salt
+ * @param[in] new_key_len The desired length of the derived key
+ * @param[in] new_key_alias The name under which the new key will be known in key-manager
+ *
+ * @return @c 0 on success, otherwise a negative error value
+ *
+ * @retval #CKMC_ERROR_NONE Successful
+ * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid (@a password = NULL or
+ * @a salt = NULL)
+ * @retval #CKMC_ERROR_NOT_SUPPORTED Unsupported key length
+ * @retval #CKMC_ERROR_DB_LOCKED A user is not logged in to key-manager
+ * @retval #CKMC_ERROR_DB_ALIAS_EXISTS @a new_key_alias already exists
+ * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error
+ * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager
+ * @retval #CKMC_ERROR_SERVER_ERROR Unknown error
+ *
+ * @pre User is already logged in to key-manager.
+ *
+ * @see ckmc_key_derive()
+ */
+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);
+
+/**
+ * @platform
+ *
+ * @since_tizen 7.5
+ *
+ * @brief Constructs OCF certificate chain and returns it
+ *
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @remarks The @a cert_chain should be freed using free().
+ *
+ * @param[out] cert_chain Certificate chain in binary, will be allocated by the library
+ * @param[out] cert_chain_len The total length of certificate chain
+ *
+ * @return #DCM_ERROR_NONE on success, otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_NO_DATA No certificate chain available
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ */
+int ckmew_get_ocf_cert_chain(char **cert_chain, size_t *cert_chain_len);
+
+/**
+ * @platform
+ *
+ * @since_tizen 7.5
+ *
+ * @brief Signs given public key with OCF using E2EE signing scheme.
+ *
+ * @privlevel platform
+ * @privilege %http://tizen.org/privilege/devicecertificate
+ *
+ * @remarks The public key will be retrieved from key-manager.
+ * @remarks It is assumed that the public key is not encrypted with a custom password in
+ * key-manager and thus there's no need to pass additional argument.
+ *
+ * @param[in] public_key_alias Alias of the public key to be signed
+ * @param[out] message The E2EE message composed from public key and E2EE prefixes. It has to be
+ * freed using ckmc_buffer_free()
+ * @param[out] signature The OCF signature calculated for @a message. It has to be
+ * freed using ckmc_buffer_free()
+ *
+ * @return #DCM_ERROR_NONE on success, otherwise a negative error value
+ *
+ * @retval #DCM_ERROR_NONE Successful
+ * @retval #DCM_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #DCM_ERROR_OUT_OF_MEMORY Out of memory during processing
+ * @retval #DCM_ERROR_PERMISSION_DENIED Failed to access device certificate manager
+ * @retval #DCM_ERROR_NOT_SUPPORTED Feature needed to run API is not supported
+ * @retval #DCM_ERROR_SOCKET Socket error between client and server
+ * @retval #DCM_ERROR_NO_DATA If OCF or public key are not available
+ * @retval #DCM_ERROR_UNKNOWN Unknown error
+ * @retval #CKMC_ERROR_INVALID_PARAMETER Input parameter is invalid
+ * @retval #CKMC_ERROR_OUT_OF_MEMORY Not enough memory
+ * @retval #CKMC_ERROR_DB_LOCKED A user key is not loaded in memory (a user is not logged in)
+ * @retval #CKMC_ERROR_DB_ERROR Failed due to a database error
+ * @retval #CKMC_ERROR_DB_ALIAS_UNKNOWN Alias does not exist
+ * @retval #CKMC_ERROR_PERMISSION_DENIED Failed to access key manager
+ * @retval #CKMC_ERROR_AUTHENTICATION_FAILED Decryption failed because password is incorrect
+ */
+int ckmew_sign_with_ocf(const char *public_key_alias,
+ ckmc_raw_buffer_s **message,
+ ckmc_raw_buffer_s **signature);
--- /dev/null
+/*
+ * Copyright (c) 2023 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 "e2ee-adaptation-layer.h"
+
+#include <sstream>
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/crypto.h>
+
+#include <dpl/test/test_runner.h>
+#include <ckm-common.h>
+#include <ckmc/ckmc-manager.h>
+#include <ckmc/ckmc-control.h>
+#include <device_certificate_manager.h>
+
+namespace {
+
+const uid_t UID = 5001;
+
+struct KeyAliasPair
+{
+ std::string prv;
+ std::string pub;
+};
+
+const KeyAliasPair OURS = { "our_ec_private", "our_ec_public" };
+const KeyAliasPair PEERS = { "peer_ec_private", "peer_ec_public" };
+const KeyAliasPair PEERS2 = { "peer2_ec_private", "peer2_ec_public" };
+const KeyAliasPair WRONG = { "wrong_ec_private", "wrong_ec_public" };
+const KeyAliasPair RSA_KEYS = { "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 };
+
+#define ERRORDESCRIBE(name) case name: return #name
+const char * E2EEErrorToString(int error) {
+ switch(error) {
+ ERRORDESCRIBE(DCM_ERROR_INVALID_PARAMETER);
+ ERRORDESCRIBE(DCM_ERROR_OUT_OF_MEMORY);
+ ERRORDESCRIBE(DCM_ERROR_PERMISSION_DENIED);
+ ERRORDESCRIBE(DCM_ERROR_NOT_SUPPORTED);
+ ERRORDESCRIBE(DCM_ERROR_NO_DATA);
+ ERRORDESCRIBE(DCM_ERROR_UNKNOWN);
+ ERRORDESCRIBE(DCM_ERROR_SOCKET);
+ default: return CKMCErrorToString(error);
+ }
+}
+#undef ERRORDESCRIBE
+
+// RUNNER_ASSERT wrappers
+template <typename F, typename... Args>
+void e2ee_result(int expected, F&& func, Args... args)
+{
+ int ret = func(args...);
+ RUNNER_ASSERT_MSG(ret == expected,
+ "Expected: " << E2EEErrorToString(expected) << "(" << expected << ")"
+ " got: " << E2EEErrorToString(ret) << "(" << ret << ")");
+}
+
+template <typename F, typename... Args>
+void e2ee_positive(F&& func, Args... args)
+{
+ e2ee_result(DCM_ERROR_NONE, std::move(func), args...);
+}
+
+template <typename F, typename... Args>
+void e2ee_invalid_param(F&& func, Args... args)
+{
+ e2ee_result(DCM_ERROR_INVALID_PARAMETER, std::move(func), args...);
+}
+
+class EALGroupFixture: public DPL::Test::TestGroup
+{
+private:
+ void GenerateEC(ckmc_ec_type_e curve,
+ const KeyAliasPair& pair,
+ const ckmc_policy_s& policy_prv,
+ const ckmc_policy_s& policy_pub)
+ {
+ ckmc_remove_alias(pair.prv.c_str());
+ ckmc_remove_alias(pair.pub.c_str());
+ e2ee_positive(ckmc_create_key_pair_ecdsa,
+ curve,
+ pair.prv.c_str(),
+ pair.pub.c_str(),
+ policy_prv,
+ policy_pub);
+ }
+
+public:
+ void Init() override
+ {
+ remove_user_data(UID);
+ e2ee_positive(ckmc_unlock_user_key, UID, "db-pass");
+
+ GenerateEC(CKMC_EC_PRIME256V1, OURS, UNEXPORTABLE, EXPORTABLE);
+ GenerateEC(CKMC_EC_PRIME256V1, PEERS, UNEXPORTABLE, EXPORTABLE);
+ GenerateEC(CKMC_EC_PRIME256V1, PEERS2, EXPORTABLE, EXPORTABLE);
+ GenerateEC(CKMC_EC_PRIME192V1, WRONG, UNEXPORTABLE, EXPORTABLE);
+
+ ckmc_remove_alias(RSA_KEYS.prv.c_str());
+ ckmc_remove_alias(RSA_KEYS.pub.c_str());
+ e2ee_positive(ckmc_create_key_pair_rsa,
+ 1024,
+ RSA_KEYS.prv.c_str(),
+ RSA_KEYS.pub.c_str(),
+ UNEXPORTABLE,
+ EXPORTABLE);
+ }
+
+ void Finish() override
+ {
+ int ret = ckmc_lock_user_key(UID);
+ if (ret != CKMC_ERROR_NONE)
+ RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
+ remove_user_data(UID);
+ }
+};
+typedef std::unique_ptr<ckmc_key_s, decltype(&ckmc_key_free)> KeyPtr;
+
+KeyPtr getKey(const std::string& alias)
+{
+ ckmc_key_s* key = nullptr;
+ e2ee_positive(ckmc_get_key, alias.c_str(), "", &key);
+
+ return KeyPtr(key, ckmc_key_free);
+}
+
+AliasRemover keyAgreement(const std::string &prv, const std::string& pub, const char* derived)
+{
+ auto pub_key = getKey(pub);
+ e2ee_positive(ckmew_key_agreement, prv.c_str(), pub_key->raw_key, pub_key->key_size, derived);
+
+ return AliasRemover(derived);
+}
+
+template <typename T, void (*Fn)(T*)>
+struct Free {
+ explicit Free(T* ptr) : ptr(ptr) {}
+ ~Free() {
+ Fn(ptr);
+ }
+ Free(const Free&) = delete;
+ Free& operator=(const Free&) = delete;
+ T* operator*() { return ptr; }
+private:
+ T* ptr;
+};
+
+void OPENSSL_free_wrapper(unsigned char* ptr)
+{
+ OPENSSL_free(static_cast<void*>(ptr));
+}
+
+typedef Free<dcm_e2ee_bundle_s, dcm_e2ee_free_bundle> FreeBundle;
+typedef Free<void, free> FreeVoid;
+typedef Free<BIO, BIO_free_all> FreeBio;
+typedef Free<unsigned char, OPENSSL_free_wrapper> FreeOpenssl;
+typedef Free<X509, X509_free> FreeX509;
+typedef Free<EVP_MD_CTX, EVP_MD_CTX_free> FreeMdCtx;
+typedef Free<X509_STORE_CTX, X509_STORE_CTX_free> FreeX509StoreCtx;
+
+typedef STACK_OF(X509) X509_STACK;
+typedef std::unique_ptr<X509_STACK, decltype(&sk_X509_free)> X509StackPtr;
+
+X509StackPtr getOcfChain()
+{
+ // extract OCFs root certificate
+ char* ocfChain = nullptr;
+ size_t ocfChainLen = 0;
+
+ // OCF cert + common OCFs root cert
+ e2ee_positive(ckmew_get_ocf_cert_chain, &ocfChain, &ocfChainLen);
+
+ RUNNER_ASSERT_MSG(ocfChain != nullptr, "OCF cert chain is empty");
+
+ FreeVoid ocfChainFree(static_cast<void*>(ocfChain));
+
+ RUNNER_ASSERT_MSG(ocfChainLen > 0, "OCF cert chain has 0 length");
+
+ auto bio = (BIO_new(BIO_s_mem()));
+ RUNNER_ASSERT_MSG(bio != nullptr, "BIO_new failed");
+ FreeBio bioFree(bio);
+
+ auto written = BIO_write(bio, ocfChain, ocfChainLen);
+ RUNNER_ASSERT_MSG(written >= 0, "BIO_write failed");
+ RUNNER_ASSERT_MSG(static_cast<size_t>(written) == ocfChainLen, "OCF chain write is incomplete");
+
+ // build a X509 chain
+ X509StackPtr chainPtr(sk_X509_new_null(), sk_X509_free);
+ RUNNER_ASSERT_MSG(chainPtr, "sk_X509_new_null failed");
+
+ X509* cert = nullptr;
+ while((cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr)) != nullptr)
+ RUNNER_ASSERT_MSG(sk_X509_push(chainPtr.get(), cert) > 0, "Nothing was pushed to stack");
+
+ RUNNER_ASSERT_MSG(sk_X509_num(chainPtr.get()) >= 1, "No certificates in the chain");
+
+ // TODO this requires 2-element OCF cert chain
+ if (sk_X509_num(chainPtr.get()) < 2)
+ RUNNER_ERROR_MSG("Insufficient number of certificates in the chain");
+
+ return chainPtr;
+}
+
+struct ustreambuf: public std::basic_streambuf<unsigned char> {
+ ustreambuf(unsigned char* buf, size_t size) : std::basic_streambuf<unsigned char>()
+ {
+ pubsetbuf(buf, size);
+ }
+};
+
+class Peer
+{
+public:
+ Peer(const KeyAliasPair& keys, const char* derived) : ours(keys), derived(derived) {}
+ ~Peer() {
+ ckmc_remove_alias(derived);
+ }
+
+ std::string send()
+ {
+ ckmc_raw_buffer_s* message = nullptr;
+ ckmc_raw_buffer_s* signature = nullptr;
+ e2ee_positive(ckmew_sign_with_ocf, ours.pub.c_str(), &message, &signature);
+
+ auto messagePtr = create_raw_buffer(message);
+ auto signaturePtr = create_raw_buffer(signature);
+
+ RUNNER_ASSERT_MSG(messagePtr->size > 0, "Message buffer has 0 length");
+ RUNNER_ASSERT_MSG(messagePtr->data != nullptr, "Message buffer has no data");
+
+ RUNNER_ASSERT_MSG(signaturePtr->size > 0, "Signature buffer has 0 length");
+ RUNNER_ASSERT_MSG(signaturePtr->data != nullptr, "Signature buffer has no data");
+
+ // extract OCF key certificate
+ auto chainPtr = getOcfChain();
+ auto ocfCertX509 = sk_X509_value(chainPtr.get(), 0);
+
+ RUNNER_ASSERT_MSG(ocfCertX509 != nullptr, "OCF certificate extraction failed");
+
+ // convert it to DER
+ unsigned char *ocfCert = nullptr;
+ size_t ocfCertLen = i2d_X509(ocfCertX509, &ocfCert);
+
+ RUNNER_ASSERT_MSG(ocfCertLen > 0, "OCF certificate has 0 length");
+ RUNNER_ASSERT_MSG(ocfCert != nullptr, "OCF certificate is empty");
+ FreeOpenssl certFree(ocfCert);
+
+ // serialize
+ std::ostringstream os;
+ auto serialize = [&](const unsigned char* data, size_t size){
+ os.write(reinterpret_cast<const char*>(&size), sizeof(size));
+ os.write(reinterpret_cast<const char*>(data), size);
+ };
+
+ serialize(message->data, message->size);
+ serialize(signature->data, signature->size);
+ serialize(ocfCert, ocfCertLen);
+
+ return os.str();
+ }
+
+ void receive(std::string&& buffer)
+ {
+ // deserialize
+ std::istringstream is(buffer);
+ auto deserialize = [&]()
+ {
+ size_t size;
+ is.read(reinterpret_cast<char*>(&size), sizeof(size));
+ RUNNER_ASSERT_MSG(size > 0, "Deserialized 0 length vector");
+ std::vector<unsigned char> data(size);
+ is.read(reinterpret_cast<char*>(data.data()), size);
+
+ return data;
+ };
+
+ auto message = deserialize();
+ auto signature = deserialize();
+ auto ocfCert = deserialize();
+
+ // decompose message
+ unsigned char* messageDup = static_cast<unsigned char*>(malloc(message.size()));
+ RUNNER_ASSERT_MSG(messageDup != nullptr, "Memory allocation failed");
+ memcpy(messageDup, message.data(), message.size());
+
+ dcm_e2ee_bundle_h bundle = nullptr;
+ e2ee_positive(dcm_e2ee_create_bundle, messageDup, message.size(), &bundle);
+ RUNNER_ASSERT_MSG(bundle != nullptr, "Bundle creation failed");
+ FreeBundle freeBundle(bundle);
+
+ const char* platform = nullptr;
+ e2ee_positive(dcm_e2ee_get_bundle_platform, bundle, &platform);
+ RUNNER_ASSERT_MSG(strcmp(platform, "Tizen") == 0, "Unexpected platform:" << platform);
+
+ char* label = NULL;
+ ssize_t size = smack_new_label_from_self(&label);
+ RUNNER_ASSERT_MSG(size > 0 && label != nullptr, "Smack label acquisition failed");
+ FreeVoid freeLabel(static_cast<void*>(label));
+
+ const char* pkgId = nullptr;
+ e2ee_positive(dcm_e2ee_get_bundle_pkg_id, bundle, &pkgId);
+ RUNNER_ASSERT_MSG(strcmp(pkgId, label) == 0, "Unexpected pkg id:" << pkgId);
+
+ const unsigned char* peerPubDevKey = nullptr;
+ size_t peerPubDevKeyLen = 0;
+ e2ee_positive(dcm_e2ee_get_bundle_payload, bundle, &peerPubDevKey, &peerPubDevKeyLen);
+ RUNNER_ASSERT_MSG(peerPubDevKey != nullptr, "Empty public key");
+ RUNNER_ASSERT_MSG(peerPubDevKeyLen > 0, "Public key has zero length");
+
+ // parse OCF certificate
+ const unsigned char* ocfCertPtr = ocfCert.data();
+ auto ocfCertX509 = d2i_X509(nullptr, &ocfCertPtr, ocfCert.size());
+ RUNNER_ASSERT_MSG(ocfCertX509 != nullptr, "OCF certificate parsing failed");
+ FreeX509 freeCert(ocfCertX509);
+
+ // extract OCF public key from OCF certificate
+ EVP_PKEY *ocfPubKey = X509_get0_pubkey(ocfCertX509);
+ RUNNER_ASSERT_MSG(ocfPubKey != nullptr, "Can't get public key from OCF certificate");
+
+ // verify OCF signature
+ EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
+ RUNNER_ASSERT_MSG(mdctx != nullptr, "EVP_MD_CTX_new failed");
+ FreeMdCtx freeMd(mdctx);
+
+ int ret = EVP_DigestVerifyInit(mdctx, nullptr, EVP_sha256(), nullptr, ocfPubKey);
+ RUNNER_ASSERT_MSG(ret == 1, "EVP_DigestVerifyInit failed");
+
+ ret = EVP_DigestVerifyUpdate(mdctx, message.data(), message.size());
+ RUNNER_ASSERT_MSG(ret == 1, "EVP_DigestVerifyUpdate failed");
+
+ ret = EVP_DigestVerifyFinal(mdctx, signature.data(), signature.size());
+ RUNNER_ASSERT_MSG(ret == 1, "OCF signature verification failed");
+
+ // verify received cert with local certchain
+ auto chainPtr = getOcfChain();
+
+ // pop the first certificate
+ sk_X509_shift(chainPtr.get());
+
+ X509_STORE* store = X509_STORE_new();
+ FreeX509StoreCtx storeCtx(X509_STORE_CTX_new());
+ // store becomes a member of storeCtx
+ ret = X509_STORE_CTX_init(*storeCtx, store, ocfCertX509, chainPtr.get());
+ RUNNER_ASSERT_MSG(ret == 1, "X509_STORE_CTX_init failed");
+ ret = X509_verify_cert(*storeCtx);
+ // TODO this requires 2-element OCF cert chain
+ if (ret != 1)
+ RUNNER_ERROR_MSG("OCF certificate verification failed");
+
+ // derive shared key
+ e2ee_positive(ckmew_key_agreement,
+ ours.prv.c_str(),
+ peerPubDevKey,
+ peerPubDevKeyLen,
+ derived);
+ }
+
+ RawBufferPtr encrypt(const ParamListPtr& params, const RawBufferPtr& plain)
+ {
+ ckmc_raw_buffer_s* encrypted = nullptr;
+ e2ee_positive(ckmc_encrypt_data, params.get(), derived, "", *plain.get(), &encrypted);
+ return create_raw_buffer(encrypted);
+ }
+
+ RawBufferPtr decrypt(const ParamListPtr& params, const RawBufferPtr& encrypted)
+ {
+ ckmc_raw_buffer_s* decrypted = nullptr;
+ e2ee_positive(ckmc_decrypt_data, params.get(), derived, "", *encrypted.get(), &decrypted);
+ return create_raw_buffer(decrypted);
+ }
+
+private:
+ const KeyAliasPair& ours;
+ const char* derived;
+};
+
+} // namespace anonymous
+
+RUNNER_TEST_GROUP_INIT_ENV(E2EE_ADAPTATION_LAYER, EALGroupFixture);
+
+RUNNER_TEST(TEAL_0010_key_agreement_positive)
+{
+ const char* const OURS_DERIVED = "ours_derived";
+ const char* const PEERS_DERIVED = "peers_derived";
+ const char* const PEERS2_DERIVED = "peers2_derived";
+
+ auto our_remover = keyAgreement(OURS.prv, PEERS.pub, OURS_DERIVED);
+ auto peer_remover = keyAgreement(PEERS.prv, OURS.pub, PEERS_DERIVED);
+ auto peer2_remover = keyAgreement(PEERS2.prv, OURS.pub, PEERS2_DERIVED);
+
+ 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;
+ e2ee_positive(ckmc_encrypt_data, params.get(), OURS_DERIVED, "", *plain.get(), &encrypted);
+ auto encryptedPtr = create_raw_buffer(encrypted);
+
+ ckmc_raw_buffer_s* decrypted = nullptr;
+ e2ee_positive(ckmc_decrypt_data, params.get(), PEERS_DERIVED, "", *encrypted, &decrypted);
+ auto decryptedPtr = create_raw_buffer(decrypted);
+
+ assert_buffers_equal(plain.get(), decrypted);
+
+ decryptedPtr.reset();
+ decrypted = nullptr;
+ e2ee_positive(ckmc_decrypt_data, params.get(), PEERS2_DERIVED, "", *encrypted, &decrypted);
+ decryptedPtr = create_raw_buffer(decrypted);
+
+ assert_buffers_equal(plain.get(), decrypted, false);
+}
+
+
+RUNNER_TEST(TEAL_0020_key_agreement_wrong_arguments)
+{
+ auto pub_key = getKey(PEERS.pub);
+
+ auto invalid = [](const char* prv,
+ const unsigned char* pub,
+ size_t pub_size,
+ const char* derived)
+ {
+ e2ee_invalid_param(ckmew_key_agreement, prv, pub, pub_size, derived);
+ };
+
+ auto garbage = create_raw_buffer(createRandomBufferCAPI(pub_key->key_size));
+
+ invalid(nullptr, pub_key->raw_key, pub_key->key_size, DERIVED);
+ invalid(OURS.pub.c_str(), pub_key->raw_key, pub_key->key_size, DERIVED);
+ invalid(OURS.prv.c_str(), nullptr, pub_key->key_size, DERIVED);
+ invalid(OURS.prv.c_str(), pub_key->raw_key, 6, DERIVED);
+ invalid(OURS.prv.c_str(), garbage->data, garbage->size, DERIVED);
+ invalid(OURS.prv.c_str(), pub_key->raw_key, 0, DERIVED);
+ invalid(OURS.prv.c_str(), pub_key->raw_key, pub_key->key_size, nullptr);
+}
+
+RUNNER_TEST(TEAL_0030_key_agreement_wrong_aliases)
+{
+ const char* const DERIVED = "derived";
+
+ auto pub_key = getKey(PEERS.pub);
+
+ e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmew_key_agreement,
+ "",
+ pub_key->raw_key,
+ pub_key->key_size,
+ DERIVED);
+
+ e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmew_key_agreement,
+ "nonexistent-alias",
+ pub_key->raw_key,
+ pub_key->key_size,
+ DERIVED);
+
+ e2ee_positive(ckmew_key_agreement,
+ OURS.prv.c_str(),
+ pub_key->raw_key,
+ pub_key->key_size,
+ DERIVED);
+
+ AliasRemover remover(DERIVED);
+
+ e2ee_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmew_key_agreement,
+ OURS.prv.c_str(),
+ pub_key->raw_key,
+ pub_key->key_size,
+ 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());
+
+ e2ee_positive(ckmew_key_derive_pbkdf2, "password", salt->data, salt->size, KEY_LEN, DERIVED);
+ auto remover1 = AliasRemover(DERIVED);
+
+ ckmc_raw_buffer_s* encrypted = nullptr;
+ e2ee_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";
+ e2ee_positive(ckmew_key_derive_pbkdf2, password, salt, salt_len, key_len, DERIVED2);
+ auto remover = AliasRemover(DERIVED2);
+
+ ckmc_raw_buffer_s* decrypted = nullptr;
+ e2ee_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)
+{
+ e2ee_invalid_param(ckmew_key_derive_pbkdf2, nullptr, SALT, SALT_LEN, 32, DERIVED);
+ e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", nullptr, SALT_LEN, 32, DERIVED);
+ e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, nullptr);
+ e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 0, DERIVED);
+
+ auto invalidFormat = [&](size_t key_len) {
+ e2ee_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)
+{
+ e2ee_positive(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, DERIVED);
+
+ auto remover = AliasRemover(DERIVED);
+
+ e2ee_result(CKMC_ERROR_DB_ALIAS_EXISTS,
+ ckmew_key_derive_pbkdf2,
+ "password",
+ SALT,
+ SALT_LEN,
+ 32,
+ DERIVED);
+}
+
+RUNNER_TEST(TEAL_2000_ocf_positive)
+{
+ ckmc_raw_buffer_s* message = nullptr;
+ ckmc_raw_buffer_s* signature = nullptr;
+ e2ee_positive(ckmew_sign_with_ocf, OURS.pub.c_str(), &message, &signature);
+
+ auto messagePtr = create_raw_buffer(message);
+ auto signaturePtr = create_raw_buffer(signature);
+
+ RUNNER_ASSERT_MSG(messagePtr->size > 0, "Message buffer size is 0");
+ RUNNER_ASSERT_MSG(messagePtr->data != nullptr, "Message buffer is empty");
+
+ RUNNER_ASSERT_MSG(signaturePtr->size > 0, "Signature buffer size is 0");
+ RUNNER_ASSERT_MSG(signaturePtr->data != nullptr, "Singature buffer is empty");
+}
+
+RUNNER_TEST(TEAL_2010_ocf_invalid_param)
+{
+ ckmc_raw_buffer_s* message = nullptr;
+ ckmc_raw_buffer_s* signature = nullptr;
+
+ auto invalid = [](const char* pub_alias,
+ ckmc_raw_buffer_s** message,
+ ckmc_raw_buffer_s** signature)
+ {
+ e2ee_result(DCM_ERROR_INVALID_PARAMETER,
+ ckmew_sign_with_ocf,
+ pub_alias,
+ message,
+ signature);
+ };
+
+ invalid(nullptr, &message, &signature);
+ invalid(OURS.pub.c_str(), nullptr, &signature);
+ invalid(OURS.pub.c_str(), &message, nullptr);
+}
+
+RUNNER_TEST(TEAL_2020_ocf_wrong_public_key)
+{
+ ckmc_raw_buffer_s* message = nullptr;
+ ckmc_raw_buffer_s* signature = nullptr;
+
+ e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
+ ckmew_sign_with_ocf,
+ "nonexistent-alias",
+ &message,
+ &signature);
+
+ e2ee_result(CKMC_ERROR_NOT_EXPORTABLE,
+ ckmew_sign_with_ocf,
+ OURS.prv.c_str(),
+ &message,
+ &signature);
+}
+
+RUNNER_TEST(TEAL_3000_link_key_agreement_scenario)
+{
+ 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());
+
+ Peer p1(OURS, "our_link_key");
+ Peer p2(PEERS, "peers_link_key");
+
+ p2.receive(p1.send());
+ p1.receive(p2.send());
+
+ auto encrypted = p1.encrypt(params, plain);
+ auto decrypted = p2.decrypt(params, encrypted);
+
+ assert_buffers_equal(plain.get(), decrypted.get());
+}
+
+int main(int argc, char *argv[])
+{
+ require_default_user(argv);
+
+ return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
+}