--- /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 <cstring>
+
+#include <ckmc/ckmc-manager.h>
+
+//! [KEY_DERIVE example]
+int key_derive(const ckmc_raw_buffer_s* peers_public)
+{
+ int ret;
+
+ const char* const SECRET_ALIAS = "shared_secret";
+ const char* const KEY_ALIAS = "derived_key";
+ const char* const OURS_PRV_ALIAS = "ours_private";
+ const char* const OURS_PUB_ALIAS = "ours_public";
+
+ ckmc_policy_s unexportable { nullptr, false };
+ ckmc_policy_s exportable { nullptr, true };
+
+ // generate EC key pair
+ ret = ckmc_create_key_pair_ecdsa(CKMC_EC_PRIME256V1,
+ OURS_PRV_ALIAS,
+ OURS_PUB_ALIAS,
+ unexportable,
+ exportable);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ // set ECDH params
+ ckmc_param_list_h ecdh_params;
+ ret = ckmc_param_list_new(&ecdh_params);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_integer(ecdh_params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_buffer(ecdh_params, CKMC_PARAM_ECDH_PUBKEY, peers_public);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ // derive shared secret
+ ret = ckmc_key_derive(ecdh_params, OURS_PRV_ALIAS, nullptr, SECRET_ALIAS, unexportable);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ // set KBKDF params
+ ckmc_param_list_h kbkdf_params;
+ ret = ckmc_param_list_new(&kbkdf_params);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_KDF_PRF, CKMC_KDF_PRF_HMAC_SHA256);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_KBKDF_MODE, CKMC_KBKDF_MODE_COUNTER);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params,
+ CKMC_PARAM_KBKDF_COUNTER_LOCATION,
+ CKMC_KBKDF_COUNTER_BEFORE_FIXED);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ char label[] = "label";
+ ckmc_raw_buffer_s* label_buf = nullptr;
+ ret = ckmc_buffer_new(reinterpret_cast<unsigned char*>(label), strlen(label), &label_buf);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_buffer(kbkdf_params, CKMC_PARAM_KBKDF_LABEL, label_buf);
+ ckmc_buffer_free(label_buf);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ char context[] = "context";
+ ckmc_raw_buffer_s* context_buf = nullptr;
+ ret = ckmc_buffer_new(reinterpret_cast<unsigned char*>(context), strlen(context), &context_buf);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_buffer(kbkdf_params, CKMC_PARAM_KBKDF_CONTEXT, context_buf);
+ ckmc_buffer_free(context_buf);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ ret = ckmc_param_list_set_integer(kbkdf_params, CKMC_PARAM_KDF_LEN, 32);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ // derive symmetric key
+ ret = ckmc_key_derive(kbkdf_params, SECRET_ALIAS, nullptr, KEY_ALIAS, unexportable);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ // remove shared secret
+ ret = ckmc_remove_key(SECRET_ALIAS);
+ if (ret != CKMC_ERROR_NONE)
+ return -1;
+
+ return 0;
+}
+//! [KEY_DERIVE example]