Release 0.1.65
[platform/core/security/key-manager.git] / common / DBFixture.cpp
1 /*
2  *  Copyright (c) 2016-2020 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        DBFixture.cpp
19  * @author      Maciej Karpiuk (m.karpiuk2@samsung.com)
20  * @version
21  * @brief
22  */
23 #include <boost/test/unit_test.hpp>
24 #include <test_common.h>
25 #include <DBFixture.h>
26 #include <fstream>
27
28 using namespace CKM;
29
30 static void copyFile(const char *src, const char *dst)
31 {
32         std::ifstream f1(src, std::fstream::binary);
33         std::ofstream f2(dst, std::fstream::trunc | std::fstream::binary);
34         f2 << f1.rdbuf();
35         f2.close();
36         f1.close();
37         BOOST_REQUIRE(f1);
38         BOOST_REQUIRE(f2);
39 }
40
41 void DBFixture::unlinkDb()
42 {
43         for (const auto f : {m_crypto_legacy_db_fname, m_crypto_db_fname})
44                 BOOST_REQUIRE_MESSAGE(!unlink(f) || errno == ENOENT, "unlink " << f);
45 }
46
47 DBFixture::DBFixture(DBCryptoThrows dbCryptoThrows)
48 {
49         unlinkDb();
50         init(dbCryptoThrows);
51 }
52 DBFixture::DBFixture(const char *legacy_db_fname, const char *db_fname, DBCryptoThrows dbCryptoThrows)
53 {
54         BOOST_REQUIRE(legacy_db_fname || db_fname);
55         unlinkDb();
56
57         if (legacy_db_fname)
58                 copyFile(legacy_db_fname, m_crypto_legacy_db_fname);
59         if (db_fname)
60                 copyFile(db_fname, m_crypto_db_fname);
61
62         init(dbCryptoThrows);
63 }
64
65 void DBFixture::init(DBCryptoThrows dbCryptoThrows)
66 {
67         switch (dbCryptoThrows) {
68                 case DBCryptoThrows::yes:
69                         BOOST_REQUIRE_THROW(m_db = DB::Crypto(m_crypto_legacy_db_fname, m_crypto_db_fname, defaultPass), Exc::DatabaseFailed);
70                         break;
71                 case DBCryptoThrows::no:
72                         BOOST_REQUIRE_NO_THROW(m_db = DB::Crypto(m_crypto_legacy_db_fname, m_crypto_db_fname, defaultPass));
73                         BOOST_REQUIRE(access(m_crypto_legacy_db_fname, F_OK) && ENOENT == errno);
74         }
75 }
76
77 void DBFixture::generate_name(unsigned int id, Name &output)
78 {
79         std::stringstream ss;
80         ss << "name_no_" << id;
81         output = ss.str();
82 }
83
84 void DBFixture::generate_owner(unsigned int id, ClientId &output)
85 {
86         std::stringstream ss;
87         ss << "label_no_" << id;
88         output = ss.str();
89 }
90
91 void DBFixture::generate_db(unsigned int num_name, unsigned int names_per_owner)
92 {
93         // to speed up data creation - cache the row
94         DB::Row rowPattern = create_default_row(DataType::BINARY_DATA);
95         rowPattern.data = RawBuffer(100, 20);
96         rowPattern.dataSize = rowPattern.data.size();
97         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
98
99         for (unsigned int i = 0; i < num_name; i++) {
100                 generate_name(i, rowPattern.name);
101                 generate_owner(i / names_per_owner, rowPattern.owner);
102
103                 BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
104         }
105 }
106
107 long DBFixture::add_full_access_rights(unsigned int num_name,
108                                                                            unsigned int num_name_per_owner)
109 {
110         long iterations = 0;
111         unsigned int num_owners = num_name / num_name_per_owner;
112         Name name;
113         ClientId owner, accessor;
114
115         for (unsigned int a = 0; a < num_name; a++) {
116                 generate_name(a, name);
117                 generate_owner(a / num_name_per_owner, owner);
118
119                 for (unsigned int l = 0; l < num_owners; l++) {
120                         // bypass the owner
121                         if (l == (a / num_name_per_owner))
122                                 continue;
123
124                         // add permission
125                         generate_owner(l, accessor);
126                         add_permission(name, owner, accessor);
127                         iterations++;
128                 }
129         }
130
131         return iterations;
132 }
133
134 DB::Row DBFixture::create_default_row(DataType type)
135 {
136         return create_default_row(m_default_name, m_default_owner, type);
137 }
138
139 DB::Row DBFixture::create_default_row(const Name &name,
140                                                                           const ClientId &owner,
141                                                                           DataType type)
142 {
143         DB::Row row;
144         row.name = name;
145         row.owner = owner;
146         row.exportable = 1;
147         row.algorithmType = DBCMAlgType::AES_GCM_256;
148         row.dataType = type;
149         row.iv = createDefaultPass();
150         row.encryptionScheme = 0;
151         row.dataSize = 0;
152         row.backendId = CryptoBackend::OpenSSL;
153
154         return row;
155 }
156
157 DB::Row DBFixture::create_default_binary_row()
158 {
159         DB::Row row = create_default_row(m_default_name, m_default_owner, DataType::BINARY_DATA);
160         row.data = RawBuffer(100, 20);
161         row.dataSize = row.data.size();
162         row.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
163
164         return row;
165 }
166
167 void DBFixture::compare_row(const DB::Row &lhs, const DB::Row &rhs)
168 {
169         BOOST_CHECK_MESSAGE(lhs.name == rhs.name,
170                                                 "namees didn't match! Got: " << rhs.name
171                                                 << " , expected : " << lhs.name);
172
173         BOOST_CHECK_MESSAGE(lhs.owner == rhs.owner,
174                                                 "owner didn't match! Got: " << rhs.owner
175                                                 << " , expected : " << lhs.owner);
176
177         BOOST_CHECK_MESSAGE(lhs.exportable == rhs.exportable,
178                                                 "exportable didn't match! Got: " << rhs.exportable
179                                                 << " , expected : " << lhs.exportable);
180
181         BOOST_CHECK_MESSAGE(lhs.iv == rhs.iv,
182                                                 "iv didn't match! Got: " << rhs.iv.size()
183                                                 << " , expected : " << lhs.iv.size());
184
185         BOOST_CHECK_MESSAGE(lhs.data == rhs.data,
186                                                 "data didn't match! Got: " << rhs.data.size()
187                                                 << " , expected : " << lhs.data.size());
188
189         BOOST_CHECK_MESSAGE(lhs.backendId == rhs.backendId,
190                                                 "backendId didn't match! Got: " << static_cast<int>(rhs.backendId)
191                                                 << " , expected : " << static_cast<int>(lhs.backendId));
192 }
193
194 void DBFixture::check_DB_integrity(const DB::Row &rowPattern)
195 {
196         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
197
198         DB::Crypto::RowOptional optional_row;
199         BOOST_REQUIRE_NO_THROW(optional_row = m_db.getRow(m_default_name, m_default_owner,
200                                                                                   DataType::BINARY_DATA));
201         BOOST_REQUIRE_MESSAGE(optional_row, "Select didn't return any row");
202
203         compare_row(*optional_row, rowPattern);
204         DB::Row name_duplicate = rowPattern;
205         name_duplicate.data = createDefaultPass();
206         name_duplicate.dataSize = name_duplicate.data.size();
207
208         unsigned int erased;
209         BOOST_REQUIRE_NO_THROW(erased = m_db.deleteRow(m_default_name, m_default_owner));
210         BOOST_REQUIRE_MESSAGE(erased > 0, "Inserted row didn't exist in db");
211
212         DB::Crypto::RowOptional row_optional;
213         BOOST_REQUIRE_NO_THROW(row_optional = m_db.getRow(m_default_name, m_default_owner,
214                                                                                   DataType::BINARY_DATA));
215         BOOST_REQUIRE_MESSAGE(!row_optional,
216                                                   "Select should not return row after deletion");
217 }
218
219 void DBFixture::insert_row()
220 {
221         insert_row(m_default_name, m_default_owner);
222 }
223
224 void DBFixture::insert_row(const Name &name, const ClientId &owner)
225 {
226         DB::Row rowPattern = create_default_row(name, owner,
227                                                                                         DataType::BINARY_DATA);
228         rowPattern.data = RawBuffer(100, 20);
229         rowPattern.dataSize = rowPattern.data.size();
230         rowPattern.tag = RawBuffer(AES_GCM_TAG_SIZE, 1);
231         BOOST_REQUIRE_NO_THROW(m_db.saveRow(rowPattern));
232 }
233
234 void DBFixture::delete_row(const Name &name, const ClientId &owner)
235 {
236         bool exit_flag=0;
237         BOOST_REQUIRE_NO_THROW(exit_flag = m_db.deleteRow(name, owner));
238         BOOST_REQUIRE_MESSAGE(true == exit_flag, "remove name failed: no rows removed");
239 }
240
241 void DBFixture::add_permission(const Name &name, const ClientId &owner,
242                                                            const ClientId &accessor)
243 {
244         BOOST_REQUIRE_NO_THROW(m_db.setPermission(name,
245                                                    owner,
246                                                    accessor,
247                                                    CKM::Permission::READ | CKM::Permission::REMOVE));
248 }
249
250 void DBFixture::read_row_expect_success(const Name &name,
251                                                                                 const ClientId &owner)
252 {
253         DB::Crypto::RowOptional row;
254         BOOST_REQUIRE_NO_THROW(row = m_db.getRow(name, owner,
255                                                                  DataType::BINARY_DATA));
256         BOOST_REQUIRE_MESSAGE(row, "row is empty");
257         BOOST_REQUIRE_MESSAGE(row->name == name, "name is not valid");
258 }