1 #include <key-provider.h>
2 #include <dpl/log/log.h>
7 CKM::RawBuffer toRawBuffer(const T &data)
10 const unsigned char *ptr = reinterpret_cast<const unsigned char*>(&data);
11 output.assign(ptr, ptr + sizeof(T));
15 // You cannot use toRawBuffer template with pointers
17 CKM::RawBuffer toRawBuffer(T *)
19 class NoPointerAllowed { NoPointerAllowed(){} };
21 return CKM::RawBuffer();
24 } // anonymous namespace
28 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
30 wrappedKeyAndInfo = new WrappedKeyAndInfo;
31 memset(wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
34 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char *data)
36 wrappedKeyAndInfo = new WrappedKeyAndInfo;
37 memcpy(wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
40 WrappedKeyAndInfo& WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
42 return *wrappedKeyAndInfo;
45 void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const unsigned int length){
46 wrappedKeyAndInfo->keyInfo.keyLength = length;
49 void WrappedKeyAndInfoContainer::setKeyInfoLabel(const std::string label)
52 wrappedKeyAndInfo->keyInfo.label,
57 void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt, const int size)
59 memcpy(wrappedKeyAndInfo->keyInfo.salt, salt, size);
62 void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
64 memcpy(&(wrappedKeyAndInfo->keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
67 WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
69 delete wrappedKeyAndInfo;
72 KeyAndInfoContainer::KeyAndInfoContainer()
74 keyAndInfo = new KeyAndInfo;
75 memset(keyAndInfo, 0, sizeof(KeyAndInfo));
78 KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
80 keyAndInfo = new KeyAndInfo;
81 memcpy(keyAndInfo, data, sizeof(KeyAndInfo));
84 KeyAndInfo& KeyAndInfoContainer::getKeyAndInfo()
89 void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
91 keyAndInfo->keyInfo.keyLength = length;
94 void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
96 memcpy(&(keyAndInfo->keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
99 KeyAndInfoContainer::~KeyAndInfoContainer()
102 char *ptr = reinterpret_cast<char*>(keyAndInfo);
103 for (size_t size = 0; size < sizeof(KeyAndInfo); ++size)
106 for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) {
107 if (0 != ptr[size]) {
109 ThrowMsg(Exception::Base, "KeyAndInfo in KeyAndInfoContainer "
110 "was not destroyed!");
116 KeyProvider::KeyProvider()
118 , m_isInitialized(false)
120 LogDebug("Created empty KeyProvider");
123 KeyProvider::KeyProvider(
124 const RawBuffer &domainKEKInWrapForm,
125 const Password &password)
126 : m_kmcDKEK(new KeyAndInfoContainer())
127 , m_isInitialized(true)
129 if (!m_isInitialized) {
130 ThrowMsg(Exception::InitFailed, "Object not initialized!. Should not happened");
132 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
133 LogError("input size:" << domainKEKInWrapForm.size()
134 << " Expected: " << sizeof(WrappedKeyAndInfo));
135 ThrowMsg(Exception::InputParamError, "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
138 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(domainKEKInWrapForm.data());
140 char *concat_user_pass = NULL;
141 uint8_t PKEK1[MAX_KEY_SIZE];
143 concat_user_pass = concat_password_user(
144 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.label,
147 if (!PKCS5_PBKDF2_HMAC_SHA1(
149 strlen(concat_user_pass),
150 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
156 delete[] concat_user_pass;
157 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
160 delete[] concat_user_pass;
164 if (0 > (keyLength = decryptAes256Gcm(
165 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
166 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
167 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag,
169 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
170 m_kmcDKEK->getKeyAndInfo().key))) {
172 ThrowMsg(Exception::PassWordError, "VerifyDomainKEK failed in KeyProvider Constructor");
175 m_kmcDKEK->setKeyInfo(&(wkmcDKEK.getWrappedKeyAndInfo().keyInfo));
176 m_kmcDKEK->setKeyInfoKeyLength((unsigned int)keyLength);
179 KeyProvider& KeyProvider::operator=(KeyProvider &&second)
181 LogDebug("Moving KeyProvider");
184 m_isInitialized = second.m_isInitialized;
185 m_kmcDKEK = second.m_kmcDKEK;
186 second.m_isInitialized = false;
187 second.m_kmcDKEK = NULL;
191 KeyProvider::KeyProvider(KeyProvider &&second)
193 LogDebug("Moving KeyProvider");
194 m_isInitialized = second.m_isInitialized;
195 m_kmcDKEK = second.m_kmcDKEK;
196 second.m_isInitialized = false;
197 second.m_kmcDKEK = NULL;
200 bool KeyProvider::isInitialized()
202 return m_isInitialized;
205 RawBuffer KeyProvider::getPureDomainKEK()
207 if (!m_isInitialized) {
208 ThrowMsg(Exception::InitFailed, "Object not initialized!");
212 return RawBuffer(m_kmcDKEK->getKeyAndInfo().key, (m_kmcDKEK->getKeyAndInfo().key) + m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength);
215 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
217 if (!m_isInitialized) {
218 ThrowMsg(Exception::InitFailed, "Object not initialized!");
221 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
223 char *concat_user_pass = NULL;
224 uint8_t PKEK1[MAX_KEY_SIZE];
226 concat_user_pass = concat_password_user(
227 m_kmcDKEK->getKeyAndInfo().keyInfo.label,
230 if (!PKCS5_PBKDF2_HMAC_SHA1(
232 strlen(concat_user_pass),
233 m_kmcDKEK->getKeyAndInfo().keyInfo.salt,
239 delete[] concat_user_pass;
240 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
243 delete[] concat_user_pass;
245 wkmcDKEK.setKeyInfo(&(m_kmcDKEK->getKeyAndInfo().keyInfo));
247 int wrappedKeyLength;
249 if (0 > (wrappedKeyLength = encryptAes256Gcm(
250 m_kmcDKEK->getKeyAndInfo().key,
251 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
253 m_kmcDKEK->getKeyAndInfo().keyInfo.iv,
254 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
255 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag))) {
257 ThrowMsg(Exception::InitFailed, "WrapDKEK Failed in KeyProvider::getDomainKEK");
260 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
262 LogDebug("getDomainKEK(password) Success");
263 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
267 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
269 if (!m_isInitialized) {
270 ThrowMsg(Exception::InitFailed, "Object not initialized!");
273 if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)){
274 LogError("input size:" << DEKInWrapForm.size()
275 << " Expected: " << sizeof(WrappedKeyAndInfo));
276 ThrowMsg(Exception::InputParamError,
277 "buffer doesn't have proper size to store "
278 "WrappedKeyAndInfo in KeyProvider::getPureDEK");
281 KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
282 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(DEKInWrapForm.data());
284 uint8_t PKEK2[MAX_KEY_SIZE];
287 if (!PKCS5_PBKDF2_HMAC_SHA1(
288 wkmcDEK.getWrappedKeyAndInfo().keyInfo.label,
289 strlen(wkmcDEK.getWrappedKeyAndInfo().keyInfo.label),
290 m_kmcDKEK->getKeyAndInfo().key,
296 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
299 if (0 > (keyLength = decryptAes256Gcm(
300 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
301 wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
302 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
304 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
305 kmcDEK.getKeyAndInfo().key))) {
307 ThrowMsg(Exception::UnwrapFailed,
308 "UnwrapDEK Failed in KeyProvider::getPureDEK");
311 kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
313 LogDebug("getPureDEK SUCCESS");
315 kmcDEK.getKeyAndInfo().key,
316 (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
319 RawBuffer KeyProvider::generateDEK(const std::string &smackLabel)
321 if (!m_isInitialized) {
322 ThrowMsg(Exception::InitFailed,
323 "Object not initialized!");
326 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
327 std::string resized_smackLabel;
329 if (smackLabel.length() < APP_LABEL_SIZE)
330 resized_smackLabel = smackLabel;
332 resized_smackLabel = smackLabel.substr(0, APP_LABEL_SIZE-1);
334 uint8_t key[MAX_KEY_SIZE], PKEK2[MAX_KEY_SIZE];
336 if (!RAND_bytes(key, m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength) ||
337 !RAND_bytes(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE)) {
339 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
342 if (!PKCS5_PBKDF2_HMAC_SHA1(
343 resized_smackLabel.c_str(),
344 strlen(resized_smackLabel.c_str()),
345 m_kmcDKEK->getKeyAndInfo().key,
351 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
354 int wrappedKeyLength;
356 if (0 > (wrappedKeyLength = encryptAes256Gcm(
358 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
360 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
361 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
362 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag))) {
364 ThrowMsg(Exception::GenFailed,
365 "GenerateDEK Failed in KeyProvider::generateDEK");
368 wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
369 wkmcDEK.setKeyInfoSalt(m_kmcDKEK->getKeyAndInfo().key, MAX_SALT_SIZE);
370 wkmcDEK.setKeyInfoLabel(resized_smackLabel);
372 LogDebug("GenerateDEK Success");
373 return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
376 RawBuffer KeyProvider::reencrypt(
377 const RawBuffer &domainKEKInWrapForm,
378 const Password &oldPass,
379 const Password &newPass)
381 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
382 LogError("input size:" << domainKEKInWrapForm.size()
383 << " Expected: " << sizeof(WrappedKeyAndInfo));
384 ThrowMsg(Exception::InputParamError,
385 "buffer doesn't have proper size to store "
386 "WrappedKeyAndInfo in KeyProvider::reencrypt");
389 WrappedKeyAndInfoContainer wkmcOldDKEK = WrappedKeyAndInfoContainer(domainKEKInWrapForm.data());
390 WrappedKeyAndInfoContainer wkmcNewDKEK = WrappedKeyAndInfoContainer();
391 KeyAndInfoContainer kmcDKEK = KeyAndInfoContainer();
393 char *concat_user_pass = NULL;
394 uint8_t PKEK1[MAX_KEY_SIZE];
398 concat_user_pass = concat_password_user(
399 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.label,
402 if (!PKCS5_PBKDF2_HMAC_SHA1(
404 strlen(concat_user_pass),
405 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.salt,
411 delete[] concat_user_pass;
412 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
414 delete[] concat_user_pass;
416 if (0 > (keyLength = decryptAes256Gcm(
417 wkmcOldDKEK.getWrappedKeyAndInfo().wrappedKey,
418 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
419 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.tag,
421 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.iv,
422 kmcDKEK.getKeyAndInfo().key))) {
424 ThrowMsg(Exception::PassWordError,
425 "Incorrect Old Password ");
428 kmcDKEK.setKeyInfo(&(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo));
429 kmcDKEK.setKeyInfoKeyLength((unsigned int)keyLength);
431 concat_user_pass = concat_password_user(
432 kmcDKEK.getKeyAndInfo().keyInfo.label,
435 if (!PKCS5_PBKDF2_HMAC_SHA1(
437 strlen(concat_user_pass),
438 kmcDKEK.getKeyAndInfo().keyInfo.salt,
444 delete[] concat_user_pass;
445 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
448 delete[] concat_user_pass;
450 int wrappedKeyLength = 0;
451 wkmcNewDKEK.setKeyInfo(&(kmcDKEK.getKeyAndInfo().keyInfo));
453 if (0 > (wrappedKeyLength = encryptAes256Gcm(
454 kmcDKEK.getKeyAndInfo().key,
455 kmcDKEK.getKeyAndInfo().keyInfo.keyLength,
457 kmcDKEK.getKeyAndInfo().keyInfo.iv,
458 wkmcNewDKEK.getWrappedKeyAndInfo().wrappedKey,
459 wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo.tag))) {
461 ThrowMsg(Exception::UnwrapFailed,
462 "UpdateDomainKEK in KeyProvider::reencrypt Failed");
465 wkmcNewDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
467 LogDebug("reencrypt SUCCESS");
468 return toRawBuffer(wkmcNewDKEK.getWrappedKeyAndInfo());
472 RawBuffer KeyProvider::generateDomainKEK(
473 const std::string &user,
474 const Password &userPassword)
476 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
477 uint8_t key[MAX_KEY_SIZE], PKEK1[MAX_KEY_SIZE];
479 if (!RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt, MAX_SALT_SIZE) ||
480 !RAND_bytes(key, MAX_KEY_SIZE) ||
481 !RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE))
482 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINE_ERROR");
484 int wrappedKeyLength;
485 char *concat_user_pass = NULL;
486 concat_user_pass = concat_password_user(user.c_str(), userPassword.c_str());
487 if (!PKCS5_PBKDF2_HMAC_SHA1(
489 strlen(concat_user_pass),
490 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
496 delete[] concat_user_pass;
497 ThrowMsg(Exception::OpensslEngineError, "OPENSSL_ENGINED_ERROR");
500 delete[] concat_user_pass;
502 if (0 > (wrappedKeyLength = encryptAes256Gcm(
506 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
507 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
508 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag))) {
510 ThrowMsg(Exception::GenFailed,
511 "GenerateDomainKEK Failed in KeyProvider::generateDomainKEK");
514 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
515 wkmcDKEK.setKeyInfoLabel(user);
517 LogDebug("generateDomainKEK Success");
518 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
521 int KeyProvider::initializeLibrary()
523 LogDebug("initializeLibrary Success");
527 int KeyProvider::closeLibrary()
529 LogDebug("closeLibrary Success");
533 KeyProvider::~KeyProvider()
535 LogDebug("KeyProvider Destructor");
538 int KeyProvider::encryptAes256Gcm(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, const unsigned char *iv, unsigned char *ciphertext, unsigned char *tag)
543 int ciphertext_len = 0;
545 if (!(ctx = EVP_CIPHER_CTX_new())) {
546 return OPENSSL_ENGINE_ERROR;
549 if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
550 return OPENSSL_ENGINE_ERROR;
553 if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
554 return OPENSSL_ENGINE_ERROR;
557 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL)) {
558 return OPENSSL_ENGINE_ERROR;
561 if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
562 return OPENSSL_ENGINE_ERROR;
564 ciphertext_len = len;
566 if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
567 return OPENSSL_ENGINE_ERROR;
569 ciphertext_len += len;
571 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag)) {
572 return OPENSSL_ENGINE_ERROR;
575 EVP_CIPHER_CTX_free(ctx);
577 return ciphertext_len;
580 int KeyProvider::decryptAes256Gcm(const unsigned char *ciphertext, int ciphertext_len, unsigned char *tag, const unsigned char *key, const unsigned char *iv, unsigned char *plaintext)
588 if (!(ctx = EVP_CIPHER_CTX_new())) {
589 return OPENSSL_ENGINE_ERROR;
592 if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
593 return OPENSSL_ENGINE_ERROR;
595 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
596 return OPENSSL_ENGINE_ERROR;
599 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL)) {
600 return OPENSSL_ENGINE_ERROR;
603 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag)) {
604 return OPENSSL_ENGINE_ERROR;
607 if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) {
608 return OPENSSL_ENGINE_ERROR;
612 if (!(ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len))) {
613 return OPENSSL_ENGINE_ERROR;
616 EVP_CIPHER_CTX_free(ctx);
619 plaintext_len += len;
620 return plaintext_len;
627 char * KeyProvider::concat_password_user(const char *user, const char *password)
629 char *concat_user_pass = NULL;
630 char *resized_user = NULL;
631 int concat_user_pass_len = 0;
633 if (strlen(user) > MAX_LABEL_SIZE-1) {
634 resized_user = new char[MAX_LABEL_SIZE];
635 memcpy(resized_user, user, MAX_LABEL_SIZE-1);
636 resized_user[MAX_LABEL_SIZE-1] = '\0';
639 resized_user = new char[strlen(user)+1];
640 memcpy(resized_user, user, strlen(user));
641 resized_user[strlen(user)] = '\0';
643 concat_user_pass_len = strlen(resized_user) + strlen(password) + 1;
644 concat_user_pass = new char[concat_user_pass_len];
646 memset(concat_user_pass, '\0', concat_user_pass_len);
647 memcpy(concat_user_pass, password, strlen(password));
648 memcpy(&(concat_user_pass[strlen(password)]), user, strlen(user));
649 concat_user_pass[strlen(resized_user) + strlen(password)] = '\0';
651 delete[] resized_user;
652 return concat_user_pass;