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