Migrate secure-storage data
[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_label = 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.ownerLabel = rowPattern.ownerLabel + "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_label,
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_label);
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_label);
134
135         unsigned int num_labels = c_num_names / c_names_per_label;
136         Name name;
137         Label label;
138
139         // actual test - successful lookup
140         performance_start("getRow");
141
142         for (unsigned int t = 0; t < c_test_retries; t++) {
143                 int label_num = rand_r(&t) % num_labels;
144                 generate_label(label_num, label);
145
146                 unsigned int start_name = label_num * c_names_per_label;
147
148                 for (unsigned int name_num = start_name;
149                                 name_num < (start_name + c_names_per_label); name_num++) {
150                         generate_name(name_num, name);
151                         read_row_expect_success(name, label);
152                 }
153         }
154
155         performance_stop(c_test_retries * c_num_names);
156 }
157
158 BOOST_AUTO_TEST_CASE(DBperfLookupAliasRandomOwnershipNoPermissions)
159 {
160         // prepare data
161         generate_perf_DB(c_num_names, c_names_per_label);
162
163         Name name;
164         Label owner_label;
165         Label smack_label;
166         unsigned int num_labels = c_num_names / c_names_per_label;
167
168         // actual test - random lookup
169         performance_start("getRow");
170
171         for (unsigned int t = 0; t < c_test_retries; t++) {
172                 int name_idx = rand_r(&t) % c_num_names;
173                 generate_name(name_idx, name);
174                 generate_label(name_idx / c_names_per_label, owner_label);
175                 generate_label(rand_r(&t) % num_labels, smack_label);
176
177                 // do not care of result
178                 m_db.getRow(name, owner_label, DataType::BINARY_DATA);
179         }
180
181         performance_stop(c_test_retries * c_num_names);
182 }
183
184 BOOST_AUTO_TEST_CASE(DBperfAddPermissions)
185 {
186         // prepare data
187         generate_perf_DB(c_num_names, c_names_per_label);
188
189         // actual test - add access rights
190         performance_start("setPermission");
191         long iterations = add_full_access_rights(c_num_names, c_names_per_label);
192         performance_stop(iterations);
193 }
194
195 BOOST_AUTO_TEST_CASE(DBperfAliasRemoval)
196 {
197         // prepare data
198         generate_perf_DB(c_num_names, c_names_per_label);
199         add_full_access_rights(c_num_names, c_names_per_label);
200
201         // actual test - random lookup
202         performance_start("deleteRow");
203         Name name;
204         Label label;
205
206         for (unsigned int t = 0; t < c_num_names; t++) {
207                 generate_name(t, name);
208                 generate_label(t / c_names_per_label, label);
209
210                 BOOST_REQUIRE_NO_THROW(m_db.deleteRow(name, label));
211         }
212
213         performance_stop(c_num_names);
214
215         // verify everything has been removed
216         unsigned int num_labels = c_num_names / c_names_per_label;
217
218         for (unsigned int l = 0; l < num_labels; l++) {
219                 generate_label(l, label);
220                 LabelNameVector expect_no_data;
221                 BOOST_REQUIRE_NO_THROW(m_db.listNames(label, expect_no_data,
222                                                                                           DataType::BINARY_DATA));
223                 BOOST_REQUIRE(0 == expect_no_data.size());
224         }
225 }
226
227 BOOST_AUTO_TEST_CASE(DBperfGetAliasList)
228 {
229         // prepare data
230         generate_perf_DB(c_num_names, c_names_per_label);
231         add_full_access_rights(c_num_names, c_names_per_label);
232
233         unsigned int num_labels = c_num_names / c_names_per_label;
234         Label label;
235
236         // actual test - random lookup
237         performance_start("listNames");
238
239         for (unsigned int t = 0; t < (c_test_retries / num_labels); t++) {
240                 LabelNameVector ret_list;
241                 generate_label(rand_r(&t) % num_labels, label);
242
243                 BOOST_REQUIRE_NO_THROW(m_db.listNames(label, ret_list, DataType::BINARY_DATA));
244                 BOOST_REQUIRE(c_num_names == ret_list.size());
245                 ret_list.clear();
246         }
247
248         performance_stop(c_test_retries / num_labels);
249 }
250 BOOST_AUTO_TEST_SUITE_END()
251
252
253 BOOST_AUTO_TEST_SUITE(DBCRYPTO_MIGRATION_TEST)
254 namespace {
255 const unsigned migration_names = 16107;
256 const unsigned migration_labels = 273;
257 const unsigned migration_reference_label_idx = 0;
258 const unsigned migration_accessed_element_idx = 7;
259
260 void verifyDBisValid(DBFixture &fixture)
261 {
262         /**
263          * there are (migration_labels), each having (migration_names)/(migration_labels) entries.
264          * reference label (migration_reference_label_idx) exists such that it has access to
265          * all others' label element with index (migration_accessed_element_idx).
266          *
267          * Example:
268          * - migration_label_63 has access to all items owned by migration_label_63,
269          *   which gives (migration_names)/(migration_labels) entries.
270          *
271          * - migration_label_0 (0 is the reference label) has access to all items
272          *   owned by migration_label_0 and all others' label element index 7,
273          *   which gives (migration_names)/(migration_labels)  + (migration_labels-1) entries.
274          *
275          */
276         Label reference_label;
277         fixture.generate_label(migration_reference_label_idx, reference_label);
278
279         // check number of elements accessible to the reference label
280         LabelNameVector ret_list;
281         BOOST_REQUIRE_NO_THROW(fixture.m_db.listNames(reference_label, ret_list,
282                                                    DataType::BINARY_DATA));
283         BOOST_REQUIRE((migration_names / migration_labels)/*own items*/ +
284                                   (migration_labels - 1)/*other labels'*/ == ret_list.size());
285         ret_list.clear();
286
287         // check number of elements accessible to the other labels
288         for (unsigned int l = 0; l < migration_labels; l++) {
289                 // bypass the reference owner label
290                 if (l == migration_reference_label_idx)
291                         continue;
292
293                 Label current_label;
294                 fixture.generate_label(l, current_label);
295                 BOOST_REQUIRE_NO_THROW(fixture.m_db.listNames(current_label, ret_list,
296                                                            DataType::BINARY_DATA));
297                 BOOST_REQUIRE((migration_names / migration_labels) == ret_list.size());
298
299                 for (auto it : ret_list)
300                         BOOST_REQUIRE(it.first == current_label);
301
302                 ret_list.clear();
303         }
304 }
305
306 struct DBVer1Migration : public DBFixture {
307         DBVer1Migration() : DBFixture(DB_TEST_DIR "/testme_ver1.db") {}
308 };
309
310 struct DBVer2Migration : public DBFixture {
311         DBVer2Migration() : DBFixture(DB_TEST_DIR "/testme_ver2.db") {}
312 };
313
314 struct DBVer3Migration : public DBFixture {
315         DBVer3Migration() : DBFixture(DB_TEST_DIR "/testme_ver3.db") {}
316 };
317 }
318
319 BOOST_AUTO_TEST_CASE(DBMigrationDBVer1)
320 {
321         DBVer1Migration DBver1;
322         verifyDBisValid(DBver1);
323 }
324
325 BOOST_AUTO_TEST_CASE(DBMigrationDBVer2)
326 {
327         DBVer2Migration DBver2;
328         verifyDBisValid(DBver2);
329 }
330
331 BOOST_AUTO_TEST_CASE(DBMigrationDBVer3)
332 {
333         DBVer3Migration DBver3;
334         verifyDBisValid(DBver3);
335 }
336
337 BOOST_AUTO_TEST_CASE(DBMigrationDBCurrent)
338 {
339         DBFixture currentDB;
340
341         // prepare data using current DB mechanism
342         Label reference_label;
343         currentDB.generate_label(migration_reference_label_idx, reference_label);
344
345         {
346                 currentDB.generate_perf_DB(migration_names, migration_names / migration_labels);
347
348                 // only the reference label has access to the other labels element <migration_accessed_element_idx>
349                 for (unsigned int l = 0; l < migration_labels; l++) {
350                         // bypass the reference owner label
351                         if (l == migration_reference_label_idx)
352                                 continue;
353
354                         unsigned element_index = migration_accessed_element_idx + l * migration_names /
355                                                                          migration_labels;
356
357                         // add permission
358                         Name accessed_name;
359                         currentDB.generate_name(element_index, accessed_name);
360                         Label current_label;
361                         currentDB.generate_label(l, current_label);
362                         currentDB.add_permission(accessed_name, current_label, reference_label);
363                 }
364         }
365
366         verifyDBisValid(currentDB);
367 }
368
369 BOOST_AUTO_TEST_SUITE_END()