#include "e2ee-adaptation-layer.h"
-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*/)
+#include <cstring>
+#include <memory>
+
+#include <ckmc/ckmc-manager.h>
+
+namespace {
+
+const char* const LABEL = "label";
+const char* const CONTEXT = "context";
+const char* const SECRET_ALIAS = "temporary_shared_e2ee_secret";
+
+typedef std::unique_ptr<struct __ckmc_param_list, decltype(&ckmc_param_list_free)> ParamsPtr;
+
+std::tuple<ParamsPtr, int> makeParams()
{
- // TODO
- return CKMC_ERROR_NONE;
+ ckmc_param_list_h params = nullptr;
+ int ret = ckmc_param_list_new(¶ms);
+ return std::make_tuple(ParamsPtr(params, ckmc_param_list_free), ret);
+}
+
+typedef std::unique_ptr<ckmc_raw_buffer_s, decltype(&ckmc_buffer_free)> BufferPtr;
+
+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;
+};
+
+} // 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*/,
int ckmew_get_ocf_cert_chain(char ** /*cert_chain*/, size_t * /*cert_chain_len*/)
{
// TODO
- return DCM_ERROR_NONE;
+ return 0;
}
int ckmew_sign_with_ocf(const char * /*public_key_alias*/,
ckmc_raw_buffer_s** /*signature_buf*/)
{
// TODO
- return DCM_ERROR_NONE;
+ return 0;
}