fix the bugs for unit-test
[platform/core/security/key-manager.git] / tests / encryption-scheme / scheme-test.cpp
1 /*
2  *  Copyright (c) 2015-2020 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 /*
17  * @file       scheme-test.cpp
18  * @author     Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
19  * @version    1.0
20  */
21 #include <scheme-test.h>
22
23 #include <sys/smack.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/sendfile.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <grp.h>
31 #include <pwd.h>
32
33 #include <fstream>
34 #include <stdexcept>
35 #include <vector>
36
37 #include <boost/test/unit_test.hpp>
38
39 #include <smack-access.h>
40
41 #include <db-crypto.h>
42 #include <file-system.h>
43 #include <key-provider.h>
44 #include <db-row.h>
45 #include <crypto-init.h>
46 #include <dpl/errno_string.h>
47
48 using namespace CKM;
49 using namespace std;
50
51 namespace {
52 const uid_t UID = 7654;
53 const gid_t GID = 7654;
54 const char *const DBPASS = "db-pass";
55 const char *const LABEL = "my-label";
56 const ClientId OWNER = "/" + string(LABEL);
57 const int ENC_SCHEME_OFFSET = 24;
58 const string TEST_DATA_STR = "test-data";
59 RawBuffer TEST_DATA(TEST_DATA_STR.begin(), TEST_DATA_STR.end());
60 const Password TEST_PASS = "custom user password";
61 const size_t IV_LEN = 16;
62 const size_t CHAIN_LEN = 3;
63 const mode_t MODE_0644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
64
65 enum {
66         NO_PASS = 0,
67         PASS = 1
68 };
69
70 enum {
71         NO_EXP = 0,
72         EXP = 1
73 };
74
75 // [password][exportable]
76 Policy policy[2][2] = {
77         {{ Password(), false }, { Password(), true }},
78         {{ TEST_PASS,  false }, { TEST_PASS,  true }},
79 };
80
81 struct Group {
82         enum {
83                 SINGLE_ITEM,
84                 KEY_PAIR_RSA,
85                 CERT_CHAIN
86         } type;
87         Items items;
88 };
89
90 Group GROUPS[] = {
91         // Data
92         {
93                 Group::SINGLE_ITEM, {
94                         Item("data-alias1", DataType::BINARY_DATA,  policy[NO_PASS][EXP])
95                 }
96         },
97         {
98                 Group::SINGLE_ITEM, {
99                         Item("data-alias2", DataType::BINARY_DATA,  policy[PASS][EXP])
100                 }
101         },
102
103         // RSA keys
104         {
105                 Group::KEY_PAIR_RSA, {
106                         Item("key-rsa-alias-prv1", DataType::KEY_RSA_PRIVATE,  policy[NO_PASS][NO_EXP]),
107                         Item("key-rsa-alias-pub1", DataType::KEY_RSA_PUBLIC,   policy[NO_PASS][NO_EXP])
108                 }
109         },
110         {
111                 Group::KEY_PAIR_RSA, {
112                         Item("key-rsa-alias-prv2", DataType::KEY_RSA_PRIVATE,  policy[NO_PASS][EXP]),
113                         Item("key-rsa-alias-pub2", DataType::KEY_RSA_PUBLIC,   policy[NO_PASS][EXP]),
114                 }
115         },
116         {
117                 Group::KEY_PAIR_RSA, {
118                         Item("key-rsa-alias-prv3", DataType::KEY_RSA_PRIVATE,  policy[PASS][NO_EXP]),
119                         Item("key-rsa-alias-pub3", DataType::KEY_RSA_PUBLIC,   policy[PASS][NO_EXP]),
120                 }
121         },
122         {
123                 Group::KEY_PAIR_RSA, {
124                         Item("key-rsa-alias-prv4", DataType::KEY_RSA_PRIVATE,  policy[PASS][EXP]),
125                         Item("key-rsa-alias-pub4", DataType::KEY_RSA_PUBLIC,   policy[PASS][EXP]),
126                 }
127         },
128         // different policies
129         {
130                 Group::KEY_PAIR_RSA, {
131                         Item("key-rsa-alias-prv5", DataType::KEY_RSA_PRIVATE,  policy[PASS][NO_EXP]),
132                         Item("key-rsa-alias-pub5", DataType::KEY_RSA_PUBLIC,   policy[NO_PASS][EXP]),
133                 }
134         },
135
136         // AES
137         {
138                 Group::SINGLE_ITEM, {
139                         Item("key-aes-alias1",     DataType::KEY_AES,          policy[NO_PASS][NO_EXP]),
140                 }
141         },
142         {
143                 Group::SINGLE_ITEM, {
144                         Item("key-aes-alias2",     DataType::KEY_AES,          policy[NO_PASS][EXP]),
145                 }
146         },
147         {
148                 Group::SINGLE_ITEM, {
149                         Item("key-aes-alias3",     DataType::KEY_AES,          policy[PASS][NO_EXP]),
150                 }
151         },
152         {
153                 Group::SINGLE_ITEM, {
154                         Item("key-aes-alias4",     DataType::KEY_AES,          policy[PASS][EXP]),
155                 }
156         },
157
158         // Certificates
159         {
160                 Group::CERT_CHAIN, {
161                         Item("cert-root-alias1",   DataType::CERTIFICATE,      policy[NO_PASS][NO_EXP]),
162                         Item("cert-im-ca-alias1",  DataType::CERTIFICATE,      policy[NO_PASS][NO_EXP]),
163                         Item("cert-leaf-alias1",   DataType::CERTIFICATE,      policy[NO_PASS][NO_EXP]),
164                 }
165         },
166         {
167                 Group::CERT_CHAIN, {
168                         Item("cert-root-alias2",   DataType::CERTIFICATE,      policy[NO_PASS][EXP]),
169                         Item("cert-im-ca-alias2",  DataType::CERTIFICATE,      policy[NO_PASS][EXP]),
170                         Item("cert-leaf-alias2",   DataType::CERTIFICATE,      policy[NO_PASS][EXP]),
171                 }
172         },
173         {
174                 Group::CERT_CHAIN, {
175                         Item("cert-root-alias3",   DataType::CERTIFICATE,      policy[PASS][NO_EXP]),
176                         Item("cert-im-ca-alias3",  DataType::CERTIFICATE,      policy[PASS][NO_EXP]),
177                         Item("cert-leaf-alias3",   DataType::CERTIFICATE,      policy[PASS][NO_EXP]),
178                 }
179         },
180         {
181                 Group::CERT_CHAIN, {
182                         Item("cert-root-alias4",   DataType::CERTIFICATE,      policy[PASS][EXP]),
183                         Item("cert-im-ca-alias4",  DataType::CERTIFICATE,      policy[PASS][EXP]),
184                         Item("cert-leaf-alias4",   DataType::CERTIFICATE,      policy[PASS][EXP]),
185                 }
186         },
187
188         // PKCS
189         {
190                 Group::SINGLE_ITEM, {
191                         Item("pkcs-alias1",        DataType::CHAIN_CERT_0,     policy[NO_PASS][NO_EXP]),
192                 }
193         },
194         {
195                 Group::SINGLE_ITEM, {
196                         Item("pkcs-alias2",        DataType::CHAIN_CERT_0,     policy[NO_PASS][EXP]),
197                 }
198         },
199         {
200                 Group::SINGLE_ITEM, {
201                         Item("pkcs-alias3",        DataType::CHAIN_CERT_0,     policy[PASS][NO_EXP]),
202                 }
203         },
204         {
205                 Group::SINGLE_ITEM, {
206                         Item("pkcs-alias4",        DataType::CHAIN_CERT_0,     policy[PASS][EXP]),
207                 }
208         },
209 };
210
211 const size_t CHAIN_SIZE = 3;
212
213 // TEST_ROOT_CA, expires 2035
214 std::string TEST_ROOT_CA =
215         "-----BEGIN CERTIFICATE-----\n"
216         "MIIDnzCCAoegAwIBAgIJAMH/ADkC5YSTMA0GCSqGSIb3DQEBBQUAMGYxCzAJBgNV\n"
217         "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDARBQ01FMRAwDgYD\n"
218         "VQQLDAdUZXN0aW5nMSEwHwYDVQQDDBhUZXN0IHJvb3QgY2EgY2VydGlmaWNhdGUw\n"
219         "HhcNMTQxMjMwMTcyMTUyWhcNMjQxMjI3MTcyMTUyWjBmMQswCQYDVQQGEwJBVTET\n"
220         "MBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UECgwEQUNNRTEQMA4GA1UECwwHVGVz\n"
221         "dGluZzEhMB8GA1UEAwwYVGVzdCByb290IGNhIGNlcnRpZmljYXRlMIIBIjANBgkq\n"
222         "hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0EJRdUtd2th0vTVF7QxvDKzyFCF3w9vC\n"
223         "9IDE/Yr12w+a9jd0s7/eG96qTHIYffS3B7x2MB+d4n+SR3W0qmYh7xk8qfEgH3da\n"
224         "eDoV59IZ9r543KM+g8jm6KffYGX1bIJVVY5OhBRbO9nY6byYpd5kbCIUB6dCf7/W\n"
225         "rQl1aIdLGFIegAzPGFPXDcU6F192686x54bxt/itMX4agHJ9ZC/rrTBIZghVsjJo\n"
226         "5/AH5WZpasv8sfrGiiohAxtieoYoJkv5MOYP4/2lPlOY+Cgw1Yoz+HHv31AllgFs\n"
227         "BquBb/kJVmCCNsAOcnvQzTZUsW/TXz9G2nwRdqI1nSy2JvVjZGsqGQIDAQABo1Aw\n"
228         "TjAdBgNVHQ4EFgQUt6pkzFt1PZlfYRL/HGnufF4frdwwHwYDVR0jBBgwFoAUt6pk\n"
229         "zFt1PZlfYRL/HGnufF4frdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC\n"
230         "AQEAld7Qwq0cdzDQ51w1RVLwTR8Oy25PB3rzwEHcSGJmdqlMi3xOdaz80S1R1BBX\n"
231         "ldvGBG5Tn0vT7xSuhmSgI2/HnBpy9ocHVOmhtNB4473NieEpfTYrnGXrFxu46Wus\n"
232         "9m/ZnugcQ2G6C54A/NFtvgLmaC8uH8M7gKdS6uYUwJFQEofkjmd4UpOYSqmcRXhS\n"
233         "Jzd5FYFWkJhKJYp3nlENSOD8CUFFVGekm05nFN2gRVc/qaqQkEX77+XYvhodLRsV\n"
234         "qMn7nf7taidDKLO2T4bhujztnTYOhhaXKgPy7AtZ28N2wvX96VyAPB/vrchGmyBK\n"
235         "kOg11TpPdNDkhb1J4ZCh2gupDg==\n"
236         "-----END CERTIFICATE-----\n";
237
238 // TEST_IM_CA, signed by TEST_ROOT_CA, expires 2035
239 std::string TEST_IM_CA =
240         "-----BEGIN CERTIFICATE-----\n"
241         "MIIDljCCAn6gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwZjELMAkGA1UEBhMCQVUx\n"
242         "EzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoMBEFDTUUxEDAOBgNVBAsMB1Rl\n"
243         "c3RpbmcxITAfBgNVBAMMGFRlc3Qgcm9vdCBjYSBjZXJ0aWZpY2F0ZTAeFw0xNTAx\n"
244         "MTYxNjQ1MzRaFw0zNTAxMTExNjQ1MzRaMGQxCzAJBgNVBAYTAkFVMRMwEQYDVQQI\n"
245         "DApTb21lLVN0YXRlMQ0wCwYDVQQKDARBQ01FMRAwDgYDVQQLDAdUZXN0aW5nMR8w\n"
246         "HQYDVQQDDBZUZXN0IElNIENBIGNlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEF\n"
247         "AAOCAQ8AMIIBCgKCAQEAzmBF78qClgoKfnLAncMXZwZ14TW+5kags1+QCYeg3c7j\n"
248         "L9+RvDxIaX2tKf1sukJcwQfYqUlQkwt+58LMOb2ORtkpj8Or6WCWCZ0BzneT8ug7\n"
249         "nxJT4m9+bohMF0JoKjjB2H4KNMHamLIwUxRKt6nyfk81kVhJOi2vzzxd+UCPi6Pc\n"
250         "UAbJNH48eNgOIg55nyFovVzYj8GIo/9GvHJj83PPa/KlJZ+Z1qZASZZ/VYorplVT\n"
251         "thsHXKfejhFy5YJ9t7n/vyAQsyBsagZsvX19xnH41fbYXHKf8UbXG23rNaZlchs6\n"
252         "XJVLQdzOpj3WTj/lCocVHqLaZISLhNQ3aI7kUBUdiwIDAQABo1AwTjAdBgNVHQ4E\n"
253         "FgQUoCYNaCBP4jl/3SYQuK8Ka+6i3QEwHwYDVR0jBBgwFoAUt6pkzFt1PZlfYRL/\n"
254         "HGnufF4frdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjRzWiD97\n"
255         "Htv4Kxpm3P+C+xP9AEteCJfO+7p8MWgtWEJOknJyt55zeKS2JwZIq57KcbqD8U7v\n"
256         "vAUx1ymtUhlFPFd7J1mJ3pou+3aFYmGShYhGHpbrmUwjp7HVP588jrW1NoZVHdMc\n"
257         "4OgJWFrViXeu9+maIcekjMB/+9Y0dUgQuK5ZuT5H/Jwet7Th/o9uufTUZjBzRvrB\n"
258         "pbXgQpqgME2av4Q/6LuldPCTHLtWXgFUU2R+yCGmuGilvhFJnKoQryAbYnIQNWE8\n"
259         "SLoHQ9s1i7Zyb7HU6UAaqMOz15LBkyAqtNyJcO2p7Q/p5YK0xfD4xisI5qXucqVm\n"
260         "F2obL5qJSTN/RQ==\n"
261         "-----END CERTIFICATE-----\n";
262
263 // TEST_LEAF, signed by TEST_IM_CA, expires 2035
264 std::string TEST_LEAF =
265         "-----BEGIN CERTIFICATE-----\n"
266         "MIIDOzCCAiMCAQEwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCQVUxEzARBgNV\n"
267         "BAgMClNvbWUtU3RhdGUxDTALBgNVBAoMBEFDTUUxEDAOBgNVBAsMB1Rlc3Rpbmcx\n"
268         "HzAdBgNVBAMMFlRlc3QgSU0gQ0EgY2VydGlmaWNhdGUwHhcNMTUwMTE2MTY0ODE0\n"
269         "WhcNMzUwMTExMTY0ODE0WjBjMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1T\n"
270         "dGF0ZTENMAsGA1UECgwEQUNNRTEQMA4GA1UECwwHVGVzdGluZzEeMBwGA1UEAwwV\n"
271         "VGVzdCBsZWFmIGNlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"
272         "CgKCAQEAzTdDIa2tDmRxFnIgiG+mBz8GoSVODs0ImNQGbqj+pLhBOFRH8fsah4Jl\n"
273         "z5YF9KwhMVLknnHGFLE/Nb7Ac35kEzhMQMpTRxohW83oxw3eZ8zN/FBoKqg4qHRq\n"
274         "QR8kS10YXTgrBR0ex/Vp+OUKEw6h7yL2r4Tpvrn9/qHwsxtLxqWbDIVf1O9b1Lfc\n"
275         "bllYMdmV5E62yN5tcwrDP8gvHjFnVeLzrG8wTpc9FR90/0Jkfp5jAJcArOBLrT0E\n"
276         "4VRqs+4HuwT8jAwFAmNnc7IYX5qSjtSWkmmHe73K/lzB+OiI0JEc/3eWUTWqwTSk\n"
277         "4tNCiQGBKJ39LXPTBBJdzmxVH7CUDQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAp\n"
278         "UdDOGu3hNiG+Vn10aQ6B1ZmOj3t+45gUV3sC+y8hB8EK1g4P5Ke9bVDts0T5eOnj\n"
279         "CSc+6VoND5O4adI0IFFRFljHNVnvjeosHfUZNnowsmA2ptQBtC1g5ZKRvKXlkC5/\n"
280         "i5BGgRqPFA7y9WB9Y05MrJHf3E+Oz/RBsLeeNiNN+rF5X1vYExvGHpo0M0zS0ze9\n"
281         "HtC0aOy8ocsTrQkf3ceHTAXx2i8ftoSSD4klojtWFpWMrNQa52F7wB9nU6FfKRuF\n"
282         "Zj/T1JkYXKkEwZU6nAR2jdZp3EP9xj3o15V/tyFcXHx6l8NTxn4cJb+Xe4VquQJz\n"
283         "6ON7PVe0ABN/AlwVQiFE\n"
284         "-----END CERTIFICATE-----\n";
285
286
287
288 struct FdCloser {
289         void operator()(int *fd)
290         {
291                 if (fd)
292                         close(*fd);
293         }
294 };
295
296 typedef std::unique_ptr<int, FdCloser> FdPtr;
297
298 uid_t getUid(const char *name)
299 {
300         struct passwd pwd;
301         struct passwd *result = nullptr;
302         int bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
303
304         if (bufsize <= 0)
305                 bufsize = 16384; /* should be more than enough */
306
307         memset(&pwd, 0x00, sizeof(pwd));
308
309         std::vector<char> buf(bufsize, 0);
310
311         int ret = getpwnam_r(name, &pwd, buf.data(), bufsize, &result);
312         BOOST_REQUIRE_MESSAGE(ret == 0 && result, "getpwnam_r failed");
313
314         return pwd.pw_uid;
315 }
316
317 gid_t getGid(const char *name)
318 {
319         struct group grp;
320         struct group *result = nullptr;
321         size_t bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
322
323         if (bufsize <= 0)
324                 bufsize = 16384; /* should be more than enough */
325
326         memset(&grp, 0x00, sizeof(grp));
327
328         std::vector<char> buf(bufsize, 0);
329
330         int ret = getgrnam_r(name, &grp, buf.data(), bufsize, &result);
331         BOOST_REQUIRE_MESSAGE(ret == 0 && result, "getgrnam_r failed");
332
333         return grp.gr_gid;
334 }
335
336 void restoreFile(const string &filename)
337 {
338         static uid_t CKM_UID = getUid(USER_NAME);
339         static gid_t CKM_GID = getGid(GROUP_NAME);
340         string sourcePath = string(DB_TEST_DIR) + "/" + filename;
341         string targetPath = string(RW_DATA_DIR) + "/" + filename;
342
343         int err, ret;
344
345         int sourceFd = TEMP_FAILURE_RETRY(open(sourcePath.c_str(), O_RDONLY));
346         err = errno;
347         BOOST_REQUIRE_MESSAGE(sourceFd > 0,
348                                                   "Opening " << sourcePath << " failed: " << GetErrnoString(err));
349
350         FdPtr sourceFdPtr(&sourceFd);
351
352         int targetFd = TEMP_FAILURE_RETRY(creat(targetPath.c_str(), MODE_0644));
353         err = errno;
354         BOOST_REQUIRE_MESSAGE(targetFd > 0,
355                                                   "Creating " << targetPath << " failed: " << GetErrnoString(err));
356
357         ret = fchown(targetFd, CKM_UID, CKM_GID);
358         err = errno;
359         BOOST_REQUIRE_MESSAGE(ret != -1, "fchown() failed: " << GetErrnoString(err));
360
361         FdPtr targetFdPtr(&targetFd);
362
363         struct stat sourceStat;
364         ret = fstat(sourceFd, &sourceStat);
365         err = errno;
366         BOOST_REQUIRE_MESSAGE(ret != -1, "fstat() failed: " << GetErrnoString(err));
367
368         ret = sendfile(targetFd, sourceFd, 0, sourceStat.st_size);
369         err = errno;
370         BOOST_REQUIRE_MESSAGE(ret != -1, "sendfile() failed: " << GetErrnoString(err));
371
372         ret = fsync(targetFd);
373         err = errno;
374         BOOST_REQUIRE_MESSAGE(ret != -1, "fsync() failed: " << GetErrnoString(err));
375 }
376
377 void generateRandom(size_t random_bytes, unsigned char *output)
378 {
379         if (random_bytes <= 0 || !output)
380                 throw runtime_error("Invalid param");
381
382         std::ifstream is("/dev/urandom", std::ifstream::binary);
383
384         if (!is)
385                 throw runtime_error("Failed to read /dev/urandom");
386
387         is.read(reinterpret_cast<char *>(output), random_bytes);
388
389         if (static_cast<std::streamsize>(random_bytes) != is.gcount())
390                 throw runtime_error("Not enough bytes read from /dev/urandom");
391 }
392
393 RawBuffer createRandomBuffer(size_t random_bytes)
394 {
395         RawBuffer buffer(random_bytes);
396         generateRandom(buffer.size(), buffer.data());
397         return buffer;
398 }
399 } // namespace anonymous
400
401
402 SchemeTest::SchemeTest() : m_userChanged(false), m_directAccessEnabled(false)
403 {
404         m_control = Control::create();
405         m_mgr = Manager::create();
406         initOpenSsl();
407
408         SmackAccess sa;
409         sa.add("System", LABEL, "rwx");
410         sa.add(LABEL, "System", "rwx");
411         sa.add(LABEL, "System::Run", "x");
412         sa.apply();
413 }
414
415 SchemeTest::~SchemeTest()
416 {
417         try {
418                 SwitchToRoot();
419         } catch (...) {}
420 }
421
422 void SchemeTest::RemoveUserData()
423 {
424         if (CKM_API_SUCCESS != m_control->lockUserKey(UID))
425                 throw runtime_error("lockUserKey failed");
426
427         if (CKM_API_SUCCESS != m_control->removeUserData(UID))
428                 throw runtime_error("removeUserData failed");
429 }
430
431 void SchemeTest::SwitchToUser()
432 {
433         if (m_userChanged)
434                 return;
435
436         if (CKM_API_SUCCESS != m_control->unlockUserKey(UID, DBPASS))
437                 throw runtime_error("unlockUserKey failed");
438
439         // get calling label
440         char *label = NULL;
441
442         if (smack_new_label_from_self(&label) <= 0)
443                 throw runtime_error("smack_new_label_from_self failed");
444
445         m_origLabel = string(label);
446         free(label);
447
448         if (0 > smack_set_label_for_self(LABEL))
449                 throw runtime_error("smack_set_label_for_self failed");
450
451         if (0 > setegid(GID))
452                 throw runtime_error("setegid failed");
453
454         if (0 > seteuid(UID))
455                 throw runtime_error("seteuid failed");
456
457         m_userChanged = true;
458 }
459
460 void SchemeTest::SwitchToRoot()
461 {
462         if (!m_userChanged)
463                 return;
464
465         if (0 > seteuid(0))
466                 throw runtime_error("seteuid failed");
467
468         if (0 > setegid(0))
469                 throw runtime_error("setegid failed");
470
471         if (0 > smack_set_label_for_self(m_origLabel.c_str()))
472                 throw runtime_error("smack_set_label_for_self failed");
473
474         if (m_control->lockUserKey(UID) != CKM_API_SUCCESS)
475                 throw runtime_error("lockUserKey failed");
476 }
477
478 void SchemeTest::FillDb()
479 {
480         // pkcs
481         ifstream is(DB_TEST_DIR "/encryption-scheme.p12");
482
483         if (!is)
484                 throw runtime_error("Failed to read pkcs");
485
486         istreambuf_iterator<char> begin(is), end;
487         RawBuffer pkcsBuffer(begin, end);
488         auto pkcs = PKCS12::create(pkcsBuffer, Password());
489
490         if (pkcs->empty())
491                 throw runtime_error("Empty pkcs");
492
493         SwitchToUser();
494
495         // certificates
496         RawBuffer rootCaBuffer(TEST_ROOT_CA.begin(), TEST_ROOT_CA.end());
497         CertificateShPtr rootCa = CKM::Certificate::create(rootCaBuffer,
498                                                           CKM::DataFormat::FORM_PEM);
499         RawBuffer imCaBuffer(TEST_IM_CA.begin(), TEST_IM_CA.end());
500         CertificateShPtr imCa = CKM::Certificate::create(imCaBuffer,
501                                                         CKM::DataFormat::FORM_PEM);
502         RawBuffer leafBuffer(TEST_LEAF.begin(), TEST_LEAF.end());
503         CertificateShPtr leaf = CKM::Certificate::create(leafBuffer,
504                                                         CKM::DataFormat::FORM_PEM);
505
506         for (const auto &g : GROUPS) {
507                 switch (g.type) {
508                 case Group::KEY_PAIR_RSA:
509                         if (g.items.size() != 2)
510                                 throw runtime_error("Wrong number of keys");
511
512                         if (g.items[0].type != DataType::KEY_RSA_PRIVATE ||
513                                         g.items[1].type != DataType::KEY_RSA_PUBLIC)
514                                 throw runtime_error("Invalid item type");
515
516                         if (CKM_API_SUCCESS != m_mgr->createKeyPairRSA(1024,
517                                         g.items[0].alias,
518                                         g.items[1].alias,
519                                         g.items[0].policy,
520                                         g.items[1].policy))
521                                 throw runtime_error("createKeyPair failed");
522
523                         break;
524
525                 case Group::CERT_CHAIN:
526                         if (g.items.size() != CHAIN_SIZE)
527                                 throw runtime_error("Wrong number of certificates");
528
529                         if (g.items[0].type != DataType::CERTIFICATE ||
530                                         g.items[1].type != DataType::CERTIFICATE ||
531                                         g.items[2].type != DataType::CERTIFICATE)
532                                 throw runtime_error("Invalid item type");
533
534                         if (CKM_API_SUCCESS != m_mgr->saveCertificate(g.items[0].alias, rootCa,
535                                         g.items[0].policy))
536                                 throw runtime_error("saveCertificate failed");
537
538                         if (CKM_API_SUCCESS != m_mgr->saveCertificate(g.items[1].alias, imCa,
539                                         g.items[1].policy))
540                                 throw runtime_error("saveCertificate failed");
541
542                         if (CKM_API_SUCCESS != m_mgr->saveCertificate(g.items[2].alias, leaf,
543                                         g.items[2].policy))
544                                 throw runtime_error("saveCertificate failed");
545
546                         break;
547
548                 default:
549                         for (const auto &i : g.items) {
550                                 switch (i.type) {
551                                 case DataType::BINARY_DATA:
552                                         if (CKM_API_SUCCESS != m_mgr->saveData(i.alias, TEST_DATA, i.policy))
553                                                 throw runtime_error("saveData failed");
554
555                                         break;
556
557                                 case DataType::KEY_AES:
558                                         if (CKM_API_SUCCESS != m_mgr->createKeyAES(256, i.alias, i.policy))
559                                                 throw runtime_error("createKeyAES failed");
560
561                                         break;
562
563                                 case DataType::CHAIN_CERT_0:    // PKCS
564                                         if (CKM_API_SUCCESS != m_mgr->savePKCS12(i.alias, pkcs, i.policy, i.policy))
565                                                 throw runtime_error("savePkcs12 failed");
566
567                                         break;
568
569                                 default:
570                                         throw runtime_error("unsupported data type");
571                                 }
572                         }
573
574                         break;
575                 }
576         }
577 }
578
579 void SchemeTest::CheckAliasInfo()
580 {
581         SwitchToUser();
582         for (const auto &g : GROUPS) {
583                 for (const auto &i : g.items) {
584                         int ret;
585                         bool encStatus = false;
586                         Password pass = i.policy.password;
587
588                         if (pass.empty())
589                                 pass = TEST_PASS;
590                         else
591                                 pass = Password();
592
593                         switch (i.type) {
594                         case DataType::BINARY_DATA: {
595                                 ret = m_mgr->getDataEncryptionStatus(i.alias, encStatus);
596                                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
597                                                                           "can not get data encryption status, ret: " +
598                                                                           std::to_string(ret));
599                                 break;
600                         }
601
602                         case DataType::KEY_AES:
603                         case DataType::KEY_RSA_PRIVATE:
604                         case DataType::KEY_RSA_PUBLIC: {
605                                 ret = m_mgr->getKeyEncryptionStatus(i.alias, encStatus);
606                                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
607                                                                           "can not get key encryption status, ret: " +
608                                                                           std::to_string(ret));
609                                 break;
610                         }
611
612                         case DataType::CERTIFICATE: {
613                                 ret = m_mgr->getCertificateEncryptionStatus(i.alias, encStatus);
614                                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
615                                                                           "can not get certificate encryption status, ret: " +
616                                                                           std::to_string(ret));
617                                 break;
618                         }
619
620                         case DataType::CHAIN_CERT_0: {
621                                 ret = m_mgr->getCertificateEncryptionStatus(i.alias, encStatus);
622                                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
623                                                                           "can not get certificate encryption status, ret: " +
624                                                                           std::to_string(ret));
625                                 ret = m_mgr->getKeyEncryptionStatus(i.alias, encStatus);
626                                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
627                                                                           "can not get key encryption status, ret: " +
628                                                                           std::to_string(ret));
629                                 break;
630                         }
631
632                         default:
633                                 BOOST_FAIL("Unsupported data type " << i.type);
634                         }
635                 BOOST_REQUIRE_MESSAGE(encStatus == !i.policy.password.empty(), "item: " <<
636                                                           i.alias << " has wrong encryption status: " << encStatus);
637
638                 }
639         }
640 }
641
642
643 void SchemeTest::ReadAll(bool useWrongPass)
644 {
645         SwitchToUser();
646
647         for (const auto &g : GROUPS) {
648                 for (const auto &i : g.items) {
649                         int ret;
650                         Password pass = i.policy.password;
651
652                         if (useWrongPass) {
653                                 if (pass.empty())
654                                         pass = TEST_PASS;
655                                 else
656                                         pass = Password();
657                         }
658
659                         switch (i.type) {
660                         case DataType::BINARY_DATA: {
661                                 RawBuffer receivedData;
662                                 ret = m_mgr->getData(i.alias, pass, receivedData);
663                                 BOOST_REQUIRE_MESSAGE(useWrongPass || receivedData == TEST_DATA,
664                                                                           "Received data is different for " << i.alias);
665                                 break;
666                         }
667
668                         case DataType::KEY_AES:
669                         case DataType::KEY_RSA_PRIVATE:
670                         case DataType::KEY_RSA_PUBLIC: {
671                                 KeyShPtr receivedKey;
672                                 ret = m_mgr->getKey(i.alias, pass, receivedKey);
673                                 break;
674                         }
675
676                         case DataType::CERTIFICATE: {
677                                 CertificateShPtr receivedCert;
678                                 ret = m_mgr->getCertificate(i.alias, pass, receivedCert);
679                                 break;
680                         }
681
682                         case DataType::CHAIN_CERT_0: { // pkcs
683                                 PKCS12ShPtr pkcs;
684                                 ret = m_mgr->getPKCS12(i.alias, pass, pass, pkcs);
685                                 break;
686                         }
687
688                         default:
689                                 BOOST_FAIL("Unsupported data type " << i.type);
690                         }
691
692                         if (i.policy.extractable) {
693                                 if (useWrongPass)
694                                         BOOST_REQUIRE_MESSAGE(ret == CKM_API_ERROR_AUTHENTICATION_FAILED,
695                                                                                   "Reading item " << i.alias << " should fail with " <<
696                                                                                   CKM_API_ERROR_AUTHENTICATION_FAILED << " got: " << ret);
697                                 else
698                                         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "Reading item " << i.alias <<
699                                                                                   " failed with " << ret);
700                         } else {
701                                 BOOST_REQUIRE_MESSAGE(ret == CKM_API_ERROR_NOT_EXPORTABLE, "Item " << i.alias <<
702                                                                           " should not be exportable");
703                         }
704                 }
705         }
706 }
707
708 void SchemeTest::SignVerify()
709 {
710         SwitchToUser();
711
712         for (const auto &g : GROUPS) {
713                 if (g.type == Group::KEY_PAIR_RSA) {
714                         BOOST_REQUIRE_MESSAGE(g.items.size() == 2, "Wrong number of keys");
715                         BOOST_REQUIRE_MESSAGE(g.items[0].type == DataType::KEY_RSA_PRIVATE &&
716                                                                   g.items[1].type == DataType::KEY_RSA_PUBLIC, "Wrong key");
717
718                         SignVerifyItem(g.items[0], g.items[1]);
719                 } else {
720                         for (const auto &i : g.items) {
721                                 switch (i.type) {
722                                 case DataType::CHAIN_CERT_0:
723                                         SignVerifyItem(i, i);
724                                         break;
725
726                                 default:
727                                         break;
728                                 }
729                         }
730                 }
731         }
732 }
733
734 void SchemeTest::EncryptDecrypt()
735 {
736         SwitchToUser();
737
738         for (const auto &g : GROUPS) {
739                 if (g.type == Group::KEY_PAIR_RSA) {
740                         BOOST_REQUIRE_MESSAGE(g.items.size() == 2, "Wrong number of keys");
741                         BOOST_REQUIRE_MESSAGE(g.items[0].type == DataType::KEY_RSA_PRIVATE &&
742                                                                   g.items[1].type == DataType::KEY_RSA_PUBLIC, "Wrong key");
743
744                         EncryptDecryptItem(g.items[0], g.items[1]);
745                 } else {
746                         for (const auto &i : g.items) {
747                                 switch (i.type) {
748                                 case DataType::KEY_AES:
749                                         EncryptDecryptItem(i);
750                                         break;
751
752                                 case DataType::CHAIN_CERT_0:
753                                         EncryptDecryptItem(i, i);
754                                         break;
755
756                                 default:
757                                         break;
758                                 }
759                         }
760                 }
761         }
762 }
763
764 void SchemeTest::CreateChain()
765 {
766         SwitchToUser();
767
768         for (const auto &g : GROUPS) {
769                 if (g.type == Group::CERT_CHAIN) {
770                         BOOST_REQUIRE_MESSAGE(g.items.size() == CHAIN_SIZE, "Not enough certificates");
771
772                         for (const auto &c : g.items)
773                                 BOOST_REQUIRE_MESSAGE(c.type == DataType::CERTIFICATE, "Wrong item type");
774
775                         Items trusted(CHAIN_SIZE - 1);
776                         std::copy(g.items.begin(), g.items.begin() + CHAIN_SIZE - 1, trusted.begin());
777
778                         // last one is ee (leaf)
779                         CreateChainItem(g.items.back(), trusted);
780                 } else {
781                         for (const auto &i : g.items) {
782                                 if (i.type == DataType::CHAIN_CERT_0) // PKCS
783                                         CreateChainItem(i, { i });
784                         }
785                 }
786         }
787 }
788
789 void SchemeTest::RemoveAll()
790 {
791         SwitchToUser();
792
793         for (const auto &g : GROUPS) {
794                 for (const auto &i : g.items) {
795                         int ret = m_mgr->removeAlias(i.alias);
796                         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
797                                                                   "removeAlias() failed with " << ret << " for " << i.alias);
798                 }
799         }
800 }
801 size_t SchemeTest::CountObjects()
802 {
803         EnableDirectDbAccess();
804
805         size_t ret = 0;
806
807         for (const auto &g : GROUPS) {
808                 for (const auto &i : g.items) {
809                         DB::RowVector rows;
810                         // it is assumed that aliases are different
811                         m_db->getRows(i.alias, OWNER, DataType::DB_FIRST, DataType::DB_LAST, rows);
812                         ret += rows.size();
813                 }
814         }
815
816         return ret;
817 }
818
819 void SchemeTest::RestoreDb()
820 {
821         m_db.reset();
822         restoreFile("key-7654");
823         restoreFile("db-key-7654");
824         restoreFile("db-7654");
825         m_directAccessEnabled = false;
826 }
827
828 void SchemeTest::CheckSchemeVersion(const ItemFilter &filter, int version)
829 {
830         EnableDirectDbAccess();
831
832         for (const auto &g : GROUPS) {
833                 for (const auto &i : g.items) {
834                         if (!filter.Matches(i))
835                                 continue;
836
837                         DB::RowVector rows;
838                         m_db->getRows(i.alias, OWNER, filter.typeFrom, filter.typeTo, rows);
839                         BOOST_REQUIRE_MESSAGE(rows.size() > 0, "No rows found for " << i.alias);
840
841                         for (const auto &r : rows) {
842                                 BOOST_REQUIRE_MESSAGE(
843                                         (r.encryptionScheme >> ENC_SCHEME_OFFSET) == version,
844                                         "Wrong encryption scheme for " << i.alias << ". Expected " << version <<
845                                         " got: " << (r.encryptionScheme >> ENC_SCHEME_OFFSET));
846                         }
847                 }
848         }
849 }
850
851 void SchemeTest::EnableDirectDbAccess()
852 {
853         SwitchToRoot();
854
855         if (m_directAccessEnabled)
856                 return;
857
858         // direct access to db
859         FileSystem fs(UID);
860         auto wrappedDKEK = fs.getDKEK();
861         auto keyProvider = KeyProvider(wrappedDKEK, DBPASS);
862         if (!keyProvider.isInitialized()) {
863                 keyProvider.migrateDKEK(wrappedDKEK, DBPASS);
864                 fs.saveDKEK(keyProvider.getWrappedDomainKEK(DBPASS));
865         }
866
867         auto wrappedDatabaseDEK = fs.getDBDEK();
868         RawBuffer key = keyProvider.getPureDEK(wrappedDatabaseDEK);
869
870         m_db.reset(new DB::Crypto(fs.getLegacyDBPath(), fs.getDBPath(), key));
871         m_directAccessEnabled = true;
872
873         // Legacy db files of the form db-$uid are incompatible with upstream sqlcipher.
874         // DB::Crypto(...) converts them to db0-$uid upstream-compatible, then deletes them.
875         // This function runs DB::Crypto(...) as root so db0-$uid are root-owned.
876         // However, database files need to be accessible to USER_NAME/GROUP_NAME (ex. ReadAll()).
877         // Thus the need to fix up ownership, much like restoreFile() does.
878         BOOST_REQUIRE(!chown(RW_DATA_DIR "/db0-7654", getUid(USER_NAME), getGid(GROUP_NAME)));
879 }
880
881 void SchemeTest::SignVerifyItem(const Item &itemPrv, const Item &itemPub)
882 {
883         int ret;
884         KeyShPtr receivedKey;
885         RawBuffer signature;
886         // create/verify signature
887         ret = m_mgr->createSignature(itemPrv.alias,
888                                                                  itemPrv.policy.password,
889                                                                  TEST_DATA,
890                                                                  HashAlgorithm::SHA512,
891                                                                  RSAPaddingAlgorithm::X931,
892                                                                  signature);
893         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
894                                                   "createSignature() failed with " << ret <<
895                                                   " for " << itemPrv.alias);
896         ret = m_mgr->verifySignature(itemPub.alias,
897                                                                  itemPub.policy.password,
898                                                                  TEST_DATA,
899                                                                  signature,
900                                                                  HashAlgorithm::SHA512,
901                                                                  RSAPaddingAlgorithm::X931);
902         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
903                                                   "verifySignature() failed with " << ret <<
904                                                   " for " << itemPub.alias);
905 }
906
907 void SchemeTest::EncryptDecryptItem(const Item &item)
908 {
909         CryptoAlgorithm algo;
910         RawBuffer iv = createRandomBuffer(IV_LEN);
911         RawBuffer encrypted, decrypted;
912         int ret;
913
914         algo.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
915         algo.setParam(ParamName::ED_IV, iv);
916
917         ret = m_mgr->encrypt(algo, item.alias, item.policy.password, TEST_DATA,
918                                                  encrypted);
919         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
920                                                   "encrypt() failed iwth " << ret << " for " <<
921                                                   item.alias);
922
923         ret = m_mgr->decrypt(algo, item.alias, item.policy.password, encrypted,
924                                                  decrypted);
925         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
926                                                   "decrypt() failed iwth " << ret << " for " <<
927                                                   item.alias);
928
929         BOOST_REQUIRE_MESSAGE(decrypted == TEST_DATA,
930                                                   "Decrypted data not equal to original");
931 }
932
933 void SchemeTest::EncryptDecryptItem(const Item &itemPrv, const Item &itemPub)
934 {
935         CryptoAlgorithm algo;
936         RawBuffer encrypted, decrypted;
937         int ret;
938
939         algo.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
940
941         ret = m_mgr->encrypt(algo, itemPub.alias, itemPub.policy.password, TEST_DATA,
942                                                  encrypted);
943         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
944                                                   "encrypt() failed iwth " << ret << " for " <<
945                                                   itemPub.alias);
946
947         ret = m_mgr->decrypt(algo, itemPrv.alias, itemPrv.policy.password, encrypted,
948                                                  decrypted);
949         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
950                                                   "decrypt() failed iwth " << ret << " for " <<
951                                                   itemPrv.alias);
952
953         BOOST_REQUIRE_MESSAGE(decrypted == TEST_DATA,
954                                                   "Decrypted data not equal to original");
955 }
956
957 void SchemeTest::CreateChainItem(const Item &leaf, const Items &certs)
958 {
959         CertificateShPtrVector chain;
960         AliasVector trusted;
961
962         if (!leaf.policy.extractable || !leaf.policy.password.empty())
963                 return;
964
965         for (const auto &i : certs) {
966                 if (!i.policy.extractable || !i.policy.password.empty())
967                         return;
968
969                 trusted.push_back(i.alias);
970         }
971
972         CertificateShPtr leafCrt;
973         int ret = m_mgr->getCertificate(leaf.alias, leaf.policy.password, leafCrt);
974         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
975                                                   "getCertificate failed with " << ret << " for " <<
976                                                   leaf.alias);
977
978         ret = m_mgr->getCertificateChain(leafCrt, AliasVector(), trusted, false, chain);
979         BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
980                                                   "getCertificateChain() failed with " << ret);
981         BOOST_REQUIRE_MESSAGE(chain.size() == CHAIN_LEN,
982                                                   "Wrong chain length: " << chain.size());
983 }