Fix SVACE and C++ issues
[platform/core/security/key-manager.git] / tests / test_db_crypto.cpp
1 /*
2  *  Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Kyungwook Tak <k.tak@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  *
18  * @file        test_db_crypto.cpp
19  * @author      Maciej Karpiuk (m.karpiuk2@samsung.com)
20  * @version
21  * @brief
22  */
23 #include <boost/test/unit_test.hpp>
24 #include <unistd.h>
25 #include <db-crypto.h>
26 #include <iostream>
27 #include <ckm/ckm-type.h>
28 #include <ckm/ckm-error.h>
29 #include <errno.h>
30 #include <test_common.h>
31 #include <DBFixture.h>
32
33 using namespace CKM;
34
35 namespace {
36 const int restricted_local = 1;
37 const int restricted_global = 0;
38
39 const unsigned int c_test_retries = 1000;
40 const unsigned int c_num_names = 500;
41 const unsigned int c_num_names_add_test = 5000;
42 const unsigned int c_names_per_owner = 15;
43
44 } // namespace anonymous
45
46 BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_TEST, DBFixture)
47 BOOST_AUTO_TEST_CASE(DBtestSimple)
48 {
49         DB::Row rowPattern = create_default_row();
50         rowPattern.data = RawBuffer(32, 1);
51         rowPattern.dataSize = rowPattern.data.size();
52         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
53
54         check_DB_integrity(rowPattern);
55 }
56 BOOST_AUTO_TEST_CASE(DBtestBIG)
57 {
58         DB::Row rowPattern = create_default_row();
59         rowPattern.data = createBigBlob(4096);
60         rowPattern.dataSize = rowPattern.data.size();
61         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
62
63         check_DB_integrity(rowPattern);
64 }
65 BOOST_AUTO_TEST_CASE(DBtestGlobal)
66 {
67         DB::Row rowPattern = create_default_row();
68         rowPattern.data = RawBuffer(1024, 2);
69         rowPattern.dataSize = rowPattern.data.size();
70         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
71
72         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
73
74         DB::Row name_duplicate = rowPattern;
75         rowPattern.owner = rowPattern.owner + "1";
76 }
77 BOOST_AUTO_TEST_CASE(DBtestTransaction)
78 {
79         DB::Row rowPattern = create_default_row();
80         rowPattern.data = RawBuffer(100, 20);
81         rowPattern.dataSize = rowPattern.data.size();
82         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
83         DB::Crypto::Transaction transaction(&m_db);
84
85         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
86         BOOST_REQUIRE_NO_THROW(transaction.rollback());
87
88         DB::Crypto::RowOptional row_optional;
89         BOOST_REQUIRE_NO_THROW(row_optional = m_db.getRow(m_default_name,
90                                                                                   m_default_owner,
91                                                                                   DataType::BINARY_DATA));
92         BOOST_CHECK_MESSAGE(!row_optional, "Row still present after rollback");
93 }
94
95 BOOST_AUTO_TEST_CASE(DBtestBackend)
96 {
97         DB::Row rowPattern = create_default_row();
98         rowPattern.data = RawBuffer(32, 1);
99         rowPattern.dataSize = rowPattern.data.size();
100         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
101
102         rowPattern.backendId =  CryptoBackend::OpenSSL;
103         check_DB_integrity(rowPattern);
104
105         rowPattern.backendId =  CryptoBackend::TrustZone;
106         check_DB_integrity(rowPattern);
107
108         rowPattern.backendId =  CryptoBackend::None;
109         check_DB_integrity(rowPattern);
110 }
111
112 BOOST_AUTO_TEST_SUITE_END()
113
114
115
116 BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_PERF_TEST, DBFixture)
117
118 BOOST_AUTO_TEST_CASE(DBperfAddNames)
119 {
120         // actual test
121         performance_start("saveRow");
122
123         {
124                 generate_perf_DB(c_num_names_add_test, c_names_per_owner);
125         }
126
127         performance_stop(c_num_names_add_test);
128 }
129
130 BOOST_AUTO_TEST_CASE(DBperfLookupAliasByOwner)
131 {
132         // prepare data
133         generate_perf_DB(c_num_names, c_names_per_owner);
134
135         unsigned int num_owners = c_num_names / c_names_per_owner;
136         Name name;
137         ClientId owner;
138
139         // actual test - successful lookup
140         performance_start("getRow");
141
142         for (unsigned int t = 0; t < c_test_retries; t++) {
143                 int owner_num = rand_r(&t) % num_owners;
144                 generate_owner(owner_num, owner);
145
146                 unsigned int start_name = owner_num * c_names_per_owner;
147
148                 for (unsigned int name_num = start_name;
149                                 name_num < (start_name + c_names_per_owner); name_num++) {
150                         generate_name(name_num, name);
151                         read_row_expect_success(name, owner);
152                 }
153         }
154
155         performance_stop(c_test_retries * c_num_names);
156 }
157
158 // TODO this test makes no sense. Rewrite it.
159 BOOST_AUTO_TEST_CASE(DBperfLookupAliasRandomOwnershipNoPermissions)
160 {
161         // prepare data
162         generate_perf_DB(c_num_names, c_names_per_owner);
163
164         Name name;
165         ClientId owner;
166         //ClientId smack_label;
167         //unsigned int num_owners = c_num_names / c_names_per_owner;
168
169         // actual test - random lookup
170         performance_start("getRow");
171
172         for (unsigned int t = 0; t < c_test_retries; t++) {
173                 int name_idx = rand_r(&t) % c_num_names;
174                 generate_name(name_idx, name);
175                 generate_owner(name_idx / c_names_per_owner, owner);
176                 //generate_owner(rand_r(&t) % num_owners, smack_label);
177
178                 // do not care of result
179                 m_db.getRow(name, owner, DataType::BINARY_DATA);
180         }
181
182         performance_stop(c_test_retries * c_num_names);
183 }
184
185 BOOST_AUTO_TEST_CASE(DBperfAddPermissions)
186 {
187         // prepare data
188         generate_perf_DB(c_num_names, c_names_per_owner);
189
190         // actual test - add access rights
191         performance_start("setPermission");
192         long iterations = add_full_access_rights(c_num_names, c_names_per_owner);
193         performance_stop(iterations);
194 }
195
196 BOOST_AUTO_TEST_CASE(DBperfAliasRemoval)
197 {
198         // prepare data
199         generate_perf_DB(c_num_names, c_names_per_owner);
200         add_full_access_rights(c_num_names, c_names_per_owner);
201
202         // actual test - random lookup
203         performance_start("deleteRow");
204         Name name;
205         ClientId owner;
206
207         for (unsigned int t = 0; t < c_num_names; t++) {
208                 generate_name(t, name);
209                 generate_owner(t / c_names_per_owner, owner);
210
211                 BOOST_REQUIRE_NO_THROW(m_db.deleteRow(name, owner));
212         }
213
214         performance_stop(c_num_names);
215
216         // verify everything has been removed
217         unsigned int num_owners = c_num_names / c_names_per_owner;
218
219         for (unsigned int l = 0; l < num_owners; l++) {
220                 generate_owner(l, owner);
221                 OwnerNameVector expect_no_data;
222                 BOOST_REQUIRE_NO_THROW(m_db.listNames(owner, expect_no_data,
223                                                                                           DataType::BINARY_DATA));
224                 BOOST_REQUIRE(0 == expect_no_data.size());
225         }
226 }
227
228 BOOST_AUTO_TEST_CASE(DBperfGetAliasList)
229 {
230         // prepare data
231         generate_perf_DB(c_num_names, c_names_per_owner);
232         add_full_access_rights(c_num_names, c_names_per_owner);
233
234         unsigned int num_owners = c_num_names / c_names_per_owner;
235         ClientId owner;
236
237         // actual test - random lookup
238         performance_start("listNames");
239
240         for (unsigned int t = 0; t < (c_test_retries / num_owners); t++) {
241                 OwnerNameVector ret_list;
242                 generate_owner(rand_r(&t) % num_owners, owner);
243
244                 BOOST_REQUIRE_NO_THROW(m_db.listNames(owner, ret_list, DataType::BINARY_DATA));
245                 BOOST_REQUIRE(c_num_names == ret_list.size());
246                 ret_list.clear();
247         }
248
249         performance_stop(c_test_retries / num_owners);
250 }
251 BOOST_AUTO_TEST_SUITE_END()
252
253
254 BOOST_AUTO_TEST_SUITE(DBCRYPTO_MIGRATION_TEST)
255 namespace {
256 const unsigned migration_names = 16107;
257 const unsigned migration_owners = 273;
258 const unsigned migration_reference_owner_idx = 0;
259 const unsigned migration_accessed_element_idx = 7;
260
261 void verifyDBisValid(DBFixture &fixture)
262 {
263         /**
264          * There are (migration_owners), each having (migration_names)/(migration_owners)
265          * entries. Reference owner (migration_reference_owner_idx) exists such that
266          * it has access to all other owners' elements with index
267          * (migration_accessed_element_idx).
268          *
269          * Example:
270          * - migration_owner_63 has access to all items owned by migration_owner_63,
271          *   which gives (migration_names)/(migration_owners) entries.
272          *
273          * - migration_owner_0 (0 is the reference owner) has access to all items
274          *   owned by migration_owner_0 and all other owners' elements with index 7,
275          *   which gives (migration_names)/(migration_owners)  + (migration_owners-1) entries.
276          *
277          */
278         ClientId reference_owner;
279         fixture.generate_owner(migration_reference_owner_idx, reference_owner);
280
281         // check number of elements accessible to the reference owner
282         OwnerNameVector ret_list;
283         BOOST_REQUIRE_NO_THROW(fixture.m_db.listNames(reference_owner, ret_list,
284                                                    DataType::BINARY_DATA));
285         BOOST_REQUIRE((migration_names / migration_owners)/*own items*/ +
286                                   (migration_owners - 1)/*other owners'*/ == ret_list.size());
287         ret_list.clear();
288
289         // check number of elements accessible to the other owners
290         for (unsigned int l = 0; l < migration_owners; l++) {
291                 // bypass the reference owner
292                 if (l == migration_reference_owner_idx)
293                         continue;
294
295                 ClientId current_owner;
296                 fixture.generate_owner(l, current_owner);
297                 BOOST_REQUIRE_NO_THROW(fixture.m_db.listNames(current_owner, ret_list,
298                                                            DataType::BINARY_DATA));
299                 BOOST_REQUIRE((migration_names / migration_owners) == ret_list.size());
300
301                 for (auto it : ret_list)
302                         BOOST_REQUIRE(it.first == current_owner);
303
304                 ret_list.clear();
305         }
306 }
307
308 struct DBVer1Migration : public DBFixture {
309         DBVer1Migration() : DBFixture(DB_TEST_DIR "/testme_ver1.db") {}
310 };
311
312 struct DBVer2Migration : public DBFixture {
313         DBVer2Migration() : DBFixture(DB_TEST_DIR "/testme_ver2.db") {}
314 };
315
316 struct DBVer3Migration : public DBFixture {
317         DBVer3Migration() : DBFixture(DB_TEST_DIR "/testme_ver3.db") {}
318 };
319 }
320
321 BOOST_AUTO_TEST_CASE(DBMigrationDBVer1)
322 {
323         DBVer1Migration DBver1;
324         verifyDBisValid(DBver1);
325 }
326
327 BOOST_AUTO_TEST_CASE(DBMigrationDBVer2)
328 {
329         DBVer2Migration DBver2;
330         verifyDBisValid(DBver2);
331 }
332
333 BOOST_AUTO_TEST_CASE(DBMigrationDBVer3)
334 {
335         DBVer3Migration DBver3;
336         verifyDBisValid(DBver3);
337 }
338
339 BOOST_AUTO_TEST_CASE(DBMigrationDBCurrent)
340 {
341         DBFixture currentDB;
342
343         // prepare data using current DB mechanism
344         ClientId reference_owner;
345         currentDB.generate_owner(migration_reference_owner_idx, reference_owner);
346
347         {
348                 currentDB.generate_perf_DB(migration_names, migration_names / migration_owners);
349
350                 // only the reference owner has access to the other owners' elements <migration_accessed_element_idx>
351                 for (unsigned int l = 0; l < migration_owners; l++) {
352                         // bypass the reference owner
353                         if (l == migration_reference_owner_idx)
354                                 continue;
355
356                         unsigned element_index = migration_accessed_element_idx + l * migration_names /
357                                                                          migration_owners;
358
359                         // add permission
360                         Name accessed_name;
361                         currentDB.generate_name(element_index, accessed_name);
362                         ClientId current_owner;
363                         currentDB.generate_owner(l, current_owner);
364                         currentDB.add_permission(accessed_name, current_owner, reference_owner);
365                 }
366         }
367
368         verifyDBisValid(currentDB);
369 }
370
371 BOOST_AUTO_TEST_SUITE_END()