Release 0.1.66
[platform/core/security/key-manager.git] / unit-tests / test_crypto-logic.cpp
1 /*
2  *  Copyright (c) 2017 - 2021 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 #include <crypto-logic.h>
17 #include <platform/decider.h>
18 #include <generic-backend/gstore.h>
19 #include <db-row.h>
20 #include <base64.h>
21
22 #include <utility>
23 #include <cstdlib>
24 #include <time.h>
25 #include <boost_macros_wrapper.h>
26 #include "test_common.h"
27
28 using namespace CKM;
29
30 namespace {
31
32 constexpr char TEST_CLIENT[] = "test_client";
33 constexpr char TEST_NAME[] = "test_name";
34 constexpr uid_t TEST_UID = 0;
35 const auto TEST_KEY = createRandom(32);
36 const auto TEST_DATA = createRandom(10);
37
38 void changeBase64(RawBuffer& data)
39 {
40         data = base64Decode<RawBuffer>(data);
41         BOOST_REQUIRE(!data.empty());
42
43         ++data[0];
44
45         data = base64Encode<RawBuffer>(data);
46         BOOST_REQUIRE(!data.empty());
47 }
48
49 } // namespace anonymous
50
51 BOOST_AUTO_TEST_SUITE(CRYPTO_LOGIC_TEST)
52
53 POSITIVE_TEST_CASE(move_semantics)
54 {
55         CryptoLogic logic;
56
57         BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
58
59         CryptoLogic moved(std::move(logic));
60         BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
61         BOOST_REQUIRE(moved.haveKey(TEST_CLIENT));
62
63         CryptoLogic moveAssigned = std::move(moved);
64         BOOST_REQUIRE(!moved.haveKey(TEST_CLIENT));
65         BOOST_REQUIRE(moveAssigned.haveKey(TEST_CLIENT));
66 }
67
68 POSITIVE_TEST_CASE(push_have_remove_key)
69 {
70         CryptoLogic logic;
71
72         char client[] = "duck";
73         for (size_t i = 0; i < 20; ++i) {
74                 ++client[0];
75                 BOOST_REQUIRE(!logic.haveKey(client));
76                 BOOST_REQUIRE_NO_THROW(logic.pushKey(client, TEST_KEY));
77                 BOOST_REQUIRE(logic.haveKey(client));
78                 BOOST_REQUIRE_NO_THROW(logic.removeKey(client));
79                 BOOST_REQUIRE(!logic.haveKey(client));
80         }
81 }
82
83 NEGATIVE_TEST_CASE(have_remove_nonexistent_key)
84 {
85         CryptoLogic logic;
86
87         BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
88         BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
89 }
90
91 NEGATIVE_TEST_CASE(have_remove_empty)
92 {
93         CryptoLogic logic;
94
95         BOOST_REQUIRE(!logic.haveKey(""));
96         BOOST_REQUIRE_NO_THROW(logic.removeKey(""));
97 }
98
99 NEGATIVE_TEST_CASE(double_remove_key)
100 {
101         CryptoLogic logic;
102
103         BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
104         BOOST_REQUIRE(logic.haveKey(TEST_CLIENT));
105         BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
106         BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
107         BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
108         BOOST_REQUIRE(!logic.haveKey(TEST_CLIENT));
109 }
110
111 NEGATIVE_TEST_CASE(push_key)
112 {
113         CryptoLogic logic;
114
115         BOOST_REQUIRE_THROW(logic.pushKey("", TEST_KEY), Exc::InternalError);
116         BOOST_REQUIRE_THROW(logic.pushKey(TEST_CLIENT, RawBuffer()), Exc::InternalError);
117
118         char client[] = "duck";
119         for (size_t i = 0; i < 20; ++i) {
120                 ++client[0];
121                 BOOST_REQUIRE(!logic.haveKey(client));
122                 BOOST_REQUIRE_NO_THROW(logic.pushKey(client, TEST_KEY));
123                 BOOST_REQUIRE_THROW(logic.pushKey(client, TEST_KEY), Exc::InternalError);
124                 BOOST_REQUIRE(logic.haveKey(client));
125         }
126 }
127
128 POSITIVE_TEST_CASE(row_encryption)
129 {
130         Policy policy("", true);
131         Crypto::Data data(DataType::BINARY_DATA, TEST_DATA);
132         Crypto::Decider decider;
133         Crypto::GStore &store = decider.getStore(data.type, policy);
134
135         const auto digest = CryptoLogic::makeHash(TEST_NAME, TEST_CLIENT, TEST_UID);
136         BOOST_REQUIRE(!digest.empty());
137
138         Token token = store.import(data, policy.password, Crypto::EncryptionParams(), digest);
139
140         DB::Row row(token, TEST_NAME, TEST_CLIENT, static_cast<int>(policy.extractable));
141
142         CryptoLogic logic;
143
144         DB::Row rowCopy;
145         BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
146         BOOST_REQUIRE_NO_THROW(rowCopy = logic.encryptRow(row));
147         BOOST_REQUIRE(rowCopy.algorithmType == DBCMAlgType::AES_GCM_256);
148         BOOST_REQUIRE(rowCopy.dataSize == static_cast<int>(row.data.size()));
149         BOOST_REQUIRE(!rowCopy.iv.empty());
150         BOOST_REQUIRE(!rowCopy.tag.empty());
151         auto scheme = CryptoLogic::getSchemeVersion(rowCopy.encryptionScheme);
152         BOOST_REQUIRE(scheme == CryptoLogic::ENCRYPTION_V2);
153
154         BOOST_REQUIRE_NO_THROW(logic.decryptRow(policy.password, rowCopy));
155         BOOST_REQUIRE(row.data == rowCopy.data);
156 }
157
158 NEGATIVE_TEST_CASE(row_encryption)
159 {
160         const Policy policy("", true);
161         Crypto::Data data(DataType::BINARY_DATA, TEST_DATA);
162         Crypto::Decider decider;
163         Crypto::GStore &store = decider.getStore(data.type, policy);
164
165         const auto digest = CryptoLogic::makeHash(TEST_NAME, TEST_CLIENT, TEST_UID);
166         BOOST_REQUIRE(!digest.empty());
167
168         Token token = store.import(data, policy.password, Crypto::EncryptionParams(), digest);
169
170         DB::Row row(token, TEST_NAME, TEST_CLIENT, static_cast<int>(policy.extractable));
171
172         CryptoLogic logic;
173
174         // empty row
175         DB::Row emptyRow;
176         BOOST_REQUIRE_THROW(logic.encryptRow(emptyRow), Exc::InternalError);
177
178         // no key
179         BOOST_REQUIRE_THROW(logic.encryptRow(row), Exc::InternalError);
180
181         // short key
182         const auto shortKey = RawBuffer(4);
183         BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, shortKey));
184         BOOST_REQUIRE_THROW(logic.encryptRow(row), Exc::InternalError);
185         BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
186         BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
187
188         // correct encryption
189         DB::Row encryptedRow;
190         BOOST_REQUIRE_NO_THROW(encryptedRow = logic.encryptRow(row));
191
192         // wrong algorithm
193         encryptedRow.algorithmType = DBCMAlgType::NONE;
194         BOOST_REQUIRE_THROW(logic.decryptRow("", encryptedRow), Exc::AuthenticationFailed);
195         encryptedRow.algorithmType = DBCMAlgType::AES_GCM_256;
196
197         // unnecessary password
198         BOOST_REQUIRE_THROW(logic.decryptRow("unnecessary password", encryptedRow),
199                                                 Exc::AuthenticationFailed);
200
201         // no key
202         BOOST_REQUIRE_NO_THROW(logic.removeKey(TEST_CLIENT));
203         BOOST_REQUIRE_THROW(logic.decryptRow("", encryptedRow), Exc::AuthenticationFailed);
204         BOOST_REQUIRE_NO_THROW(logic.pushKey(TEST_CLIENT, TEST_KEY));
205
206         // wrong owner
207         ++encryptedRow.owner[0];
208         BOOST_REQUIRE_THROW(logic.decryptRow("", encryptedRow), Exc::AuthenticationFailed);
209         --encryptedRow.owner[0];
210
211         // no iv
212         auto rowCopy = encryptedRow;
213         rowCopy.iv.clear();
214         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError);
215
216         // wrong iv (not base64)
217         rowCopy = encryptedRow;
218         rowCopy.iv[0] = 64;
219         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError);
220
221         // wrong iv
222         rowCopy = encryptedRow;
223         changeBase64(rowCopy.iv);
224         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
225
226         // no ciphertext
227         rowCopy = encryptedRow;
228         rowCopy.data.clear();
229         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy),Exc::InternalError);
230
231         // wrong ciphertext (not base64)
232         rowCopy = encryptedRow;
233         rowCopy.data[0] = 64;
234         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::InternalError);
235
236         // wrong ciphertext
237         rowCopy = encryptedRow;
238         changeBase64(rowCopy.data);
239         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
240
241         // wrong tag
242         rowCopy = encryptedRow;
243         ++rowCopy.tag[0];
244         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
245
246         // wrong dataSize
247         rowCopy = encryptedRow;
248         ++rowCopy.dataSize;
249         BOOST_REQUIRE_THROW(logic.decryptRow("", rowCopy), Exc::AuthenticationFailed);
250 }
251
252 BOOST_AUTO_TEST_SUITE_END() // CRYPTO_LOGIC_TEST