E2EE: Key agreement API implementation
[platform/core/test/security-tests.git] / src / e2ee-adaptation-layer / e2ee-adaptation-layer.cpp
index cf78576..d5b39ec 100644 (file)
 
 #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(&params);
+    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*/,
@@ -38,7 +166,7 @@ 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*/,
@@ -46,5 +174,5 @@ int ckmew_sign_with_ocf(const char * /*public_key_alias*/,
                         ckmc_raw_buffer_s** /*signature_buf*/)
 {
     // TODO
-    return DCM_ERROR_NONE;
+    return 0;
 }