2 * Copyright (c) 2014 - 2019 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 #include <exception.h>
18 #include <key-provider.h>
19 #include <dpl/log/log.h>
29 RawBuffer toRawBuffer(const T &data)
32 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
33 output.assign(ptr, ptr + sizeof(T));
37 // You cannot use toRawBuffer template with pointers
39 RawBuffer toRawBuffer(T *)
41 class NoPointerAllowed {
48 int encryptAes256Gcm(const unsigned char *plaintext,
49 int plaintext_len, const unsigned char *key, const unsigned char *iv,
50 unsigned char *ciphertext, unsigned char *tag)
54 int ciphertext_len = 0;
56 if (!(ctx = EVP_CIPHER_CTX_new()))
57 return OPENSSL_ENGINE_ERROR;
59 if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
60 return OPENSSL_ENGINE_ERROR;
62 if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
63 return OPENSSL_ENGINE_ERROR;
65 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
66 return OPENSSL_ENGINE_ERROR;
68 if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
69 return OPENSSL_ENGINE_ERROR;
73 if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
74 return OPENSSL_ENGINE_ERROR;
76 ciphertext_len += len;
78 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag))
79 return OPENSSL_ENGINE_ERROR;
81 EVP_CIPHER_CTX_free(ctx);
83 return ciphertext_len;
86 int decryptAes256Gcm(const unsigned char *ciphertext,
87 int ciphertext_len, unsigned char *tag, const unsigned char *key,
88 const unsigned char *iv, unsigned char *plaintext)
95 if (!(ctx = EVP_CIPHER_CTX_new()))
96 return OPENSSL_ENGINE_ERROR;
98 if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
99 return OPENSSL_ENGINE_ERROR;
101 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
102 return OPENSSL_ENGINE_ERROR;
104 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
105 return OPENSSL_ENGINE_ERROR;
107 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag))
108 return OPENSSL_ENGINE_ERROR;
110 if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
111 return OPENSSL_ENGINE_ERROR;
115 if (!(ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len)))
116 return OPENSSL_ENGINE_ERROR;
118 EVP_CIPHER_CTX_free(ctx);
121 plaintext_len += len;
122 return plaintext_len;
128 typedef std::array<uint8_t, MAX_KEY_SIZE> KeyData;
130 // derives a key used for DomainKEK encryption (aka PKEK1) from random salt & user password
131 KeyData makePKEK1(const KeyComponentsInfo& keyInfo, const Password &password)
133 std::string concatPasswordClient(password.c_str());
134 concatPasswordClient += std::string(keyInfo.client);
137 if (!PKCS5_PBKDF2_HMAC_SHA1(concatPasswordClient.c_str(),
138 concatPasswordClient.size(),
144 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
149 // derives a key used for DB DEK encryption (aka PKEK2) from DomainKEK and user id
150 KeyData makePKEK2(const uint8_t *domainKEK, const std::string &user)
153 if (!PKCS5_PBKDF2_HMAC_SHA1(user.c_str(),
160 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
167 bool randomize(uint8_t (&array)[N])
169 return RAND_bytes(array, N) == 1;
172 } // anonymous namespace
174 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
176 memset(&wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
179 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char
182 memcpy(&wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
184 if (wrappedKeyAndInfo.keyInfo.keyLength > sizeof(wrappedKeyAndInfo.wrappedKey)) {
185 ThrowErr(Exc::InternalError,
186 "Wrapped key info is corrupted. Key length exceeds the size of the key buffer.");
189 size_t maxlen = sizeof(wrappedKeyAndInfo.keyInfo.client);
190 if (strnlen(wrappedKeyAndInfo.keyInfo.client, maxlen) == maxlen) {
191 ThrowErr(Exc::InternalError,
192 "Wrapped key info is corrupted. Client id is not NULL terminated.");
196 WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
198 return wrappedKeyAndInfo;
201 void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const unsigned int length)
203 wrappedKeyAndInfo.keyInfo.keyLength = length;
206 void WrappedKeyAndInfoContainer::setKeyInfoClient(const std::string resized_client)
208 if (resized_client.size() >= sizeof(wrappedKeyAndInfo.keyInfo.client)) {
209 ThrowErr(Exc::InternalError, "Client name too long");
212 strcpy(wrappedKeyAndInfo.keyInfo.client, resized_client.c_str());
215 void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt,
218 memcpy(wrappedKeyAndInfo.keyInfo.salt, salt, size);
221 void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo
224 memcpy(&(wrappedKeyAndInfo.keyInfo), keyComponentsInfo,
225 sizeof(KeyComponentsInfo));
228 WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
232 KeyAndInfoContainer::KeyAndInfoContainer()
234 memset(&keyAndInfo, 0, sizeof(KeyAndInfo));
237 KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
239 memcpy(&keyAndInfo, data, sizeof(KeyAndInfo));
242 KeyAndInfo &KeyAndInfoContainer::getKeyAndInfo()
247 void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
249 keyAndInfo.keyInfo.keyLength = length;
252 void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
254 memcpy(&(keyAndInfo.keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
257 KeyAndInfoContainer::~KeyAndInfoContainer()
260 char *ptr = reinterpret_cast<char *>(&keyAndInfo);
261 memset(ptr, 0, sizeof(KeyAndInfo));
264 for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) {
266 LogError("Write memory error! Memory used by key was not owerwritten.");
270 KeyProvider::KeyProvider() :
272 m_isInitialized(false)
274 LogDebug("Created empty KeyProvider");
277 KeyProvider::KeyProvider(
278 const RawBuffer &domainKEKInWrapForm,
279 const Password &password) :
280 m_kmcDKEK(new KeyAndInfoContainer()),
281 m_isInitialized(true)
283 if (!m_isInitialized)
284 ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
286 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
287 LogError("input size:" << domainKEKInWrapForm.size()
288 << " Expected: " << sizeof(WrappedKeyAndInfo));
289 ThrowErr(Exc::InternalError,
290 "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
293 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(
294 domainKEKInWrapForm.data());
296 KeyData PKEK1 = makePKEK1(wkmcDKEK.getWrappedKeyAndInfo().keyInfo, password);
299 if (0 > (keyLength = decryptAes256Gcm(
300 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
301 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
302 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag,
304 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
305 m_kmcDKEK->getKeyAndInfo().key))) {
306 ThrowErr(Exc::AuthenticationFailed,
307 "VerifyDomainKEK failed in KeyProvider Constructor");
310 m_kmcDKEK->setKeyInfo(&(wkmcDKEK.getWrappedKeyAndInfo().keyInfo));
311 m_kmcDKEK->setKeyInfoKeyLength((unsigned int)keyLength);
314 KeyProvider &KeyProvider::operator=(KeyProvider &&second)
316 LogDebug("Moving KeyProvider");
321 m_isInitialized = second.m_isInitialized;
322 m_kmcDKEK = second.m_kmcDKEK;
323 second.m_isInitialized = false;
324 second.m_kmcDKEK = NULL;
328 KeyProvider::KeyProvider(KeyProvider &&second)
330 LogDebug("Moving KeyProvider");
331 m_isInitialized = second.m_isInitialized;
332 m_kmcDKEK = second.m_kmcDKEK;
333 second.m_isInitialized = false;
334 second.m_kmcDKEK = NULL;
337 bool KeyProvider::isInitialized()
339 return m_isInitialized;
342 RawBuffer KeyProvider::getPureDomainKEK()
344 if (!m_isInitialized)
345 ThrowErr(Exc::InternalError, "Object not initialized!");
348 return RawBuffer(m_kmcDKEK->getKeyAndInfo().key,
349 (m_kmcDKEK->getKeyAndInfo().key) +
350 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength);
353 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
355 if (!m_isInitialized)
356 ThrowErr(Exc::InternalError, "Object not initialized!");
358 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
359 wkmcDKEK.setKeyInfo(&(m_kmcDKEK->getKeyAndInfo().keyInfo));
361 KeyData PKEK1 = makePKEK1(wkmcDKEK.getWrappedKeyAndInfo().keyInfo, password);
363 int wrappedKeyLength;
365 if (0 > (wrappedKeyLength = encryptAes256Gcm(
366 m_kmcDKEK->getKeyAndInfo().key,
367 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
369 m_kmcDKEK->getKeyAndInfo().keyInfo.iv,
370 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
371 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
372 ThrowErr(Exc::InternalError, "WrapDKEK Failed in KeyProvider::getDomainKEK");
374 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
376 LogDebug("getDomainKEK(password) Success");
377 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
381 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
383 if (!m_isInitialized)
384 ThrowErr(Exc::InternalError, "Object not initialized!");
386 if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
387 LogError("input size:" << DEKInWrapForm.size()
388 << " Expected: " << sizeof(WrappedKeyAndInfo));
389 ThrowErr(Exc::InternalError,
390 "buffer doesn't have proper size to store "
391 "WrappedKeyAndInfo in KeyProvider::getPureDEK");
394 KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
395 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(
396 DEKInWrapForm.data());
398 KeyData PKEK2 = makePKEK2(m_kmcDKEK->getKeyAndInfo().key,
399 wkmcDEK.getWrappedKeyAndInfo().keyInfo.client);
402 if (0 > (keyLength = decryptAes256Gcm(
403 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
404 wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
405 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
407 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
408 kmcDEK.getKeyAndInfo().key)))
409 ThrowErr(Exc::InternalError,
410 "UnwrapDEK Failed in KeyProvider::getPureDEK");
412 kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
414 LogDebug("getPureDEK SUCCESS");
416 kmcDEK.getKeyAndInfo().key,
417 (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
420 RawBuffer KeyProvider::generateDEK(const ClientId &client)
422 if (!m_isInitialized)
423 ThrowErr(Exc::InternalError, "Object not initialized!");
425 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
426 std::string resized_client;
428 if (client.length() < MAX_CLIENT_ID_SIZE)
429 resized_client = client;
431 resized_client = client.substr(0, MAX_CLIENT_ID_SIZE - 1);
433 uint8_t key[MAX_KEY_SIZE];
435 if (!randomize(key) || !randomize(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv))
436 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
438 KeyData PKEK2 = makePKEK2(m_kmcDKEK->getKeyAndInfo().key, resized_client);
440 int wrappedKeyLength;
441 if (0 > (wrappedKeyLength = encryptAes256Gcm(
443 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
445 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
446 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
447 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag)))
448 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
450 wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
451 wkmcDEK.setKeyInfoClient(resized_client);
453 LogDebug("GenerateDEK Success");
454 return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
457 RawBuffer KeyProvider::reencrypt(
458 const RawBuffer &domainKEKInWrapForm,
459 const Password &oldPass,
460 const Password &newPass)
462 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
463 LogError("input size:" << domainKEKInWrapForm.size()
464 << " Expected: " << sizeof(WrappedKeyAndInfo));
465 ThrowErr(Exc::InternalError,
466 "buffer doesn't have proper size to store "
467 "WrappedKeyAndInfo in KeyProvider::reencrypt");
470 WrappedKeyAndInfoContainer wkmcOldDKEK = WrappedKeyAndInfoContainer(
471 domainKEKInWrapForm.data());
472 WrappedKeyAndInfoContainer wkmcNewDKEK = WrappedKeyAndInfoContainer();
473 KeyAndInfoContainer kmcDKEK = KeyAndInfoContainer();
475 KeyData PKEK1 = makePKEK1(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo, oldPass);
478 if (0 > (keyLength = decryptAes256Gcm(
479 wkmcOldDKEK.getWrappedKeyAndInfo().wrappedKey,
480 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
481 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.tag,
483 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.iv,
484 kmcDKEK.getKeyAndInfo().key)))
485 ThrowErr(Exc::AuthenticationFailed, "Incorrect Old Password ");
487 kmcDKEK.setKeyInfo(&(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo));
488 kmcDKEK.setKeyInfoKeyLength((unsigned int)keyLength);
490 PKEK1 = makePKEK1(wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo, newPass);
492 wkmcNewDKEK.setKeyInfo(&(kmcDKEK.getKeyAndInfo().keyInfo));
494 int wrappedKeyLength = 0;
495 if (0 > (wrappedKeyLength = encryptAes256Gcm(
496 kmcDKEK.getKeyAndInfo().key,
497 kmcDKEK.getKeyAndInfo().keyInfo.keyLength,
499 kmcDKEK.getKeyAndInfo().keyInfo.iv,
500 wkmcNewDKEK.getWrappedKeyAndInfo().wrappedKey,
501 wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
502 ThrowErr(Exc::InternalError,
503 "UpdateDomainKEK in KeyProvider::reencrypt Failed");
505 wkmcNewDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
507 LogDebug("reencrypt SUCCESS");
508 return toRawBuffer(wkmcNewDKEK.getWrappedKeyAndInfo());
511 RawBuffer KeyProvider::generateDomainKEK(
512 const std::string &user,
513 const Password &userPassword)
515 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
516 uint8_t key[MAX_KEY_SIZE];
517 int wrappedKeyLength;
519 wkmcDKEK.setKeyInfoClient(user);
521 if (!randomize(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt) ||
523 !randomize(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv)) {
524 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
527 KeyData PKEK1 = makePKEK1(wkmcDKEK.getWrappedKeyAndInfo().keyInfo, userPassword);
529 if (0 > (wrappedKeyLength = encryptAes256Gcm(
533 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
534 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
535 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
536 ThrowErr(Exc::InternalError,
537 "GenerateDomainKEK Failed in KeyProvider::generateDomainKEK");
539 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
540 wkmcDKEK.setKeyInfoClient(user);
542 LogDebug("generateDomainKEK Success");
543 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
546 int KeyProvider::initializeLibrary()
548 LogDebug("initializeLibrary Success");
552 int KeyProvider::closeLibrary()
554 LogDebug("closeLibrary Success");
558 KeyProvider::~KeyProvider()
560 LogDebug("KeyProvider Destructor");