#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 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";
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:
{
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
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);
}
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 <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);
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);
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));
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)
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,
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);
};
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);
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[])