tizen 2.4 release
[framework/security/key-manager.git] / tests / test_db_crypto.cpp
1 #include <boost/test/unit_test.hpp>
2 #include <unistd.h>
3 #include <db-crypto.h>
4 #include <iostream>
5 #include <ckm/ckm-type.h>
6 #include <ckm/ckm-error.h>
7 #include <errno.h>
8 #include <test_common.h>
9 #include <DBFixture.h>
10
11 using namespace CKM;
12
13 namespace
14 {
15 const int restricted_local = 1;
16 const int restricted_global = 0;
17
18 const unsigned int c_test_retries = 1000;
19 const unsigned int c_num_names = 500;
20 const unsigned int c_num_names_add_test = 5000;
21 const unsigned int c_names_per_label = 15;
22
23 int getRandom()
24 {
25     int randVal;
26
27     FILE *fp = fopen("/dev/urandom", "r");
28     if (fp == NULL) {
29         std::cerr << "err to open /dev/urandom" << std::endl;
30         return -1;
31     }
32
33     if (1 != fread(&randVal, sizeof(randVal), 1, fp)) {
34         std::cerr << "err to fread /dev/urandom" << std::endl;
35         randVal = -1;
36     }
37
38     fclose(fp);
39
40     return randVal;
41 }
42
43 } // namespace anonymous
44
45 BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_TEST, DBFixture)
46 BOOST_AUTO_TEST_CASE(DBtestSimple) {
47     DB::Row rowPattern = create_default_row();
48     rowPattern.data = RawBuffer(32, 1);
49     rowPattern.dataSize = rowPattern.data.size();
50     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
51
52     check_DB_integrity(rowPattern);
53 }
54 BOOST_AUTO_TEST_CASE(DBtestBIG) {
55     DB::Row rowPattern = create_default_row();
56     rowPattern.data = createBigBlob(4096);
57     rowPattern.dataSize = rowPattern.data.size();
58     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
59
60     check_DB_integrity(rowPattern);
61 }
62 BOOST_AUTO_TEST_CASE(DBtestGlobal) {
63     DB::Row rowPattern = create_default_row();
64     rowPattern.data = RawBuffer(1024, 2);
65     rowPattern.dataSize = rowPattern.data.size();
66     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
67
68     BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
69
70     DB::Row name_duplicate = rowPattern;
71     rowPattern.ownerLabel = rowPattern.ownerLabel + "1";
72 }
73 BOOST_AUTO_TEST_CASE(DBtestTransaction) {
74     DB::Row rowPattern = create_default_row();
75     rowPattern.data = RawBuffer(100, 20);
76     rowPattern.dataSize = rowPattern.data.size();
77     rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
78     DB::Crypto::Transaction transaction(&m_db);
79
80     BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
81     BOOST_REQUIRE_NO_THROW(transaction.rollback());
82
83     DB::Crypto::RowOptional row_optional;
84     BOOST_REQUIRE_NO_THROW(row_optional = m_db.getRow(m_default_name, m_default_label,
85                                                       DataType::BINARY_DATA));
86     BOOST_CHECK_MESSAGE(!row_optional, "Row still present after rollback");
87 }
88
89 BOOST_AUTO_TEST_SUITE_END()
90
91
92
93 BOOST_FIXTURE_TEST_SUITE(DBCRYPTO_PERF_TEST, DBFixture)
94
95 BOOST_AUTO_TEST_CASE(DBperfAddNames)
96 {
97     // actual test
98     performance_start("saveRow");
99     {
100         generate_perf_DB(c_num_names_add_test, c_names_per_label);
101     }
102     performance_stop(c_num_names_add_test);
103 }
104
105 BOOST_AUTO_TEST_CASE(DBperfLookupAliasByOwner)
106 {
107     // prepare data
108     generate_perf_DB(c_num_names, c_names_per_label);
109
110     unsigned int num_labels = c_num_names/c_names_per_label;
111     Name name;
112     Label label;
113
114     // actual test - successful lookup
115     performance_start("getRow");
116     for(unsigned int t=0; t<c_test_retries; t++)
117     {
118         int label_num = getRandom() % num_labels;
119         generate_label(label_num, label);
120
121         unsigned int start_name = label_num*c_names_per_label;
122         for(unsigned int name_num=start_name; name_num<(start_name+c_names_per_label); name_num++)
123         {
124             generate_name(name_num, name);
125             read_row_expect_success(name, label);
126         }
127     }
128     performance_stop(c_test_retries * c_num_names);
129 }
130
131 BOOST_AUTO_TEST_CASE(DBperfLookupAliasRandomOwnershipNoPermissions)
132 {
133     // prepare data
134     generate_perf_DB(c_num_names, c_names_per_label);
135
136     Name name;
137     Label owner_label;
138     Label smack_label;
139     unsigned int num_labels = c_num_names / c_names_per_label;
140
141     // actual test - random lookup
142     performance_start("getRow");
143     for(unsigned int t=0; t<c_test_retries; t++)
144     {
145         int name_idx = getRandom()%c_num_names;
146         generate_name(name_idx, name);
147         generate_label(name_idx/c_names_per_label, owner_label);
148         generate_label(getRandom()%num_labels, smack_label);
149
150         // do not care of result
151         m_db.getRow(name, owner_label, DataType::BINARY_DATA);
152     }
153     performance_stop(c_test_retries * c_num_names);
154 }
155
156 BOOST_AUTO_TEST_CASE(DBperfAddPermissions)
157 {
158     // prepare data
159     generate_perf_DB(c_num_names, c_names_per_label);
160
161     // actual test - add access rights
162     performance_start("setPermission");
163     long iterations = add_full_access_rights(c_num_names, c_names_per_label);
164     performance_stop(iterations);
165 }
166
167 BOOST_AUTO_TEST_CASE(DBperfAliasRemoval)
168 {
169     // prepare data
170     generate_perf_DB(c_num_names, c_names_per_label);
171     add_full_access_rights(c_num_names, c_names_per_label);
172
173     // actual test - random lookup
174     performance_start("deleteRow");
175     Name name;
176     Label label;
177     for(unsigned int t=0; t<c_num_names; t++)
178     {
179         generate_name(t, name);
180         generate_label(t/c_names_per_label, label);
181
182         BOOST_REQUIRE_NO_THROW(m_db.deleteRow(name, label));
183     }
184     performance_stop(c_num_names);
185
186     // verify everything has been removed
187     unsigned int num_labels = c_num_names / c_names_per_label;
188     for(unsigned int l=0; l<num_labels; l++)
189     {
190         generate_label(l, label);
191         LabelNameVector expect_no_data;
192         BOOST_REQUIRE_NO_THROW(m_db.listNames(label, expect_no_data, DataType::BINARY_DATA));
193         BOOST_REQUIRE(0 == expect_no_data.size());
194     }
195 }
196
197 BOOST_AUTO_TEST_CASE(DBperfGetAliasList)
198 {
199     // prepare data
200     generate_perf_DB(c_num_names, c_names_per_label);
201     add_full_access_rights(c_num_names, c_names_per_label);
202
203     unsigned int num_labels = c_num_names / c_names_per_label;
204     Label label;
205
206     // actual test - random lookup
207     performance_start("listNames");
208     for(unsigned int t=0; t<(c_test_retries/num_labels); t++)
209     {
210         LabelNameVector ret_list;
211         generate_label(getRandom()%num_labels, label);
212
213         BOOST_REQUIRE_NO_THROW(m_db.listNames(label, ret_list, DataType::BINARY_DATA));
214         BOOST_REQUIRE(c_num_names == ret_list.size());
215         ret_list.clear();
216     }
217     performance_stop(c_test_retries/num_labels);
218 }
219 BOOST_AUTO_TEST_SUITE_END()
220
221
222 BOOST_AUTO_TEST_SUITE(DBCRYPTO_MIGRATION_TEST)
223 namespace
224 {
225 const unsigned migration_names = 16107;
226 const unsigned migration_labels = 273;
227 const unsigned migration_reference_label_idx = 0;
228 const unsigned migration_accessed_element_idx = 7;
229
230 void verifyDBisValid(DBFixture & fixture)
231 {
232     /**
233      * there are (migration_labels), each having (migration_names)/(migration_labels) entries.
234      * reference label (migration_reference_label_idx) exists such that it has access to
235      * all others' label element with index (migration_accessed_element_idx).
236      *
237      * Example:
238      * - migration_label_63 has access to all items owned by migration_label_63,
239      *   which gives (migration_names)/(migration_labels) entries.
240      *
241      * - migration_label_0 (0 is the reference label) has access to all items
242      *   owned by migration_label_0 and all others' label element index 7,
243      *   which gives (migration_names)/(migration_labels)  + (migration_labels-1) entries.
244      *
245      */
246     Label reference_label;
247     fixture.generate_label(migration_reference_label_idx, reference_label);
248
249     // check number of elements accessible to the reference label
250     LabelNameVector ret_list;
251     BOOST_REQUIRE_NO_THROW(fixture.m_db.listNames(reference_label, ret_list, DataType::BINARY_DATA));
252     BOOST_REQUIRE((migration_names/migration_labels)/*own items*/ + (migration_labels-1)/*other labels'*/ == ret_list.size());
253     ret_list.clear();
254
255     // check number of elements accessible to the other labels
256     for(unsigned int l=0; l<migration_labels; l++)
257     {
258         // bypass the reference owner label
259         if(l == migration_reference_label_idx)
260             continue;
261
262         Label current_label;
263         fixture.generate_label(l, current_label);
264         BOOST_REQUIRE_NO_THROW(fixture.m_db.listNames(current_label, ret_list, DataType::BINARY_DATA));
265         BOOST_REQUIRE((migration_names/migration_labels) == ret_list.size());
266         for(auto it: ret_list)
267             BOOST_REQUIRE(it.first == current_label);
268         ret_list.clear();
269     }
270 }
271 struct DBVer1Migration : public DBFixture
272 {
273     DBVer1Migration() : DBFixture("/usr/share/ckm-db-test/testme_ver1.db")
274     {}
275 };
276
277 struct DBVer2Migration : public DBFixture
278 {
279     DBVer2Migration() : DBFixture("/usr/share/ckm-db-test/testme_ver2.db")
280     {}
281 };
282 }
283
284 BOOST_AUTO_TEST_CASE(DBMigrationDBVer1)
285 {
286     DBVer1Migration DBver1;
287     verifyDBisValid(DBver1);
288 }
289
290 BOOST_AUTO_TEST_CASE(DBMigrationDBVer2)
291 {
292     DBVer2Migration DBver2;
293     verifyDBisValid(DBver2);
294 }
295
296 BOOST_AUTO_TEST_CASE(DBMigrationDBCurrent)
297 {
298     DBFixture currentDB;
299
300     // prepare data using current DB mechanism
301     Label reference_label;
302     currentDB.generate_label(migration_reference_label_idx, reference_label);
303     {
304         currentDB.generate_perf_DB(migration_names, migration_names/migration_labels);
305
306         // only the reference label has access to the other labels element <migration_accessed_element_idx>
307         for(unsigned int l=0; l<migration_labels; l++)
308         {
309             // bypass the reference owner label
310             if(l == migration_reference_label_idx)
311                 continue;
312
313             unsigned element_index = migration_accessed_element_idx + l*migration_names/migration_labels;
314
315             // add permission
316             Name accessed_name;
317             currentDB.generate_name(element_index, accessed_name);
318             Label current_label;
319             currentDB.generate_label(l, current_label);
320             currentDB.add_permission(accessed_name, current_label, reference_label);
321         }
322     }
323
324     verifyDBisValid(currentDB);
325 }
326
327 BOOST_AUTO_TEST_SUITE_END()