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