2 * Copyright (c) 2016 - 2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Kyungwook Tak <k.tak@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
18 * @file test_key-provider.cpp
19 * @author Kyungwook Tak (k.tak@samsung.com)
24 #include <boost_macros_wrapper.h>
25 #include <exception.h>
26 #include <key-provider.h>
27 #include <test_common.h>
30 #include "crypto-backend.h"
35 const Password PASSWORD = "12345TIZEN12345AAAAAAAAA";
36 const Password INCORRECT_PASSWORD = "AAAAAAAAAAAAAAAAAAAAA";
37 const Password NEW_PASSWORD = "NEW12345TIZEN12345NEW";
39 const std::string USERNAME = "SOFTWARE_CENTER_SYSTEM_SW_LAB";
40 const std::string CLIENT_ID = "SAMPLE_CLIENT_ID_1";
42 constexpr uint32_t KEYCOMPONENT_VERSION = 2; // keep it in sync with key-provider.cpp
45 RawBuffer toRawBuffer(const T &data)
48 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
49 output.assign(ptr, ptr + sizeof(T));
53 RawBuffer makeDefaultWrappedDomainKEK()
56 BOOST_REQUIRE_NO_THROW(wdkek = KeyProvider::generateDomainKEK(USERNAME, PASSWORD));
57 BOOST_REQUIRE(!wdkek.empty());
61 KeyProvider makeDefaultKeyProvider()
64 RawBuffer wdkek = makeDefaultWrappedDomainKEK();
66 BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
67 BOOST_REQUIRE_MESSAGE(kp.isInitialized(), "KeyProvider created, but uninitialized");
71 RawBuffer makeDefaultWrappedDomainKEK(CryptoBackend backend)
73 struct TestKeyProvider : public KeyProvider {
74 using KeyProvider::KeyProvider;
76 void setBackend(CryptoBackend backend) {
77 BOOST_REQUIRE(m_domainKEK);
78 m_domainKEK->info.backend = static_cast<uint32_t>(backend);
82 auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK();
83 TestKeyProvider kp(wrappedDKEKbuffer, PASSWORD);
84 kp.setBackend(backend);
85 return kp.getWrappedDomainKEK(PASSWORD);
88 void checkVersionAndBackend(const RawBuffer& wrappedDomainKEKbuffer)
90 DomainKEKAndInfo wdkek(wrappedDomainKEKbuffer);
91 BOOST_REQUIRE(wdkek.info.version == KEYCOMPONENT_VERSION);
92 #if SE_BACKEND_ENABLED
93 BOOST_REQUIRE(wdkek.info.backend == static_cast<uint32_t>(CryptoBackend::SecureElement));
95 BOOST_REQUIRE(wdkek.info.backend == static_cast<uint32_t>(CryptoBackend::OpenSSL));
99 RawBuffer convertToOldFormat(const RawBuffer& wrappedDKEKbuffer)
101 DomainKEKAndInfo wrappedDKEK(wrappedDKEKbuffer);
102 DEKAndInfo wrappedOldDKEK;
104 // hacky conversion to old key format
105 wrappedOldDKEK.setKeyInfo(static_cast<KeyInfo>(wrappedDKEK.info));
106 memcpy(wrappedOldDKEK.key, wrappedDKEK.key, wrappedDKEK.info.keyLength);
108 return toRawBuffer(wrappedOldDKEK);
111 } // anonymous namespace
113 BOOST_AUTO_TEST_SUITE(KEY_PROVIDER_TEST)
115 NEGATIVE_TEST_CASE(KeyAndInfo_ctor_wrong_size)
117 RawBuffer buffer(sizeof(DomainKEKAndInfo) + 1, 0);
118 BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
121 BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
123 buffer.resize(sizeof(DEKAndInfo) + 1, 0);
124 BOOST_REQUIRE_THROW((DEKAndInfo(buffer)), Exc::InternalError);
127 BOOST_REQUIRE_THROW((DEKAndInfo(buffer)), Exc::InternalError);
130 NEGATIVE_TEST_CASE(KeyAndInfo_ctor_wrong_key_length)
132 DomainKEKAndInfo dkek;
133 dkek.info.keyLength = MAX_KEY_SIZE+1;
134 auto buffer = toRawBuffer(dkek);
136 BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
139 dek.info.keyLength = MAX_KEY_SIZE+1;
140 auto buffer2 = toRawBuffer(dek);
142 BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer2)), Exc::InternalError);
145 NEGATIVE_TEST_CASE(KeyAndInfo_ctor_wrong_client)
147 DomainKEKAndInfo dkek;
148 memset(&dkek.info.client, 'a', MAX_CLIENT_ID_SIZE);
149 auto buffer = toRawBuffer(dkek);
151 BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer)), Exc::InternalError);
154 memset(&dek.info.client, 'a', MAX_CLIENT_ID_SIZE);
155 auto buffer2 = toRawBuffer(dek);
157 BOOST_REQUIRE_THROW((DomainKEKAndInfo(buffer2)), Exc::InternalError);
160 POSITIVE_TEST_CASE(KeyAndInfo_ctor)
162 BOOST_REQUIRE_NO_THROW(DomainKEKAndInfo(RawBuffer(sizeof(DomainKEKAndInfo), 0)));
164 BOOST_REQUIRE_NO_THROW(DEKAndInfo(RawBuffer(sizeof(DEKAndInfo), 0)));
167 NEGATIVE_TEST_CASE(KeyProvider_wrong_size)
169 RawBuffer wdkek = makeDefaultWrappedDomainKEK();
173 BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
174 BOOST_REQUIRE(!kp.isInitialized());
178 BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
179 BOOST_REQUIRE(!kp.isInitialized());
182 NEGATIVE_TEST_CASE(KeyProvider_garbage)
184 BOOST_REQUIRE_THROW(KeyProvider(RawBuffer(sizeof(DomainKEKAndInfo)), PASSWORD),
188 NEGATIVE_TEST_CASE(KeyDomainKek_invalid_password)
191 RawBuffer wdkek = makeDefaultWrappedDomainKEK();
193 BOOST_REQUIRE_THROW(kp = KeyProvider(wdkek, INCORRECT_PASSWORD), Exc::AuthenticationFailed);
194 BOOST_REQUIRE_MESSAGE(!kp.isInitialized(), "KeyProvider not created, but initialized");
197 POSITIVE_TEST_CASE(KeygetPureDomainKEK)
199 KeyProvider kp = makeDefaultKeyProvider();
202 BOOST_REQUIRE_NO_THROW(dkek = kp.getPureDomainKEK());
203 BOOST_REQUIRE(dkek.size() <= MAX_KEY_SIZE);
205 checkVersionAndBackend(kp.getWrappedDomainKEK("whatever"));
208 NEGATIVE_TEST_CASE(KeygetPureDomainKEK_uninitialized)
212 BOOST_REQUIRE_THROW(kp.getPureDomainKEK(), Exc::InternalError);
215 POSITIVE_TEST_CASE(KeyGetWrappedDomainKEK)
217 KeyProvider kp = makeDefaultKeyProvider();
220 BOOST_REQUIRE_NO_THROW(wdkek = kp.getWrappedDomainKEK("whatever"));
221 BOOST_REQUIRE(!wdkek.empty());
224 NEGATIVE_TEST_CASE(KeyGetWrappedDomainKEK_uninitialized)
227 BOOST_REQUIRE_THROW(kp.getWrappedDomainKEK("whatever"), Exc::InternalError);
230 POSITIVE_TEST_CASE(KeyGenerateDEK)
232 KeyProvider kp = makeDefaultKeyProvider();
235 BOOST_REQUIRE_NO_THROW(wdek = kp.generateDEK(CLIENT_ID));
236 BOOST_REQUIRE(!wdek.empty());
239 NEGATIVE_TEST_CASE(KeyGenerateDEK_uninitialized)
243 BOOST_REQUIRE_THROW(kp.generateDEK(CLIENT_ID), Exc::InternalError);
246 POSITIVE_TEST_CASE(KeyGetPureDEK)
248 KeyProvider kp = makeDefaultKeyProvider();
251 BOOST_REQUIRE_NO_THROW(wdek = kp.generateDEK(CLIENT_ID));
252 BOOST_REQUIRE(!wdek.empty());
254 BOOST_REQUIRE_NO_THROW(dek = kp.getPureDEK(wdek));
255 BOOST_REQUIRE(dek.size() <= MAX_KEY_SIZE);
258 NEGATIVE_TEST_CASE(KeyGetPureDEK_uninitialized)
261 RawBuffer wdek(sizeof(DEKAndInfo));
263 BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
266 NEGATIVE_TEST_CASE(KeyGetPureDEK_wrong_size)
268 KeyProvider kp = makeDefaultKeyProvider();
271 BOOST_REQUIRE_NO_THROW(wdek = kp.generateDEK(CLIENT_ID));
274 BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
278 BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
281 NEGATIVE_TEST_CASE(KeyGetPureDEK_garbage)
283 KeyProvider kp = makeDefaultKeyProvider();
284 RawBuffer wdek(sizeof(DEKAndInfo));
286 BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
289 POSITIVE_TEST_CASE(WrappedDomainKEK)
291 RawBuffer wdkekBuffer = makeDefaultWrappedDomainKEK();
293 checkVersionAndBackend(wdkekBuffer);
296 POSITIVE_TEST_CASE(KeyReencrypt)
298 RawBuffer wdkek = makeDefaultWrappedDomainKEK();
300 KeyProvider keyProvider;
302 BOOST_REQUIRE_NO_THROW(keyProvider = KeyProvider(wdkek, PASSWORD));
303 BOOST_REQUIRE_NO_THROW(wdkek2 = keyProvider.getWrappedDomainKEK(NEW_PASSWORD));
304 BOOST_REQUIRE(!wdkek2.empty());
307 POSITIVE_TEST_CASE(KeyGetPureDEK_after_reencrypt)
310 RawBuffer wdek, dek, wdkek2;
311 RawBuffer wdkek = makeDefaultWrappedDomainKEK();
313 BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
314 BOOST_REQUIRE_NO_THROW(wdkek2 = kp.getWrappedDomainKEK(NEW_PASSWORD));
315 BOOST_REQUIRE(!wdkek2.empty());
317 BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek2, NEW_PASSWORD));
319 BOOST_REQUIRE_NO_THROW(wdek = kp.generateDEK(CLIENT_ID));
320 BOOST_REQUIRE(!wdek.empty());
322 BOOST_REQUIRE_NO_THROW(dek = kp.getPureDEK(wdek));
323 BOOST_REQUIRE(dek.size() <= MAX_KEY_SIZE);
326 POSITIVE_TEST_CASE(dek_and_info)
330 auto salt = createRandom(20);
331 memcpy(dai.info.salt, salt.data(), sizeof(dai.info.salt));
332 BOOST_REQUIRE_NO_THROW(dai.setKeyInfoClient("key_info_client"));
333 dai.info.keyLength = 10;
336 BOOST_REQUIRE_NO_THROW(dai2.setKeyInfo(dai.info));
338 BOOST_REQUIRE(dai.info.keyLength == dai2.info.keyLength);
339 BOOST_REQUIRE(memcmp(dai.info.salt, dai2.info.salt, sizeof(dai.info.salt)) == 0);
340 BOOST_REQUIRE(memcmp(dai.info.client, dai2.info.client, sizeof(dai.info.client)) == 0);
343 NEGATIVE_TEST_CASE(dek_and_info)
346 BOOST_REQUIRE_THROW(dai.setKeyInfoClient("key_info_client_waaaaay_too_long"),
350 dai2.info.keyLength = MAX_KEY_SIZE + 1;
351 auto buffer = toRawBuffer(dai2);
352 BOOST_REQUIRE_THROW(new DEKAndInfo((buffer)), Exc::InternalError);
354 // missing NULL termination in dai3.info.client
355 RawBuffer garbage(0x01, sizeof(DEKAndInfo));
356 BOOST_REQUIRE_THROW(new DEKAndInfo((garbage)), Exc::InternalError);
359 POSITIVE_TEST_CASE(moves)
361 KeyProvider kp = makeDefaultKeyProvider();
364 BOOST_REQUIRE_NO_THROW(dkek = kp.getPureDomainKEK());
365 BOOST_REQUIRE(dkek.size() <= MAX_KEY_SIZE);
368 KeyProvider kp2(std::move(kp));
369 KeyProvider kp3 = std::move(kp2);
371 BOOST_REQUIRE(!kp.isInitialized());
372 BOOST_REQUIRE(!kp2.isInitialized());
373 BOOST_REQUIRE(kp3.isInitialized());
376 BOOST_REQUIRE_NO_THROW(dkek3 = kp3.getPureDomainKEK());
377 BOOST_REQUIRE(dkek == dkek3);
379 BOOST_REQUIRE_MESSAGE(false, "Unknown exception on moving KeyProvider");
383 NEGATIVE_TEST_CASE(moves)
385 KeyProvider kp = makeDefaultKeyProvider();
386 KeyProvider kp2(std::move(kp));
388 BOOST_REQUIRE_THROW(kp.getPureDomainKEK(), Exc::InternalError);
391 NEGATIVE_TEST_CASE(migration)
393 // migration may only happen in case of openssl backend
394 auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK(CryptoBackend::OpenSSL);
396 KeyProvider kp(RawBuffer(), "whatever");
397 BOOST_REQUIRE(!kp.isInitialized());
399 // migration possible only from old shorter format
400 BOOST_REQUIRE_THROW(kp.migrateDomainKEK(wrappedDKEKbuffer, PASSWORD), Exc::InternalError);
401 BOOST_REQUIRE(!kp.isInitialized());
403 auto wrappedOldDKEKbuffer = convertToOldFormat(wrappedDKEKbuffer);
405 KeyProvider kp2(wrappedOldDKEKbuffer, PASSWORD);
406 BOOST_REQUIRE(!kp2.isInitialized());
407 BOOST_REQUIRE_THROW(kp2.migrateDomainKEK(wrappedOldDKEKbuffer, INCORRECT_PASSWORD),
408 Exc::AuthenticationFailed);
409 BOOST_REQUIRE(!kp2.isInitialized());
412 POSITIVE_TEST_CASE(migration)
414 // migration may only happen in case of openssl backend
415 auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK(CryptoBackend::OpenSSL);
416 KeyProvider kp(wrappedDKEKbuffer, PASSWORD);
418 auto wrappedOldDKEKbuffer = convertToOldFormat(wrappedDKEKbuffer);
421 BOOST_REQUIRE_NO_THROW(kp2 = KeyProvider(wrappedOldDKEKbuffer, PASSWORD));
422 BOOST_REQUIRE(!kp2.isInitialized());
423 BOOST_REQUIRE_NO_THROW(kp2.migrateDomainKEK(wrappedOldDKEKbuffer, PASSWORD));
424 BOOST_REQUIRE(kp2.isInitialized());
426 BOOST_REQUIRE(kp.getPureDomainKEK() == kp2.getPureDomainKEK());
428 checkVersionAndBackend(kp2.getWrappedDomainKEK("whatever"));
431 NEGATIVE_TEST_CASE(version)
433 auto wrappedDKEKbuffer = makeDefaultWrappedDomainKEK();
434 DomainKEKAndInfo wrappedDKEK(wrappedDKEKbuffer);
435 wrappedDKEK.info.version = 0;
437 auto wrappedWrongVersionBuffer = toRawBuffer(wrappedDKEK);
438 BOOST_REQUIRE_THROW(KeyProvider(wrappedWrongVersionBuffer, PASSWORD), Exc::InternalError);
441 NEGATIVE_TEST_CASE(backend)
443 auto throwForBackend = [](CryptoBackend backend){
444 BOOST_REQUIRE_THROW(KeyProvider(makeDefaultWrappedDomainKEK(backend), PASSWORD),
448 throwForBackend(CryptoBackend::None);
449 throwForBackend(CryptoBackend::TrustZone);
450 throwForBackend(static_cast<CryptoBackend>(999));
452 #ifndef SE_BACKEND_ENABLED
453 throwForBackend(CryptoBackend::SecureElement);
457 #ifdef SE_BACKEND_ENABLED
458 POSITIVE_TEST_CASE(backend)
461 BOOST_REQUIRE_NO_THROW(
462 kp = KeyProvider(makeDefaultWrappedDomainKEK(CryptoBackend::OpenSSL), PASSWORD));
463 DomainKEKAndInfo wdkek(kp.getWrappedDomainKEK("whatever"));
464 BOOST_REQUIRE(wdkek.info.backend == static_cast<uint32_t>(CryptoBackend::OpenSSL));
468 BOOST_AUTO_TEST_SUITE_END()