CKM: Add ECDH tests
[platform/core/test/security-tests.git] / src / ckm / unprivileged / key-derivation.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 <string>
18 #include <vector>
19 #include <unordered_map>
20
21 #include <dpl/test/test_runner.h>
22 #include <ckm-common.h>
23 #include <ckmc/ckmc-manager.h>
24 #include <ckmc/ckmc-control.h>
25
26 namespace {
27
28 const char* PASSWORD = "test-password";
29 const uid_t UID = 5001;
30
31 struct KeyAliasPair
32 {
33     std::string prv;
34     std::string pub;
35 };
36
37 const KeyAliasPair OURS = { "our_ec_private", "our_ec_public" };
38 const KeyAliasPair PEERS = { "peer_ec_private", "peer_ec_public" };
39 const KeyAliasPair PEERS2 = { "peer2_ec_private", "peer2_ec_public" };
40 const KeyAliasPair WRONG = { "wrong_ec_private", "wrong_ec_public" };
41 const KeyAliasPair RSA = { "rsa_private", "rsa_public" };
42 const std::string DERIVED = "derived";
43
44 const ckmc_policy_s UNEXPORTABLE { nullptr, false };
45 const ckmc_policy_s EXPORTABLE { nullptr, true };
46 const ckmc_policy_s UNEXPORTABLE_PW { const_cast<char*>(PASSWORD), false };
47 const ckmc_policy_s EXPORTABLE_PW { const_cast<char*>(PASSWORD), true };
48
49 class EcdhGroupFixture: public DPL::Test::TestGroup
50 {
51 private:
52     void GenerateEC(ckmc_ec_type_e curve,
53                     const KeyAliasPair& pair,
54                     const ckmc_policy_s& policy_prv,
55                     const ckmc_policy_s& policy_pub)
56     {
57         assert_positive(ckmc_create_key_pair_ecdsa,
58                         curve,
59                         pair.prv.c_str(),
60                         pair.pub.c_str(),
61                         policy_prv,
62                         policy_pub);
63     }
64
65 public:
66     void Init() override
67     {
68         remove_user_data(UID);
69         assert_positive(ckmc_unlock_user_key, UID, "db-pass");
70
71         GenerateEC(CKMC_EC_PRIME256V1, OURS, UNEXPORTABLE, EXPORTABLE);
72         GenerateEC(CKMC_EC_PRIME256V1, PEERS, UNEXPORTABLE_PW, EXPORTABLE);
73         GenerateEC(CKMC_EC_PRIME256V1, PEERS2, EXPORTABLE, EXPORTABLE);
74         GenerateEC(CKMC_EC_PRIME192V1, WRONG, UNEXPORTABLE, EXPORTABLE);
75
76         assert_positive(ckmc_create_key_pair_rsa,
77                         1024,
78                         RSA.prv.c_str(),
79                         RSA.pub.c_str(),
80                         UNEXPORTABLE,
81                         EXPORTABLE);
82     }
83
84     void Finish() override
85     {
86         int ret = ckmc_lock_user_key(UID);
87         if (ret != CKMC_ERROR_NONE)
88             RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
89         remove_user_data(UID);
90     }
91 };
92
93 struct DerivedFixture
94 {
95     void init(const std::string&)
96     {
97     }
98
99     void finish()
100     {
101         ckmc_remove_alias(DERIVED.c_str());
102     }
103 };
104
105 RawBufferPtr getPublicKey(const std::string& pub_alias)
106 {
107     ckmc_key_s *pubKey = nullptr;
108     assert_positive(ckmc_get_key, pub_alias.c_str(), "", &pubKey);
109
110     ckmc_raw_buffer_s* pubBuffer = nullptr;
111     assert_positive(ckmc_buffer_new, pubKey->raw_key, pubKey->key_size, &pubBuffer);
112     ckmc_key_free(pubKey);
113
114     return create_raw_buffer(pubBuffer);
115 }
116
117 ParamListPtr getDefaultECDHParams(const std::string& pubAlias)
118 {
119     auto ecdhParams = createParamListPtr();
120     setParam(ecdhParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
121     auto pubKey = getPublicKey(pubAlias);
122     setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, pubKey.get());
123     return ecdhParams;
124 }
125
126 void deriveEcdh(const std::string& prvAlias,
127                 const std::string& prvPass,
128                 const std::string& pubAlias,
129                 const std::string& derivedAlias,
130                 const ckmc_policy_s& derivedPolicy,
131                 int expected)
132 {
133     auto ecdhParams = getDefaultECDHParams(pubAlias);
134
135     assert_result(expected,
136                   ckmc_key_derive,
137                   ecdhParams.get(),
138                   prvAlias.c_str(),
139                   prvPass.c_str(),
140                   derivedAlias.c_str(),
141                   derivedPolicy);
142 }
143
144 RawBufferPtr deriveEcdhAndGet(const std::string& prvAlias,
145                               const std::string& prvPass,
146                               const std::string& pubAlias,
147                               const std::string& derivedAlias,
148                               const ckmc_policy_s& derivedPolicy)
149 {
150     deriveEcdh(prvAlias, prvPass, pubAlias, derivedAlias, derivedPolicy, CKMC_ERROR_NONE);
151
152     ckmc_raw_buffer_s *derivedBuffer = nullptr;
153     assert_positive(ckmc_get_data, derivedAlias.c_str(), derivedPolicy.password, &derivedBuffer);
154
155     ckmc_remove_alias(derivedAlias.c_str());
156
157     return create_raw_buffer(derivedBuffer);
158 }
159
160 void invalidDerive(const ParamListPtr& params)
161 {
162     assert_invalid_param(ckmc_key_derive,
163                          params.get(),
164                          OURS.prv.c_str(),
165                          "",
166                          DERIVED.c_str(),
167                          EXPORTABLE);
168 }
169
170 } // namespace anonymous
171
172 RUNNER_TEST_GROUP_INIT_ENV(CKM_DERIVE_ECDH, EcdhGroupFixture);
173
174 RUNNER_TEST(TECDH_0010_positive, DerivedFixture)
175 {
176     auto ourDerived = deriveEcdhAndGet(OURS.prv, "", PEERS.pub, DERIVED, EXPORTABLE);
177     auto peerDerived = deriveEcdhAndGet(PEERS.prv, PASSWORD, OURS.pub, DERIVED, EXPORTABLE_PW);
178
179     assert_buffers_equal(ourDerived.get(), peerDerived.get());
180
181     auto wrongDerived = deriveEcdhAndGet(OURS.prv, "", PEERS2.pub, DERIVED, EXPORTABLE);
182
183     assert_buffers_equal(ourDerived.get(), wrongDerived.get(), false);
184 }
185
186 RUNNER_TEST(TECDH_0020_missing_arguments, DerivedFixture)
187 {
188     auto ecdhParams = getDefaultECDHParams(PEERS.pub);
189
190     assert_invalid_param(ckmc_key_derive,
191                          nullptr,
192                          OURS.prv.c_str(),
193                          "",
194                          DERIVED.c_str(),
195                          EXPORTABLE);
196
197     assert_invalid_param(ckmc_key_derive,
198                          ecdhParams.get(),
199                          nullptr,
200                          "",
201                          DERIVED.c_str(),
202                          EXPORTABLE);
203
204     assert_invalid_param(ckmc_key_derive,
205                          ecdhParams.get(),
206                          OURS.prv.c_str(),
207                          "",
208                          nullptr,
209                          EXPORTABLE);
210 }
211
212 RUNNER_TEST(TECDH_0030_unknown_alias, DerivedFixture)
213 {
214     auto ecdhParams = getDefaultECDHParams(PEERS.pub);
215
216     assert_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
217                   ckmc_key_derive,
218                   ecdhParams.get(),
219                   "nonexistent-alias",
220                   "",
221                   DERIVED.c_str(),
222                   EXPORTABLE);
223 }
224
225 RUNNER_TEST(TECDH_0040_alias_exists, DerivedFixture)
226 {
227     auto ecdhParams = getDefaultECDHParams(PEERS.pub);
228
229     assert_positive(ckmc_key_derive,
230                     ecdhParams.get(),
231                     OURS.prv.c_str(),
232                     "",
233                     DERIVED.c_str(),
234                     EXPORTABLE);
235
236     assert_result(CKMC_ERROR_DB_ALIAS_EXISTS,
237                   ckmc_key_derive,
238                   ecdhParams.get(),
239                   OURS.prv.c_str(),
240                   "",
241                   DERIVED.c_str(),
242                   EXPORTABLE);
243 }
244
245 RUNNER_TEST(TECDH_0050_derived_password, DerivedFixture)
246 {
247     auto ecdhParams = getDefaultECDHParams(PEERS.pub);
248
249     assert_positive(ckmc_key_derive,
250                     ecdhParams.get(),
251                     OURS.prv.c_str(),
252                     "",
253                     DERIVED.c_str(),
254                     EXPORTABLE_PW);
255
256     ckmc_raw_buffer_s *derived = nullptr;
257     assert_result(CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), "", &derived);
258     assert_result(CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), "pw", &derived);
259
260     assert_positive(ckmc_remove_alias, DERIVED.c_str());
261
262     assert_positive(ckmc_key_derive,
263                     ecdhParams.get(),
264                     OURS.prv.c_str(),
265                     "",
266                     DERIVED.c_str(),
267                     EXPORTABLE);
268
269     assert_result(CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), "pw", &derived);
270     assert_result(
271             CKMC_ERROR_AUTHENTICATION_FAILED, ckmc_get_data, DERIVED.c_str(), PASSWORD, &derived);
272 }
273
274 RUNNER_TEST(TECDH_0050_derived_unexportable, DerivedFixture)
275 {
276     auto ecdhParams = getDefaultECDHParams(PEERS.pub);
277
278     assert_positive(ckmc_key_derive,
279                     ecdhParams.get(),
280                     OURS.prv.c_str(),
281                     "",
282                     DERIVED.c_str(),
283                     UNEXPORTABLE);
284
285     ckmc_raw_buffer_s *derived = nullptr;
286     assert_result(CKMC_ERROR_NOT_EXPORTABLE, ckmc_get_data, DERIVED.c_str(), "", &derived);
287 }
288
289 RUNNER_TEST(TECDH_0100_wrong_parameters, DerivedFixture)
290 {
291     auto ecdhParams = createParamListPtr();
292
293     // no algo
294     invalidDerive(ecdhParams);
295
296     // no pubkey
297     setParam(ecdhParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_ECDH);
298     invalidDerive(ecdhParams);
299
300     // garbage pubkey
301     ckmc_raw_buffer_s* garbage = createRandomBufferCAPI(1);
302     auto buffer = create_raw_buffer(garbage);
303     setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, buffer.get());
304     invalidDerive(ecdhParams);
305
306     // private key instead of pubkey
307     buffer = getPublicKey(PEERS2.prv);
308     setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, buffer.get());
309     invalidDerive(ecdhParams);
310
311     // wrong algo
312     buffer = getPublicKey(OURS.pub);
313     setParam(ecdhParams, CKMC_PARAM_ECDH_PUBKEY, buffer.get());
314     setParam(ecdhParams, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_KBKDF);
315     invalidDerive(ecdhParams);
316 }
317
318 RUNNER_TEST(TECDH_0200_wrong_password, DerivedFixture)
319 {
320     deriveEcdh(PEERS.prv, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_AUTHENTICATION_FAILED);
321     deriveEcdh(OURS.prv,
322                UNEXPORTABLE_PW.password,
323                PEERS.pub,
324                DERIVED,
325                UNEXPORTABLE,
326                CKMC_ERROR_AUTHENTICATION_FAILED);
327 }
328
329 RUNNER_TEST(TECDH_0210_different_curves, DerivedFixture)
330 {
331     deriveEcdh(OURS.prv, "", WRONG.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
332     deriveEcdh(WRONG.prv, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
333 }
334
335 RUNNER_TEST(TECDH_0220_different_key_types, DerivedFixture)
336 {
337     deriveEcdh(OURS.prv, "", RSA.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
338     deriveEcdh(RSA.prv, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
339 }
340
341 RUNNER_TEST(TECDH_0230_public_instead_of_private, DerivedFixture)
342 {
343     deriveEcdh(OURS.pub, "", OURS.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
344 }
345
346 RUNNER_TEST(TECDH_0230_wrong_key_types, DerivedFixture)
347 {
348     deriveEcdh(RSA.prv, "", RSA.pub, DERIVED, UNEXPORTABLE, CKMC_ERROR_INVALID_PARAMETER);
349 }