2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 * @file scheme-test.cpp
18 * @author Krzysztof Jackiewicz (k.jackiewicz@samsung.com)
21 #include <scheme-test.h>
23 #include <sys/smack.h>
24 #include <sys/types.h>
26 #include <sys/sendfile.h>
34 #include <boost/test/unit_test.hpp>
36 #include <smack-access.h>
38 #include <db-crypto.h>
39 #include <file-system.h>
40 #include <key-provider.h>
42 #include <crypto-init.h>
48 const uid_t UID = 7654;
49 const gid_t GID = 7654;
50 const char* const DBPASS = "db-pass";
51 const char* const LABEL = "my-label";
52 const Label DB_LABEL = "/" + string(LABEL);
53 const int ENC_SCHEME_OFFSET = 24;
54 const string TEST_DATA_STR = "test-data";
55 RawBuffer TEST_DATA(TEST_DATA_STR.begin(), TEST_DATA_STR.end());
56 const Password TEST_PASS = "custom user password";
57 const size_t IV_LEN = 16;
58 const size_t CHAIN_LEN = 3;
70 // [password][exportable]
71 Policy policy[2][2] = {
72 {{ Password(), false }, { Password(), true }},
73 {{ TEST_PASS, false }, { TEST_PASS, true }},
87 { Group::SINGLE_ITEM, {
88 Item("data-alias1", DataType::BINARY_DATA, policy[NO_PASS][EXP])
90 { Group::SINGLE_ITEM, {
91 Item("data-alias2", DataType::BINARY_DATA, policy[PASS][EXP])
95 { Group::KEY_PAIR_RSA, {
96 Item("key-rsa-alias-prv1", DataType::KEY_RSA_PRIVATE, policy[NO_PASS][NO_EXP]),
97 Item("key-rsa-alias-pub1", DataType::KEY_RSA_PUBLIC, policy[NO_PASS][NO_EXP])
99 { Group::KEY_PAIR_RSA, {
100 Item("key-rsa-alias-prv2", DataType::KEY_RSA_PRIVATE, policy[NO_PASS][EXP]),
101 Item("key-rsa-alias-pub2", DataType::KEY_RSA_PUBLIC, policy[NO_PASS][EXP]),
103 { Group::KEY_PAIR_RSA, {
104 Item("key-rsa-alias-prv3", DataType::KEY_RSA_PRIVATE, policy[PASS][NO_EXP]),
105 Item("key-rsa-alias-pub3", DataType::KEY_RSA_PUBLIC, policy[PASS][NO_EXP]),
107 { Group::KEY_PAIR_RSA, {
108 Item("key-rsa-alias-prv4", DataType::KEY_RSA_PRIVATE, policy[PASS][EXP]),
109 Item("key-rsa-alias-pub4", DataType::KEY_RSA_PUBLIC, policy[PASS][EXP]),
111 // different policies
112 { Group::KEY_PAIR_RSA, {
113 Item("key-rsa-alias-prv5", DataType::KEY_RSA_PRIVATE, policy[PASS][NO_EXP]),
114 Item("key-rsa-alias-pub5", DataType::KEY_RSA_PUBLIC, policy[NO_PASS][EXP]),
118 { Group::SINGLE_ITEM, {
119 Item("key-aes-alias1", DataType::KEY_AES, policy[NO_PASS][NO_EXP]),
121 { Group::SINGLE_ITEM, {
122 Item("key-aes-alias2", DataType::KEY_AES, policy[NO_PASS][EXP]),
124 { Group::SINGLE_ITEM, {
125 Item("key-aes-alias3", DataType::KEY_AES, policy[PASS][NO_EXP]),
127 { Group::SINGLE_ITEM, {
128 Item("key-aes-alias4", DataType::KEY_AES, policy[PASS][EXP]),
132 { Group::CERT_CHAIN, {
133 Item("cert-root-alias1", DataType::CERTIFICATE, policy[NO_PASS][NO_EXP]),
134 Item("cert-im-ca-alias1", DataType::CERTIFICATE, policy[NO_PASS][NO_EXP]),
135 Item("cert-leaf-alias1", DataType::CERTIFICATE, policy[NO_PASS][NO_EXP]),
137 { Group::CERT_CHAIN, {
138 Item("cert-root-alias2", DataType::CERTIFICATE, policy[NO_PASS][EXP]),
139 Item("cert-im-ca-alias2", DataType::CERTIFICATE, policy[NO_PASS][EXP]),
140 Item("cert-leaf-alias2", DataType::CERTIFICATE, policy[NO_PASS][EXP]),
142 { Group::CERT_CHAIN, {
143 Item("cert-root-alias3", DataType::CERTIFICATE, policy[PASS][NO_EXP]),
144 Item("cert-im-ca-alias3", DataType::CERTIFICATE, policy[PASS][NO_EXP]),
145 Item("cert-leaf-alias3", DataType::CERTIFICATE, policy[PASS][NO_EXP]),
147 { Group::CERT_CHAIN, {
148 Item("cert-root-alias4", DataType::CERTIFICATE, policy[PASS][EXP]),
149 Item("cert-im-ca-alias4", DataType::CERTIFICATE, policy[PASS][EXP]),
150 Item("cert-leaf-alias4", DataType::CERTIFICATE, policy[PASS][EXP]),
154 { Group::SINGLE_ITEM, {
155 Item("pkcs-alias1", DataType::CHAIN_CERT_0, policy[NO_PASS][NO_EXP]),
157 { Group::SINGLE_ITEM, {
158 Item("pkcs-alias2", DataType::CHAIN_CERT_0, policy[NO_PASS][EXP]),
160 { Group::SINGLE_ITEM, {
161 Item("pkcs-alias3", DataType::CHAIN_CERT_0, policy[PASS][NO_EXP]),
163 { Group::SINGLE_ITEM, {
164 Item("pkcs-alias4", DataType::CHAIN_CERT_0, policy[PASS][EXP]),
168 const size_t CHAIN_SIZE = 3;
170 // TEST_ROOT_CA, expires 2035
171 std::string TEST_ROOT_CA =
172 "-----BEGIN CERTIFICATE-----\n"
173 "MIIDnzCCAoegAwIBAgIJAMH/ADkC5YSTMA0GCSqGSIb3DQEBBQUAMGYxCzAJBgNV\n"
174 "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMQ0wCwYDVQQKDARBQ01FMRAwDgYD\n"
175 "VQQLDAdUZXN0aW5nMSEwHwYDVQQDDBhUZXN0IHJvb3QgY2EgY2VydGlmaWNhdGUw\n"
176 "HhcNMTQxMjMwMTcyMTUyWhcNMjQxMjI3MTcyMTUyWjBmMQswCQYDVQQGEwJBVTET\n"
177 "MBEGA1UECAwKU29tZS1TdGF0ZTENMAsGA1UECgwEQUNNRTEQMA4GA1UECwwHVGVz\n"
178 "dGluZzEhMB8GA1UEAwwYVGVzdCByb290IGNhIGNlcnRpZmljYXRlMIIBIjANBgkq\n"
179 "hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0EJRdUtd2th0vTVF7QxvDKzyFCF3w9vC\n"
180 "9IDE/Yr12w+a9jd0s7/eG96qTHIYffS3B7x2MB+d4n+SR3W0qmYh7xk8qfEgH3da\n"
181 "eDoV59IZ9r543KM+g8jm6KffYGX1bIJVVY5OhBRbO9nY6byYpd5kbCIUB6dCf7/W\n"
182 "rQl1aIdLGFIegAzPGFPXDcU6F192686x54bxt/itMX4agHJ9ZC/rrTBIZghVsjJo\n"
183 "5/AH5WZpasv8sfrGiiohAxtieoYoJkv5MOYP4/2lPlOY+Cgw1Yoz+HHv31AllgFs\n"
184 "BquBb/kJVmCCNsAOcnvQzTZUsW/TXz9G2nwRdqI1nSy2JvVjZGsqGQIDAQABo1Aw\n"
185 "TjAdBgNVHQ4EFgQUt6pkzFt1PZlfYRL/HGnufF4frdwwHwYDVR0jBBgwFoAUt6pk\n"
186 "zFt1PZlfYRL/HGnufF4frdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC\n"
187 "AQEAld7Qwq0cdzDQ51w1RVLwTR8Oy25PB3rzwEHcSGJmdqlMi3xOdaz80S1R1BBX\n"
188 "ldvGBG5Tn0vT7xSuhmSgI2/HnBpy9ocHVOmhtNB4473NieEpfTYrnGXrFxu46Wus\n"
189 "9m/ZnugcQ2G6C54A/NFtvgLmaC8uH8M7gKdS6uYUwJFQEofkjmd4UpOYSqmcRXhS\n"
190 "Jzd5FYFWkJhKJYp3nlENSOD8CUFFVGekm05nFN2gRVc/qaqQkEX77+XYvhodLRsV\n"
191 "qMn7nf7taidDKLO2T4bhujztnTYOhhaXKgPy7AtZ28N2wvX96VyAPB/vrchGmyBK\n"
192 "kOg11TpPdNDkhb1J4ZCh2gupDg==\n"
193 "-----END CERTIFICATE-----\n";
195 // TEST_IM_CA, signed by TEST_ROOT_CA, expires 2035
196 std::string TEST_IM_CA =
197 "-----BEGIN CERTIFICATE-----\n"
198 "MIIDljCCAn6gAwIBAgICEAAwDQYJKoZIhvcNAQEFBQAwZjELMAkGA1UEBhMCQVUx\n"
199 "EzARBgNVBAgMClNvbWUtU3RhdGUxDTALBgNVBAoMBEFDTUUxEDAOBgNVBAsMB1Rl\n"
200 "c3RpbmcxITAfBgNVBAMMGFRlc3Qgcm9vdCBjYSBjZXJ0aWZpY2F0ZTAeFw0xNTAx\n"
201 "MTYxNjQ1MzRaFw0zNTAxMTExNjQ1MzRaMGQxCzAJBgNVBAYTAkFVMRMwEQYDVQQI\n"
202 "DApTb21lLVN0YXRlMQ0wCwYDVQQKDARBQ01FMRAwDgYDVQQLDAdUZXN0aW5nMR8w\n"
203 "HQYDVQQDDBZUZXN0IElNIENBIGNlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEF\n"
204 "AAOCAQ8AMIIBCgKCAQEAzmBF78qClgoKfnLAncMXZwZ14TW+5kags1+QCYeg3c7j\n"
205 "L9+RvDxIaX2tKf1sukJcwQfYqUlQkwt+58LMOb2ORtkpj8Or6WCWCZ0BzneT8ug7\n"
206 "nxJT4m9+bohMF0JoKjjB2H4KNMHamLIwUxRKt6nyfk81kVhJOi2vzzxd+UCPi6Pc\n"
207 "UAbJNH48eNgOIg55nyFovVzYj8GIo/9GvHJj83PPa/KlJZ+Z1qZASZZ/VYorplVT\n"
208 "thsHXKfejhFy5YJ9t7n/vyAQsyBsagZsvX19xnH41fbYXHKf8UbXG23rNaZlchs6\n"
209 "XJVLQdzOpj3WTj/lCocVHqLaZISLhNQ3aI7kUBUdiwIDAQABo1AwTjAdBgNVHQ4E\n"
210 "FgQUoCYNaCBP4jl/3SYQuK8Ka+6i3QEwHwYDVR0jBBgwFoAUt6pkzFt1PZlfYRL/\n"
211 "HGnufF4frdwwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAjRzWiD97\n"
212 "Htv4Kxpm3P+C+xP9AEteCJfO+7p8MWgtWEJOknJyt55zeKS2JwZIq57KcbqD8U7v\n"
213 "vAUx1ymtUhlFPFd7J1mJ3pou+3aFYmGShYhGHpbrmUwjp7HVP588jrW1NoZVHdMc\n"
214 "4OgJWFrViXeu9+maIcekjMB/+9Y0dUgQuK5ZuT5H/Jwet7Th/o9uufTUZjBzRvrB\n"
215 "pbXgQpqgME2av4Q/6LuldPCTHLtWXgFUU2R+yCGmuGilvhFJnKoQryAbYnIQNWE8\n"
216 "SLoHQ9s1i7Zyb7HU6UAaqMOz15LBkyAqtNyJcO2p7Q/p5YK0xfD4xisI5qXucqVm\n"
218 "-----END CERTIFICATE-----\n";
220 // TEST_LEAF, signed by TEST_IM_CA, expires 2035
221 std::string TEST_LEAF =
222 "-----BEGIN CERTIFICATE-----\n"
223 "MIIDOzCCAiMCAQEwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCQVUxEzARBgNV\n"
224 "BAgMClNvbWUtU3RhdGUxDTALBgNVBAoMBEFDTUUxEDAOBgNVBAsMB1Rlc3Rpbmcx\n"
225 "HzAdBgNVBAMMFlRlc3QgSU0gQ0EgY2VydGlmaWNhdGUwHhcNMTUwMTE2MTY0ODE0\n"
226 "WhcNMzUwMTExMTY0ODE0WjBjMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1T\n"
227 "dGF0ZTENMAsGA1UECgwEQUNNRTEQMA4GA1UECwwHVGVzdGluZzEeMBwGA1UEAwwV\n"
228 "VGVzdCBsZWFmIGNlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"
229 "CgKCAQEAzTdDIa2tDmRxFnIgiG+mBz8GoSVODs0ImNQGbqj+pLhBOFRH8fsah4Jl\n"
230 "z5YF9KwhMVLknnHGFLE/Nb7Ac35kEzhMQMpTRxohW83oxw3eZ8zN/FBoKqg4qHRq\n"
231 "QR8kS10YXTgrBR0ex/Vp+OUKEw6h7yL2r4Tpvrn9/qHwsxtLxqWbDIVf1O9b1Lfc\n"
232 "bllYMdmV5E62yN5tcwrDP8gvHjFnVeLzrG8wTpc9FR90/0Jkfp5jAJcArOBLrT0E\n"
233 "4VRqs+4HuwT8jAwFAmNnc7IYX5qSjtSWkmmHe73K/lzB+OiI0JEc/3eWUTWqwTSk\n"
234 "4tNCiQGBKJ39LXPTBBJdzmxVH7CUDQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQAp\n"
235 "UdDOGu3hNiG+Vn10aQ6B1ZmOj3t+45gUV3sC+y8hB8EK1g4P5Ke9bVDts0T5eOnj\n"
236 "CSc+6VoND5O4adI0IFFRFljHNVnvjeosHfUZNnowsmA2ptQBtC1g5ZKRvKXlkC5/\n"
237 "i5BGgRqPFA7y9WB9Y05MrJHf3E+Oz/RBsLeeNiNN+rF5X1vYExvGHpo0M0zS0ze9\n"
238 "HtC0aOy8ocsTrQkf3ceHTAXx2i8ftoSSD4klojtWFpWMrNQa52F7wB9nU6FfKRuF\n"
239 "Zj/T1JkYXKkEwZU6nAR2jdZp3EP9xj3o15V/tyFcXHx6l8NTxn4cJb+Xe4VquQJz\n"
240 "6ON7PVe0ABN/AlwVQiFE\n"
241 "-----END CERTIFICATE-----\n";
246 void operator()(int* fd) {
252 typedef std::unique_ptr<int, FdCloser> FdPtr;
254 void restoreFile(const string& filename) {
255 string sourcePath = "/usr/share/ckm-db-test/" + filename;
256 string targetPath = "/opt/data/ckm/" + filename;
260 int sourceFd = TEMP_FAILURE_RETRY(open(sourcePath.c_str(), O_RDONLY));
261 BOOST_REQUIRE_MESSAGE(sourceFd > 0, "Opening " << sourcePath << " failed.");
263 FdPtr sourceFdPtr(&sourceFd);
265 int targetFd = TEMP_FAILURE_RETRY(creat(targetPath.c_str(), 666));
266 BOOST_REQUIRE_MESSAGE(targetFd > 0, "Creating " << targetPath << " failed.");
268 FdPtr targetFdPtr(&targetFd);
270 struct stat sourceStat;
271 ret = fstat(sourceFd, &sourceStat);
272 BOOST_REQUIRE_MESSAGE(ret != -1, "fstat() failed: " << ret);
274 ret = sendfile(targetFd, sourceFd, 0, sourceStat.st_size);
275 BOOST_REQUIRE_MESSAGE(ret != -1, "sendfile failed: " << ret);
277 ret = fsync(targetFd);
278 BOOST_REQUIRE_MESSAGE(ret != -1, "fsync failed: " << ret);
281 void generateRandom(size_t random_bytes, unsigned char *output)
283 if(random_bytes<=0 || !output)
284 throw runtime_error("Invalid param");
286 std::ifstream is("/dev/urandom", std::ifstream::binary);
288 throw runtime_error("Failed to read /dev/urandom");
289 is.read(reinterpret_cast<char*>(output), random_bytes);
290 if(static_cast<std::streamsize>(random_bytes) != is.gcount())
291 throw runtime_error("Not enough bytes read from /dev/urandom");
294 RawBuffer createRandomBuffer(size_t random_bytes)
296 RawBuffer buffer(random_bytes);
297 generateRandom(buffer.size(), buffer.data());
300 } // namespace anonymous
303 SchemeTest::SchemeTest() : m_userChanged(false), m_directAccessEnabled(false) {
304 m_control = Control::create();
305 m_mgr = Manager::create();
309 sa.add("System", LABEL, "rwx");
310 sa.add(LABEL, "System", "rwx");
311 sa.add(LABEL, "System::Run", "x");
315 SchemeTest::~SchemeTest() {
321 void SchemeTest::RemoveUserData() {
322 if(CKM_API_SUCCESS != m_control->lockUserKey(UID))
323 throw runtime_error("lockUserKey failed");
325 if(CKM_API_SUCCESS != m_control->removeUserData(UID))
326 throw runtime_error("removeUserData failed");
329 void SchemeTest::SwitchToUser() {
333 if(CKM_API_SUCCESS != m_control->unlockUserKey(UID, DBPASS))
334 throw runtime_error("unlockUserKey failed");
338 if (smack_new_label_from_self(&label) <= 0)
339 throw runtime_error("smack_new_label_from_self failed");
341 m_origLabel = string(label);
344 if(0 > smack_set_label_for_self(LABEL))
345 throw runtime_error("smack_set_label_for_self failed");
348 throw runtime_error("setegid failed");
351 throw runtime_error("seteuid failed");
353 m_userChanged = true;
356 void SchemeTest::SwitchToRoot() {
361 throw runtime_error("seteuid failed");
363 throw runtime_error("setegid failed");
365 if(0 > smack_set_label_for_self(m_origLabel.c_str()))
366 throw runtime_error("smack_set_label_for_self failed");
368 if(m_control->lockUserKey(UID) != CKM_API_SUCCESS)
369 throw runtime_error("lockUserKey failed");
372 void SchemeTest::FillDb() {
374 ifstream is("/usr/share/ckm-db-test/encryption-scheme.p12");
376 throw runtime_error("Failed to read pkcs");
377 istreambuf_iterator<char> begin(is), end;
378 RawBuffer pkcsBuffer(begin, end);
379 auto pkcs = PKCS12::create(pkcsBuffer, Password());
381 throw runtime_error("Empty pkcs");
386 RawBuffer rootCaBuffer(TEST_ROOT_CA.begin(), TEST_ROOT_CA.end());
387 CertificateShPtr rootCa = CKM::Certificate::create(rootCaBuffer, CKM::DataFormat::FORM_PEM);
388 RawBuffer imCaBuffer(TEST_IM_CA.begin(), TEST_IM_CA.end());
389 CertificateShPtr imCa = CKM::Certificate::create(imCaBuffer, CKM::DataFormat::FORM_PEM);
390 RawBuffer leafBuffer(TEST_LEAF.begin(), TEST_LEAF.end());
391 CertificateShPtr leaf = CKM::Certificate::create(leafBuffer, CKM::DataFormat::FORM_PEM);
393 for(const auto& g:GROUPS) {
395 case Group::KEY_PAIR_RSA:
396 if(g.items.size() != 2)
397 throw runtime_error("Wrong number of keys");
398 if( g.items[0].type != DataType::KEY_RSA_PRIVATE ||
399 g.items[1].type != DataType::KEY_RSA_PUBLIC)
400 throw runtime_error("Invalid item type");
402 if(CKM_API_SUCCESS != m_mgr->createKeyPairRSA(1024,
407 throw runtime_error("createKeyPair failed");
410 case Group::CERT_CHAIN:
411 if(g.items.size() != CHAIN_SIZE)
412 throw runtime_error("Wrong number of certificates");
413 if( g.items[0].type != DataType::CERTIFICATE ||
414 g.items[1].type != DataType::CERTIFICATE ||
415 g.items[2].type != DataType::CERTIFICATE)
416 throw runtime_error("Invalid item type");
418 if(CKM_API_SUCCESS != m_mgr->saveCertificate(g.items[0].alias, rootCa, g.items[0].policy))
419 throw runtime_error("saveCertificate failed");
420 if(CKM_API_SUCCESS != m_mgr->saveCertificate(g.items[1].alias, imCa, g.items[1].policy))
421 throw runtime_error("saveCertificate failed");
422 if(CKM_API_SUCCESS != m_mgr->saveCertificate(g.items[2].alias, leaf, g.items[2].policy))
423 throw runtime_error("saveCertificate failed");
427 for(const auto& i:g.items) {
429 case DataType::BINARY_DATA:
430 if(CKM_API_SUCCESS != m_mgr->saveData(i.alias, TEST_DATA, i.policy))
431 throw runtime_error("saveData failed");
434 case DataType::KEY_AES:
435 if(CKM_API_SUCCESS != m_mgr->createKeyAES(256, i.alias, i.policy))
436 throw runtime_error("createKeyAES failed");
439 case DataType::CHAIN_CERT_0: // PKCS
440 if(CKM_API_SUCCESS != m_mgr->savePKCS12(i.alias, pkcs, i.policy, i.policy))
441 throw runtime_error("savePkcs12 failed");
445 throw runtime_error("unsupported data type");
453 void SchemeTest::ReadAll(bool useWrongPass) {
456 for(const auto& g:GROUPS) {
457 for(const auto& i:g.items) {
459 Password pass = i.policy.password;
468 case DataType::BINARY_DATA:
470 RawBuffer receivedData;
471 ret = m_mgr->getData(i.alias, pass, receivedData);
472 BOOST_REQUIRE_MESSAGE(useWrongPass || receivedData == TEST_DATA,
473 "Received data is different for " << i.alias);
477 case DataType::KEY_AES:
478 case DataType::KEY_RSA_PRIVATE:
479 case DataType::KEY_RSA_PUBLIC:
481 KeyShPtr receivedKey;
482 ret = m_mgr->getKey(i.alias, pass, receivedKey);
486 case DataType::CERTIFICATE:
488 CertificateShPtr receivedCert;
489 ret = m_mgr->getCertificate(i.alias, pass, receivedCert);
493 case DataType::CHAIN_CERT_0: // pkcs
496 ret = m_mgr->getPKCS12(i.alias, pass, pass, pkcs);
501 BOOST_FAIL("Unsupported data type " << i.type);
504 if(i.policy.extractable) {
506 BOOST_REQUIRE_MESSAGE(ret == CKM_API_ERROR_AUTHENTICATION_FAILED,
507 "Reading item " << i.alias << " should fail with " <<
508 CKM_API_ERROR_AUTHENTICATION_FAILED << " got: " << ret);
510 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "Reading item " << i.alias <<
511 " failed with " << ret);
514 BOOST_REQUIRE_MESSAGE(ret == CKM_API_ERROR_NOT_EXPORTABLE, "Item " << i.alias <<
515 " should not be exportable");
520 void SchemeTest::SignVerify() {
523 for(const auto& g:GROUPS) {
524 if(g.type == Group::KEY_PAIR_RSA) {
525 BOOST_REQUIRE_MESSAGE(g.items.size() == 2, "Wrong number of keys");
526 BOOST_REQUIRE_MESSAGE(g.items[0].type == DataType::KEY_RSA_PRIVATE &&
527 g.items[1].type == DataType::KEY_RSA_PUBLIC, "Wrong key");
529 SignVerifyItem(g.items[0], g.items[1]);
531 for(const auto& i:g.items) {
533 case DataType::CHAIN_CERT_0:
534 SignVerifyItem(i, i);
545 void SchemeTest::EncryptDecrypt() {
548 for(const auto& g:GROUPS) {
549 if(g.type == Group::KEY_PAIR_RSA) {
550 BOOST_REQUIRE_MESSAGE(g.items.size() == 2, "Wrong number of keys");
551 BOOST_REQUIRE_MESSAGE(g.items[0].type == DataType::KEY_RSA_PRIVATE &&
552 g.items[1].type == DataType::KEY_RSA_PUBLIC, "Wrong key");
554 EncryptDecryptItem(g.items[0], g.items[1]);
556 for(const auto& i:g.items) {
558 case DataType::KEY_AES:
559 EncryptDecryptItem(i);
562 case DataType::CHAIN_CERT_0:
563 EncryptDecryptItem(i, i);
574 void SchemeTest::CreateChain() {
577 for(const auto& g:GROUPS) {
578 if(g.type == Group::CERT_CHAIN) {
579 BOOST_REQUIRE_MESSAGE(g.items.size() == CHAIN_SIZE, "Not enough certificates");
580 for(const auto& c:g.items)
581 BOOST_REQUIRE_MESSAGE(c.type == DataType::CERTIFICATE, "Wrong item type");
582 Items trusted(CHAIN_SIZE-1);
583 std::copy(g.items.begin(), g.items.begin() + CHAIN_SIZE-1, trusted.begin());
585 // last one is ee (leaf)
586 CreateChainItem(g.items.back(), trusted);
588 for(const auto& i:g.items) {
589 if(i.type == DataType::CHAIN_CERT_0) // PKCS
590 CreateChainItem(i, { i });
596 void SchemeTest::RemoveAll() {
599 for(const auto& g:GROUPS) {
600 for(const auto& i:g.items) {
601 int ret = m_mgr->removeAlias(i.alias);
602 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
603 "removeAlias() failed with " << ret << " for " << i.alias);
607 size_t SchemeTest::CountObjects() {
608 EnableDirectDbAccess();
611 for(const auto& g:GROUPS) {
612 for(const auto& i:g.items) {
614 // it is assumed that aliases are different
615 m_db->getRows(i.alias, DB_LABEL, DataType::DB_FIRST, DataType::DB_LAST, rows);
622 void SchemeTest::RestoreDb() {
623 restoreFile("key-7654");
624 restoreFile("db-key-7654");
625 restoreFile("db-7654");
627 m_directAccessEnabled = false;
630 void SchemeTest::CheckSchemeVersion(const ItemFilter& filter, int version) {
631 EnableDirectDbAccess();
633 for(const auto& g:GROUPS) {
634 for(const auto& i:g.items) {
635 if(!filter.Matches(i))
639 m_db->getRows(i.alias, DB_LABEL, filter.typeFrom, filter.typeTo, rows);
640 BOOST_REQUIRE_MESSAGE(rows.size() > 0, "No rows found for " << i.alias);
641 for(const auto& r : rows) {
642 BOOST_REQUIRE_MESSAGE(
643 (r.encryptionScheme >> ENC_SCHEME_OFFSET) == version,
644 "Wrong encryption scheme for " << i.alias << ". Expected " << version <<
645 " got: " << (r.encryptionScheme >> ENC_SCHEME_OFFSET));
651 void SchemeTest::EnableDirectDbAccess() {
654 if(m_directAccessEnabled)
657 // direct access to db
659 auto wrappedDKEK = fs.getDKEK();
660 auto keyProvider = KeyProvider(wrappedDKEK, DBPASS);
662 auto wrappedDatabaseDEK = fs.getDBDEK();
663 RawBuffer key = keyProvider.getPureDEK(wrappedDatabaseDEK);
665 m_db.reset(new DB::Crypto(fs.getDBPath(), key));
666 m_directAccessEnabled = true;
669 void SchemeTest::SignVerifyItem(const Item& itemPrv, const Item& itemPub) {
671 KeyShPtr receivedKey;
673 // create/verify signature
674 ret = m_mgr->createSignature(itemPrv.alias,
675 itemPrv.policy.password,
677 HashAlgorithm::SHA512,
678 RSAPaddingAlgorithm::X931,
680 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "createSignature() failed with " << ret <<
681 " for " << itemPrv.alias);
682 ret = m_mgr->verifySignature(itemPub.alias,
683 itemPub.policy.password,
686 HashAlgorithm::SHA512,
687 RSAPaddingAlgorithm::X931);
688 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "verifySignature() failed with " << ret <<
689 " for " << itemPub.alias);
693 void SchemeTest::EncryptDecryptItem(const Item& item) {
694 CryptoAlgorithm algo;
695 RawBuffer iv = createRandomBuffer(IV_LEN);
696 RawBuffer encrypted, decrypted;
699 algo.setParam(ParamName::ALGO_TYPE, AlgoType::AES_GCM);
700 algo.setParam(ParamName::ED_IV, iv);
702 ret = m_mgr->encrypt(algo, item.alias, item.policy.password, TEST_DATA, encrypted);
703 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "encrypt() failed iwth " << ret << " for " <<
706 ret = m_mgr->decrypt(algo, item.alias, item.policy.password, encrypted, decrypted);
707 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "decrypt() failed iwth " << ret << " for " <<
710 BOOST_REQUIRE_MESSAGE(decrypted == TEST_DATA, "Decrypted data not equal to original");
713 void SchemeTest::EncryptDecryptItem(const Item& itemPrv, const Item& itemPub) {
714 CryptoAlgorithm algo;
715 RawBuffer encrypted, decrypted;
718 algo.setParam(ParamName::ALGO_TYPE, AlgoType::RSA_OAEP);
720 ret = m_mgr->encrypt(algo, itemPub.alias, itemPub.policy.password, TEST_DATA, encrypted);
721 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "encrypt() failed iwth " << ret << " for " <<
724 ret = m_mgr->decrypt(algo, itemPrv.alias, itemPrv.policy.password, encrypted, decrypted);
725 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS, "decrypt() failed iwth " << ret << " for " <<
728 BOOST_REQUIRE_MESSAGE(decrypted == TEST_DATA, "Decrypted data not equal to original");
731 void SchemeTest::CreateChainItem(const Item& leaf, const Items& certs) {
732 CertificateShPtrVector chain;
735 if(!leaf.policy.extractable || !leaf.policy.password.empty())
738 for(const auto& i : certs) {
739 if(!i.policy.extractable || !i.policy.password.empty())
741 trusted.push_back(i.alias);
744 CertificateShPtr leafCrt;
745 int ret = m_mgr->getCertificate(leaf.alias, leaf.policy.password, leafCrt);
746 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
747 "getCertificate failed with " << ret << " for " <<
750 ret = m_mgr->getCertificateChain(leafCrt, AliasVector(), trusted, false, chain);
751 BOOST_REQUIRE_MESSAGE(ret == CKM_API_SUCCESS,
752 "getCertificateChain() failed with " << ret);
753 BOOST_REQUIRE_MESSAGE(chain.size() == CHAIN_LEN, "Wrong chain length: " << chain.size());