From 331dbbf62e19033ee5995ded6921f0c8efbe006a Mon Sep 17 00:00:00 2001 From: Krzysztof Jackiewicz Date: Wed, 1 Mar 2023 10:54:50 +0100 Subject: [PATCH] E2EE: OCF API implementation Tests included. Change-Id: I04a3b56d66b51b5508e7fa4f14d923e876122f78 --- packaging/security-tests.spec | 1 + src/e2ee-adaptation-layer/CMakeLists.txt | 1 + .../e2ee-adaptation-layer.cpp | 81 +++- src/e2ee-adaptation-layer/tests.cpp | 507 ++++++++++++++++++--- 4 files changed, 508 insertions(+), 82 deletions(-) diff --git a/packaging/security-tests.spec b/packaging/security-tests.spec index 9e6e3fc..4d21ef0 100644 --- a/packaging/security-tests.spec +++ b/packaging/security-tests.spec @@ -36,6 +36,7 @@ BuildRequires: pkgconfig(vconf) 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: perf Requires: gdb diff --git a/src/e2ee-adaptation-layer/CMakeLists.txt b/src/e2ee-adaptation-layer/CMakeLists.txt index 03cff11..ab8791a 100644 --- a/src/e2ee-adaptation-layer/CMakeLists.txt +++ b/src/e2ee-adaptation-layer/CMakeLists.txt @@ -21,6 +21,7 @@ SET(TARGET_E2EE_ADAPTATION_LAYER "e2ee-adaptation-layer") PKG_CHECK_MODULES(E2EE_ADAPTATION_LAYER_DEP REQUIRED key-manager # >=0.1.48 + device-certificate-manager>=2.1 openssl1.1 ) diff --git a/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp b/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp index 73d068e..3e86ae0 100644 --- a/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp +++ b/src/e2ee-adaptation-layer/e2ee-adaptation-layer.cpp @@ -17,11 +17,14 @@ #include "e2ee-adaptation-layer.h" #include +#include + #include #include #include +#include namespace { @@ -31,6 +34,10 @@ const char* const SECRET_ALIAS = "temporary_shared_e2ee_secret"; constexpr size_t ITERATIONS = 1000; typedef std::unique_ptr ParamsPtr; +typedef std::unique_ptr DcmCtxPtr; +typedef std::unique_ptr BufferPtr; +typedef std::unique_ptr KeyPtr; +typedef std::unique_ptr BundlePtr; std::tuple makeParams() { @@ -39,8 +46,6 @@ std::tuple makeParams() return std::make_tuple(ParamsPtr(params, ckmc_param_list_free), ret); } -typedef std::unique_ptr BufferPtr; - std::tuple makeBuffer(const unsigned char* data, size_t size) { ckmc_raw_buffer_s* buffer = nullptr; @@ -60,6 +65,13 @@ private: const char* alias; }; +std::tuple 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, @@ -188,16 +200,65 @@ int ckmew_key_derive_pbkdf2(const char *password, return ret; } -int ckmew_get_ocf_cert_chain(char ** /*cert_chain*/, size_t * /*cert_chain_len*/) +int ckmew_get_ocf_cert_chain(char **cert_chain, size_t *cert_chain_len) { - // TODO - return 0; + 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*/) +int ckmew_sign_with_ocf(const char *public_key_alias, + ckmc_raw_buffer_s **message_buf, + ckmc_raw_buffer_s **signature_buf) { - // TODO - return 0; + 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(&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(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; } diff --git a/src/e2ee-adaptation-layer/tests.cpp b/src/e2ee-adaptation-layer/tests.cpp index e60d543..f10b5c6 100644 --- a/src/e2ee-adaptation-layer/tests.cpp +++ b/src/e2ee-adaptation-layer/tests.cpp @@ -16,10 +16,18 @@ #include "e2ee-adaptation-layer.h" +#include + +#include +#include +#include +#include + #include #include #include #include +#include namespace { @@ -35,7 +43,7 @@ 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 KeyAliasPair RSA_KEYS = { "rsa_private", "rsa_public" }; const char* const DERIVED = "derived"; @@ -45,6 +53,43 @@ 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 +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 +void e2ee_positive(F&& func, Args... args) +{ + e2ee_result(DCM_ERROR_NONE, std::move(func), args...); +} + +template +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: @@ -55,33 +100,33 @@ private: { ckmc_remove_alias(pair.prv.c_str()); ckmc_remove_alias(pair.pub.c_str()); - assert_positive(ckmc_create_key_pair_ecdsa, - curve, - pair.prv.c_str(), - pair.pub.c_str(), - policy_prv, - policy_pub); + 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); - assert_positive(ckmc_unlock_user_key, UID, "db-pass"); + 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.prv.c_str()); - ckmc_remove_alias(RSA.pub.c_str()); - assert_positive(ckmc_create_key_pair_rsa, - 1024, - RSA.prv.c_str(), - RSA.pub.c_str(), - 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 @@ -97,7 +142,7 @@ typedef std::unique_ptr KeyPtr; KeyPtr getKey(const std::string& alias) { ckmc_key_s* key = nullptr; - assert_positive(ckmc_get_key, alias.c_str(), "", &key); + e2ee_positive(ckmc_get_key, alias.c_str(), "", &key); return KeyPtr(key, ckmc_key_free); } @@ -105,11 +150,253 @@ KeyPtr getKey(const std::string& alias) AliasRemover keyAgreement(const std::string &prv, const std::string& pub, const char* derived) { auto pub_key = getKey(pub); - assert_positive(ckmew_key_agreement, prv.c_str(), pub_key->raw_key, pub_key->key_size, derived); + e2ee_positive(ckmew_key_agreement, prv.c_str(), pub_key->raw_key, pub_key->key_size, derived); return AliasRemover(derived); } +template +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(ptr)); +} + +typedef Free FreeBundle; +typedef Free FreeVoid; +typedef Free FreeBio; +typedef Free FreeOpenssl; +typedef Free FreeX509; +typedef Free FreeMdCtx; +typedef Free FreeX509StoreCtx; + +typedef STACK_OF(X509) X509_STACK; +typedef std::unique_ptr 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(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(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 { + ustreambuf(unsigned char* buf, size_t size) : std::basic_streambuf() + { + 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(&size), sizeof(size)); + os.write(reinterpret_cast(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(&size), sizeof(size)); + RUNNER_ASSERT_MSG(size > 0, "Deserialized 0 length vector"); + std::vector data(size); + is.read(reinterpret_cast(data.data()), size); + + return data; + }; + + auto message = deserialize(); + auto signature = deserialize(); + auto ocfCert = deserialize(); + + // decompose message + unsigned char* messageDup = static_cast(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(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); @@ -132,18 +419,18 @@ RUNNER_TEST(TEAL_0010_key_agreement_positive) setParam(params, CKMC_PARAM_ED_IV, iv.get()); ckmc_raw_buffer_s* encrypted = nullptr; - assert_positive(ckmc_encrypt_data, params.get(), OURS_DERIVED, "", *plain.get(), &encrypted); + e2ee_positive(ckmc_encrypt_data, params.get(), OURS_DERIVED, "", *plain.get(), &encrypted); auto encryptedPtr = create_raw_buffer(encrypted); ckmc_raw_buffer_s* decrypted = nullptr; - assert_positive(ckmc_decrypt_data, params.get(), PEERS_DERIVED, "", *encrypted, &decrypted); + 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; - assert_positive(ckmc_decrypt_data, params.get(), PEERS2_DERIVED, "", *encrypted, &decrypted); + e2ee_positive(ckmc_decrypt_data, params.get(), PEERS2_DERIVED, "", *encrypted, &decrypted); decryptedPtr = create_raw_buffer(decrypted); assert_buffers_equal(plain.get(), decrypted, false); @@ -159,7 +446,7 @@ RUNNER_TEST(TEAL_0020_key_agreement_wrong_arguments) size_t pub_size, const char* derived) { - assert_invalid_param(ckmew_key_agreement, prv, pub, pub_size, derived); + e2ee_invalid_param(ckmew_key_agreement, prv, pub, pub_size, derived); }; auto garbage = create_raw_buffer(createRandomBufferCAPI(pub_key->key_size)); @@ -179,34 +466,34 @@ RUNNER_TEST(TEAL_0030_key_agreement_wrong_aliases) auto pub_key = getKey(PEERS.pub); - assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN, - ckmew_key_agreement, - "", - pub_key->raw_key, - pub_key->key_size, - DERIVED); - - assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN, - ckmew_key_agreement, - "nonexistent-alias", + 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); - assert_positive(ckmew_key_agreement, - OURS.prv.c_str(), - pub_key->raw_key, - pub_key->key_size, - DERIVED); - AliasRemover remover(DERIVED); - assert_result(CKMC_ERROR_DB_ALIAS_EXISTS, - ckmew_key_agreement, - OURS.prv.c_str(), - pub_key->raw_key, - pub_key->key_size, - 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) @@ -221,11 +508,11 @@ RUNNER_TEST(TEAL_1000_pbkdf_positive) setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR); setParam(params, CKMC_PARAM_ED_IV, iv.get()); - assert_positive(ckmew_key_derive_pbkdf2, "password", salt->data, salt->size, KEY_LEN, DERIVED); + e2ee_positive(ckmew_key_derive_pbkdf2, "password", salt->data, salt->size, KEY_LEN, DERIVED); auto remover1 = AliasRemover(DERIVED); ckmc_raw_buffer_s* encrypted = nullptr; - assert_positive(ckmc_encrypt_data, params.get(), DERIVED, "", *plain.get(), &encrypted); + e2ee_positive(ckmc_encrypt_data, params.get(), DERIVED, "", *plain.get(), &encrypted); auto encryptedPtr = create_raw_buffer(encrypted); auto deriveAndDecrypt = [&encryptedPtr, ¶ms](const char* password, @@ -234,16 +521,16 @@ RUNNER_TEST(TEAL_1000_pbkdf_positive) size_t key_len) { const char* const DERIVED2 = "derived2"; - assert_positive(ckmew_key_derive_pbkdf2, password, salt, salt_len, key_len, DERIVED2); + e2ee_positive(ckmew_key_derive_pbkdf2, password, salt, salt_len, key_len, DERIVED2); auto remover = AliasRemover(DERIVED2); ckmc_raw_buffer_s* decrypted = nullptr; - assert_positive(ckmc_decrypt_data, - params.get(), - DERIVED2, - "", - *encryptedPtr.get(), - &decrypted); + e2ee_positive(ckmc_decrypt_data, + params.get(), + DERIVED2, + "", + *encryptedPtr.get(), + &decrypted); return create_raw_buffer(decrypted); }; @@ -267,19 +554,19 @@ RUNNER_TEST(TEAL_1000_pbkdf_positive) RUNNER_TEST(TEAL_1010_pbkdf_invalid_arguments) { - assert_invalid_param(ckmew_key_derive_pbkdf2, nullptr, SALT, SALT_LEN, 32, DERIVED); - assert_invalid_param(ckmew_key_derive_pbkdf2, "password", nullptr, SALT_LEN, 32, DERIVED); - assert_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, nullptr); - assert_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 0, DERIVED); + 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) { - assert_result(CKMC_ERROR_INVALID_FORMAT, - ckmew_key_derive_pbkdf2, - "password", - SALT, - SALT_LEN, - key_len, - DERIVED); + e2ee_result(CKMC_ERROR_INVALID_FORMAT, + ckmew_key_derive_pbkdf2, + "password", + SALT, + SALT_LEN, + key_len, + DERIVED); }; invalidFormat(64); invalidFormat(31); @@ -289,17 +576,93 @@ RUNNER_TEST(TEAL_1010_pbkdf_invalid_arguments) RUNNER_TEST(TEAL_1020_pbkdf_wrong_alias) { - assert_positive(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, DERIVED); + e2ee_positive(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, DERIVED); auto remover = AliasRemover(DERIVED); - assert_result(CKMC_ERROR_DB_ALIAS_EXISTS, - ckmew_key_derive_pbkdf2, - "password", - SALT, - SALT_LEN, - 32, - DERIVED); + 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[]) -- 2.7.4