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