2 * Copyright (c) 2014 - 2018 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>
24 CKM::RawBuffer toRawBuffer(const T &data)
26 CKM::RawBuffer output;
27 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
28 output.assign(ptr, ptr + sizeof(T));
32 // You cannot use toRawBuffer template with pointers
34 CKM::RawBuffer toRawBuffer(T *)
36 class NoPointerAllowed {
40 return CKM::RawBuffer();
43 } // anonymous namespace
47 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
49 wrappedKeyAndInfo = new WrappedKeyAndInfo;
50 memset(wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
53 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char
56 wrappedKeyAndInfo = new WrappedKeyAndInfo;
57 memcpy(wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
60 WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
62 return *wrappedKeyAndInfo;
65 void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const unsigned int length)
67 wrappedKeyAndInfo->keyInfo.keyLength = length;
70 void WrappedKeyAndInfoContainer::setKeyInfoClient(const std::string resized_client)
73 wrappedKeyAndInfo->keyInfo.client,
74 resized_client.c_str(),
75 MAX_CLIENT_ID_SIZE-1);
78 void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt,
81 memcpy(wrappedKeyAndInfo->keyInfo.salt, salt, size);
84 void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo
87 memcpy(&(wrappedKeyAndInfo->keyInfo), keyComponentsInfo,
88 sizeof(KeyComponentsInfo));
91 WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
93 delete wrappedKeyAndInfo;
96 KeyAndInfoContainer::KeyAndInfoContainer()
98 keyAndInfo = new KeyAndInfo;
99 memset(keyAndInfo, 0, sizeof(KeyAndInfo));
102 KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
104 keyAndInfo = new KeyAndInfo;
105 memcpy(keyAndInfo, data, sizeof(KeyAndInfo));
108 KeyAndInfo &KeyAndInfoContainer::getKeyAndInfo()
113 void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
115 keyAndInfo->keyInfo.keyLength = length;
118 void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
120 memcpy(&(keyAndInfo->keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
123 KeyAndInfoContainer::~KeyAndInfoContainer()
126 char *ptr = reinterpret_cast<char *>(keyAndInfo);
127 memset(ptr, 0, sizeof(KeyAndInfo));
130 for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) {
132 LogError("Write momory error! Memory used by key was not owerwritten.");
138 KeyProvider::KeyProvider() :
140 m_isInitialized(false)
142 LogDebug("Created empty KeyProvider");
145 KeyProvider::KeyProvider(
146 const RawBuffer &domainKEKInWrapForm,
147 const Password &password) :
148 m_kmcDKEK(new KeyAndInfoContainer()),
149 m_isInitialized(true)
151 if (!m_isInitialized)
152 ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
154 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
155 LogError("input size:" << domainKEKInWrapForm.size()
156 << " Expected: " << sizeof(WrappedKeyAndInfo));
157 ThrowErr(Exc::InternalError,
158 "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
161 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(
162 domainKEKInWrapForm.data());
164 char *concat_user_pass = NULL;
165 uint8_t PKEK1[MAX_KEY_SIZE];
167 concat_user_pass = concat_password_user(
168 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.client,
171 if (!PKCS5_PBKDF2_HMAC_SHA1(
173 strlen(concat_user_pass),
174 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
179 delete[] concat_user_pass;
180 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
183 delete[] concat_user_pass;
187 if (0 > (keyLength = decryptAes256Gcm(
188 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
189 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
190 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag,
192 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
193 m_kmcDKEK->getKeyAndInfo().key))) {
194 ThrowErr(Exc::AuthenticationFailed,
195 "VerifyDomainKEK failed in KeyProvider Constructor");
198 m_kmcDKEK->setKeyInfo(&(wkmcDKEK.getWrappedKeyAndInfo().keyInfo));
199 m_kmcDKEK->setKeyInfoKeyLength((unsigned int)keyLength);
202 KeyProvider &KeyProvider::operator=(KeyProvider &&second)
204 LogDebug("Moving KeyProvider");
209 m_isInitialized = second.m_isInitialized;
210 m_kmcDKEK = second.m_kmcDKEK;
211 second.m_isInitialized = false;
212 second.m_kmcDKEK = NULL;
216 KeyProvider::KeyProvider(KeyProvider &&second)
218 LogDebug("Moving KeyProvider");
219 m_isInitialized = second.m_isInitialized;
220 m_kmcDKEK = second.m_kmcDKEK;
221 second.m_isInitialized = false;
222 second.m_kmcDKEK = NULL;
225 bool KeyProvider::isInitialized()
227 return m_isInitialized;
230 RawBuffer KeyProvider::getPureDomainKEK()
232 if (!m_isInitialized)
233 ThrowErr(Exc::InternalError, "Object not initialized!");
236 return RawBuffer(m_kmcDKEK->getKeyAndInfo().key,
237 (m_kmcDKEK->getKeyAndInfo().key) +
238 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength);
241 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
243 if (!m_isInitialized)
244 ThrowErr(Exc::InternalError, "Object not initialized!");
246 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
248 char *concat_user_pass = NULL;
249 uint8_t PKEK1[MAX_KEY_SIZE];
251 concat_user_pass = concat_password_user(
252 m_kmcDKEK->getKeyAndInfo().keyInfo.client,
255 if (!PKCS5_PBKDF2_HMAC_SHA1(
257 strlen(concat_user_pass),
258 m_kmcDKEK->getKeyAndInfo().keyInfo.salt,
263 delete[] concat_user_pass;
264 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
267 delete[] concat_user_pass;
269 wkmcDKEK.setKeyInfo(&(m_kmcDKEK->getKeyAndInfo().keyInfo));
271 int wrappedKeyLength;
273 if (0 > (wrappedKeyLength = encryptAes256Gcm(
274 m_kmcDKEK->getKeyAndInfo().key,
275 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
277 m_kmcDKEK->getKeyAndInfo().keyInfo.iv,
278 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
279 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
280 ThrowErr(Exc::InternalError, "WrapDKEK Failed in KeyProvider::getDomainKEK");
282 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
284 LogDebug("getDomainKEK(password) Success");
285 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
289 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
291 if (!m_isInitialized)
292 ThrowErr(Exc::InternalError, "Object not initialized!");
294 if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
295 LogError("input size:" << DEKInWrapForm.size()
296 << " Expected: " << sizeof(WrappedKeyAndInfo));
297 ThrowErr(Exc::InternalError,
298 "buffer doesn't have proper size to store "
299 "WrappedKeyAndInfo in KeyProvider::getPureDEK");
302 KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
303 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(
304 DEKInWrapForm.data());
306 uint8_t PKEK2[MAX_KEY_SIZE];
309 if (!PKCS5_PBKDF2_HMAC_SHA1(
310 wkmcDEK.getWrappedKeyAndInfo().keyInfo.client,
311 strlen(wkmcDEK.getWrappedKeyAndInfo().keyInfo.client),
312 m_kmcDKEK->getKeyAndInfo().key,
317 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
319 if (0 > (keyLength = decryptAes256Gcm(
320 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
321 wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
322 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
324 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
325 kmcDEK.getKeyAndInfo().key)))
326 ThrowErr(Exc::InternalError,
327 "UnwrapDEK Failed in KeyProvider::getPureDEK");
329 kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
331 LogDebug("getPureDEK SUCCESS");
333 kmcDEK.getKeyAndInfo().key,
334 (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
337 RawBuffer KeyProvider::generateDEK(const ClientId &client)
339 if (!m_isInitialized)
340 ThrowErr(Exc::InternalError, "Object not initialized!");
342 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
343 std::string resized_client;
345 if (client.length() < MAX_CLIENT_ID_SIZE)
346 resized_client = client;
348 resized_client = client.substr(0, MAX_CLIENT_ID_SIZE - 1);
350 uint8_t key[MAX_KEY_SIZE], PKEK2[MAX_KEY_SIZE];
352 if (!RAND_bytes(key, m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength) ||
353 !RAND_bytes(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE))
354 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
356 if (!PKCS5_PBKDF2_HMAC_SHA1(
357 resized_client.c_str(),
358 strlen(resized_client.c_str()),
359 m_kmcDKEK->getKeyAndInfo().key,
364 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
366 int wrappedKeyLength;
368 if (0 > (wrappedKeyLength = encryptAes256Gcm(
370 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
372 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
373 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
374 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag)))
375 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
377 wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
378 wkmcDEK.setKeyInfoClient(resized_client);
380 LogDebug("GenerateDEK Success");
381 return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
384 RawBuffer KeyProvider::reencrypt(
385 const RawBuffer &domainKEKInWrapForm,
386 const Password &oldPass,
387 const Password &newPass)
389 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
390 LogError("input size:" << domainKEKInWrapForm.size()
391 << " Expected: " << sizeof(WrappedKeyAndInfo));
392 ThrowErr(Exc::InternalError,
393 "buffer doesn't have proper size to store "
394 "WrappedKeyAndInfo in KeyProvider::reencrypt");
397 WrappedKeyAndInfoContainer wkmcOldDKEK = WrappedKeyAndInfoContainer(
398 domainKEKInWrapForm.data());
399 WrappedKeyAndInfoContainer wkmcNewDKEK = WrappedKeyAndInfoContainer();
400 KeyAndInfoContainer kmcDKEK = KeyAndInfoContainer();
402 char *concat_user_pass = NULL;
403 uint8_t PKEK1[MAX_KEY_SIZE];
407 concat_user_pass = concat_password_user(
408 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.client,
411 if (!PKCS5_PBKDF2_HMAC_SHA1(
413 strlen(concat_user_pass),
414 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.salt,
419 delete[] concat_user_pass;
420 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
423 delete[] concat_user_pass;
425 if (0 > (keyLength = decryptAes256Gcm(
426 wkmcOldDKEK.getWrappedKeyAndInfo().wrappedKey,
427 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
428 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.tag,
430 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.iv,
431 kmcDKEK.getKeyAndInfo().key)))
432 ThrowErr(Exc::AuthenticationFailed, "Incorrect Old Password ");
434 kmcDKEK.setKeyInfo(&(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo));
435 kmcDKEK.setKeyInfoKeyLength((unsigned int)keyLength);
437 concat_user_pass = concat_password_user(
438 kmcDKEK.getKeyAndInfo().keyInfo.client,
441 if (!PKCS5_PBKDF2_HMAC_SHA1(
443 strlen(concat_user_pass),
444 kmcDKEK.getKeyAndInfo().keyInfo.salt,
449 delete[] concat_user_pass;
450 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
453 delete[] concat_user_pass;
455 int wrappedKeyLength = 0;
456 wkmcNewDKEK.setKeyInfo(&(kmcDKEK.getKeyAndInfo().keyInfo));
458 if (0 > (wrappedKeyLength = encryptAes256Gcm(
459 kmcDKEK.getKeyAndInfo().key,
460 kmcDKEK.getKeyAndInfo().keyInfo.keyLength,
462 kmcDKEK.getKeyAndInfo().keyInfo.iv,
463 wkmcNewDKEK.getWrappedKeyAndInfo().wrappedKey,
464 wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
465 ThrowErr(Exc::InternalError,
466 "UpdateDomainKEK in KeyProvider::reencrypt Failed");
468 wkmcNewDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
470 LogDebug("reencrypt SUCCESS");
471 return toRawBuffer(wkmcNewDKEK.getWrappedKeyAndInfo());
475 RawBuffer KeyProvider::generateDomainKEK(
476 const std::string &user,
477 const Password &userPassword)
479 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
480 uint8_t key[MAX_KEY_SIZE], PKEK1[MAX_KEY_SIZE];
482 if (!RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt, MAX_SALT_SIZE) ||
483 !RAND_bytes(key, MAX_KEY_SIZE) ||
484 !RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE))
485 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
487 int wrappedKeyLength;
488 char *concat_user_pass = NULL;
489 concat_user_pass = concat_password_user(user.c_str(), userPassword.c_str());
491 if (!PKCS5_PBKDF2_HMAC_SHA1(
493 strlen(concat_user_pass),
494 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
499 delete[] concat_user_pass;
500 ThrowErr(Exc::InternalError, "OPENSSL_ENGINED_ERROR");
503 delete[] concat_user_pass;
505 if (0 > (wrappedKeyLength = encryptAes256Gcm(
509 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
510 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
511 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
512 ThrowErr(Exc::InternalError,
513 "GenerateDomainKEK Failed in KeyProvider::generateDomainKEK");
515 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
516 wkmcDKEK.setKeyInfoClient(user);
518 LogDebug("generateDomainKEK Success");
519 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
522 int KeyProvider::initializeLibrary()
524 LogDebug("initializeLibrary Success");
528 int KeyProvider::closeLibrary()
530 LogDebug("closeLibrary Success");
534 KeyProvider::~KeyProvider()
536 LogDebug("KeyProvider Destructor");
539 int KeyProvider::encryptAes256Gcm(const unsigned char *plaintext,
540 int plaintext_len, const unsigned char *key, const unsigned char *iv,
541 unsigned char *ciphertext, unsigned char *tag)
545 int ciphertext_len = 0;
547 if (!(ctx = EVP_CIPHER_CTX_new()))
548 return OPENSSL_ENGINE_ERROR;
550 if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
551 return OPENSSL_ENGINE_ERROR;
553 if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
554 return OPENSSL_ENGINE_ERROR;
556 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
557 return OPENSSL_ENGINE_ERROR;
559 if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
560 return OPENSSL_ENGINE_ERROR;
562 ciphertext_len = len;
564 if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
565 return OPENSSL_ENGINE_ERROR;
567 ciphertext_len += len;
569 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag))
570 return OPENSSL_ENGINE_ERROR;
572 EVP_CIPHER_CTX_free(ctx);
574 return ciphertext_len;
577 int KeyProvider::decryptAes256Gcm(const unsigned char *ciphertext,
578 int ciphertext_len, unsigned char *tag, const unsigned char *key,
579 const unsigned char *iv, unsigned char *plaintext)
586 if (!(ctx = EVP_CIPHER_CTX_new()))
587 return OPENSSL_ENGINE_ERROR;
589 if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
590 return OPENSSL_ENGINE_ERROR;
592 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
593 return OPENSSL_ENGINE_ERROR;
595 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
596 return OPENSSL_ENGINE_ERROR;
598 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag))
599 return OPENSSL_ENGINE_ERROR;
601 if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
602 return OPENSSL_ENGINE_ERROR;
606 if (!(ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len)))
607 return OPENSSL_ENGINE_ERROR;
609 EVP_CIPHER_CTX_free(ctx);
612 plaintext_len += len;
613 return plaintext_len;
619 char *KeyProvider::concat_password_user(const char *user, const char *password)
621 std::string result(password);
624 if (strlen(user) > MAX_CLIENT_ID_SIZE - 1)
625 result.resize(strlen(password) + MAX_CLIENT_ID_SIZE - 1);
627 char *ret = new char[result.size() + 1];
628 memcpy(ret, result.c_str(), result.size() + 1);