E2EE: PBKDF API implementation
[platform/core/test/security-tests.git] / src / e2ee-adaptation-layer / e2ee-adaptation-layer.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 #include "e2ee-adaptation-layer.h"
18
19 #include <cstring>
20 #include <memory>
21
22 #include <openssl/evp.h>
23
24 #include <ckmc/ckmc-manager.h>
25
26 namespace {
27
28 const char* const LABEL = "label";
29 const char* const CONTEXT = "context";
30 const char* const SECRET_ALIAS = "temporary_shared_e2ee_secret";
31 constexpr size_t ITERATIONS = 1000;
32
33 typedef std::unique_ptr<struct __ckmc_param_list, decltype(&ckmc_param_list_free)> ParamsPtr;
34
35 std::tuple<ParamsPtr, int> makeParams()
36 {
37     ckmc_param_list_h params = nullptr;
38     int ret = ckmc_param_list_new(&params);
39     return std::make_tuple(ParamsPtr(params, ckmc_param_list_free), ret);
40 }
41
42 typedef std::unique_ptr<ckmc_raw_buffer_s, decltype(&ckmc_buffer_free)> BufferPtr;
43
44 std::tuple<BufferPtr, int> makeBuffer(const unsigned char* data, size_t size)
45 {
46     ckmc_raw_buffer_s* buffer = nullptr;
47     int ret = ckmc_buffer_new(const_cast<unsigned char*>(data), size, &buffer);
48     return std::make_tuple(BufferPtr(buffer, ckmc_buffer_free), ret);
49 }
50
51 class AliasRemover
52 {
53 public:
54     AliasRemover(const char *alias) : alias(alias) {}
55     ~AliasRemover() {
56         ckmc_remove_alias(alias);
57     }
58
59 private:
60     const char* alias;
61 };
62
63 } // anonymous namespace
64
65 int ckmew_key_agreement(const char *private_key_alias,
66                         const unsigned char *raw_public_key,
67                         size_t raw_public_key_len,
68                         const char *new_key_alias)
69 {
70     if (private_key_alias == nullptr || raw_public_key == nullptr || raw_public_key_len == 0 ||
71         new_key_alias == nullptr)
72         return CKMC_ERROR_INVALID_PARAMETER;
73
74     ckmc_policy_s unexportable { nullptr, false };
75
76     auto [ecdh_params, ret] = makeParams();
77     if (ret != CKMC_ERROR_NONE)
78         return ret;
79
80     ret = ckmc_param_list_set_integer(ecdh_params.get(), CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
81     if (ret != CKMC_ERROR_NONE)
82         return ret;
83
84     auto [peers_public, ret2] = makeBuffer(raw_public_key, raw_public_key_len);
85     if (ret2 != CKMC_ERROR_NONE)
86         return ret2;
87
88     ret = ckmc_param_list_set_buffer(ecdh_params.get(), CKMC_PARAM_ECDH_PUBKEY, peers_public.get());
89     if (ret != CKMC_ERROR_NONE)
90         return ret;
91
92     // derive shared secret
93     ret = ckmc_key_derive(ecdh_params.get(),
94                           private_key_alias,
95                           nullptr,
96                           SECRET_ALIAS,
97                           unexportable);
98     if (ret != CKMC_ERROR_NONE)
99         return ret;
100
101     // delete secret
102     AliasRemover remover(SECRET_ALIAS);
103
104     // set KBKDF params
105     auto [kbkdf_params, ret3] = makeParams();
106     if (ret3 != CKMC_ERROR_NONE)
107         return ret3;
108
109     ret = ckmc_param_list_set_integer(kbkdf_params.get(), CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
110     if (ret != CKMC_ERROR_NONE)
111         return ret;
112
113     ret = ckmc_param_list_set_integer(kbkdf_params.get(),
114                                       CKMC_PARAM_KDF_PRF,
115                                       CKMC_KDF_PRF_HMAC_SHA256);
116     if (ret != CKMC_ERROR_NONE)
117         return ret;
118
119     ret = ckmc_param_list_set_integer(kbkdf_params.get(),
120                                       CKMC_PARAM_KBKDF_MODE,
121                                       CKMC_KBKDF_MODE_COUNTER);
122     if (ret != CKMC_ERROR_NONE)
123         return ret;
124
125     ret = ckmc_param_list_set_integer(kbkdf_params.get(),
126                                       CKMC_PARAM_KBKDF_COUNTER_LOCATION,
127                                       CKMC_KBKDF_COUNTER_BEFORE_FIXED);
128     if (ret != CKMC_ERROR_NONE)
129         return ret;
130
131     auto [label_buf, ret4] = makeBuffer(reinterpret_cast<const unsigned char*>(LABEL),
132                                         strlen(LABEL));
133     if (ret4 != CKMC_ERROR_NONE)
134         return ret4;
135
136     ret = ckmc_param_list_set_buffer(kbkdf_params.get(), CKMC_PARAM_KBKDF_LABEL, label_buf.get());
137     if (ret != CKMC_ERROR_NONE)
138         return ret;
139
140     auto [context_buf, ret5] = makeBuffer(reinterpret_cast<const unsigned char*>(CONTEXT),
141                                           strlen(CONTEXT));
142     if (ret5 != CKMC_ERROR_NONE)
143         return ret5;
144
145     ret = ckmc_param_list_set_buffer(kbkdf_params.get(),
146                                      CKMC_PARAM_KBKDF_CONTEXT,
147                                      context_buf.get());
148     if (ret != CKMC_ERROR_NONE)
149         return ret;
150
151     ret = ckmc_param_list_set_integer(kbkdf_params.get(), CKMC_PARAM_KDF_LEN, 32);
152     if (ret != CKMC_ERROR_NONE)
153         return ret;
154
155     // derive symmetric key
156     return ckmc_key_derive(kbkdf_params.get(), SECRET_ALIAS, nullptr, new_key_alias, unexportable);
157 }
158
159 int ckmew_key_derive_pbkdf2(const char *password,
160                             const unsigned char *salt,
161                             size_t salt_len,
162                             size_t new_key_len,
163                             const char *new_key_alias)
164 {
165     if (password == nullptr || salt == nullptr || new_key_alias == nullptr || new_key_len == 0)
166         return CKMC_ERROR_INVALID_PARAMETER;
167
168     unsigned char derived[new_key_len];
169
170     if (1 != PKCS5_PBKDF2_HMAC_SHA1(password,
171                                     strlen(password),
172                                     salt,
173                                     salt_len,
174                                     ITERATIONS,
175                                     new_key_len,
176                                     derived))
177         return CKMC_ERROR_SERVER_ERROR;
178
179     ckmc_key_s* key = nullptr;
180     int ret = ckmc_key_new(derived, new_key_len, CKMC_KEY_AES, nullptr, &key);
181     if (ret != CKMC_ERROR_NONE)
182         return ret;
183
184     ckmc_policy_s unexportable { nullptr, false };
185     ret = ckmc_save_key(new_key_alias, *key, unexportable);
186     ckmc_key_free(key);
187
188     return ret;
189 }
190
191 int ckmew_get_ocf_cert_chain(char ** /*cert_chain*/, size_t * /*cert_chain_len*/)
192 {
193     // TODO
194     return 0;
195 }
196
197 int ckmew_sign_with_ocf(const char * /*public_key_alias*/,
198                         ckmc_raw_buffer_s** /*message_buf*/,
199                         ckmc_raw_buffer_s** /*signature_buf*/)
200 {
201     // TODO
202     return 0;
203 }