2 #include <key-provider.h>
3 #include <dpl/log/log.h>
8 CKM::RawBuffer toRawBuffer(const T &data)
10 CKM::RawBuffer output;
11 const unsigned char *ptr = reinterpret_cast<const unsigned char*>(&data);
12 output.assign(ptr, ptr + sizeof(T));
16 // You cannot use toRawBuffer template with pointers
18 CKM::RawBuffer toRawBuffer(T *)
20 class NoPointerAllowed { NoPointerAllowed(){} };
22 return CKM::RawBuffer();
25 } // anonymous namespace
29 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
31 wrappedKeyAndInfo = new WrappedKeyAndInfo;
32 memset(wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
35 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char *data)
37 wrappedKeyAndInfo = new WrappedKeyAndInfo;
38 memcpy(wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
41 WrappedKeyAndInfo& WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
43 return *wrappedKeyAndInfo;
46 void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const unsigned int length){
47 wrappedKeyAndInfo->keyInfo.keyLength = length;
50 void WrappedKeyAndInfoContainer::setKeyInfoLabel(const std::string label)
53 wrappedKeyAndInfo->keyInfo.label,
58 void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt, const int size)
60 memcpy(wrappedKeyAndInfo->keyInfo.salt, salt, size);
63 void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
65 memcpy(&(wrappedKeyAndInfo->keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
68 WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
70 delete wrappedKeyAndInfo;
73 KeyAndInfoContainer::KeyAndInfoContainer()
75 keyAndInfo = new KeyAndInfo;
76 memset(keyAndInfo, 0, sizeof(KeyAndInfo));
79 KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
81 keyAndInfo = new KeyAndInfo;
82 memcpy(keyAndInfo, data, sizeof(KeyAndInfo));
85 KeyAndInfo& KeyAndInfoContainer::getKeyAndInfo()
90 void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
92 keyAndInfo->keyInfo.keyLength = length;
95 void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
97 memcpy(&(keyAndInfo->keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
100 KeyAndInfoContainer::~KeyAndInfoContainer()
103 char *ptr = reinterpret_cast<char*>(keyAndInfo);
104 memset(ptr, 0, sizeof(KeyAndInfo));
106 for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) {
108 LogError("Write momory error! Memory used by key was not owerwritten.");
114 KeyProvider::KeyProvider()
116 , m_isInitialized(false)
118 LogDebug("Created empty KeyProvider");
121 KeyProvider::KeyProvider(
122 const RawBuffer &domainKEKInWrapForm,
123 const Password &password)
124 : m_kmcDKEK(new KeyAndInfoContainer())
125 , m_isInitialized(true)
127 if (!m_isInitialized) {
128 ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
130 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
131 LogError("input size:" << domainKEKInWrapForm.size()
132 << " Expected: " << sizeof(WrappedKeyAndInfo));
133 ThrowErr(Exc::InternalError, "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
136 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(domainKEKInWrapForm.data());
138 char *concat_user_pass = NULL;
139 uint8_t PKEK1[MAX_KEY_SIZE];
141 concat_user_pass = concat_password_user(
142 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.label,
145 if (!PKCS5_PBKDF2_HMAC_SHA1(
147 strlen(concat_user_pass),
148 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
154 delete[] concat_user_pass;
155 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
158 delete[] concat_user_pass;
162 if (0 > (keyLength = decryptAes256Gcm(
163 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
164 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
165 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag,
167 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
168 m_kmcDKEK->getKeyAndInfo().key))) {
170 ThrowErr(Exc::AuthenticationFailed, "VerifyDomainKEK failed in KeyProvider Constructor");
173 m_kmcDKEK->setKeyInfo(&(wkmcDKEK.getWrappedKeyAndInfo().keyInfo));
174 m_kmcDKEK->setKeyInfoKeyLength((unsigned int)keyLength);
177 KeyProvider& KeyProvider::operator=(KeyProvider &&second)
179 LogDebug("Moving KeyProvider");
182 m_isInitialized = second.m_isInitialized;
183 m_kmcDKEK = second.m_kmcDKEK;
184 second.m_isInitialized = false;
185 second.m_kmcDKEK = NULL;
189 KeyProvider::KeyProvider(KeyProvider &&second)
191 LogDebug("Moving KeyProvider");
192 m_isInitialized = second.m_isInitialized;
193 m_kmcDKEK = second.m_kmcDKEK;
194 second.m_isInitialized = false;
195 second.m_kmcDKEK = NULL;
198 bool KeyProvider::isInitialized()
200 return m_isInitialized;
203 RawBuffer KeyProvider::getPureDomainKEK()
205 if (!m_isInitialized) {
206 ThrowErr(Exc::InternalError, "Object not initialized!");
210 return RawBuffer(m_kmcDKEK->getKeyAndInfo().key, (m_kmcDKEK->getKeyAndInfo().key) + m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength);
213 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
215 if (!m_isInitialized) {
216 ThrowErr(Exc::InternalError, "Object not initialized!");
219 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
221 char *concat_user_pass = NULL;
222 uint8_t PKEK1[MAX_KEY_SIZE];
224 concat_user_pass = concat_password_user(
225 m_kmcDKEK->getKeyAndInfo().keyInfo.label,
228 if (!PKCS5_PBKDF2_HMAC_SHA1(
230 strlen(concat_user_pass),
231 m_kmcDKEK->getKeyAndInfo().keyInfo.salt,
237 delete[] concat_user_pass;
238 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
241 delete[] concat_user_pass;
243 wkmcDKEK.setKeyInfo(&(m_kmcDKEK->getKeyAndInfo().keyInfo));
245 int wrappedKeyLength;
247 if (0 > (wrappedKeyLength = encryptAes256Gcm(
248 m_kmcDKEK->getKeyAndInfo().key,
249 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
251 m_kmcDKEK->getKeyAndInfo().keyInfo.iv,
252 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
253 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag))) {
255 ThrowErr(Exc::InternalError, "WrapDKEK Failed in KeyProvider::getDomainKEK");
258 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
260 LogDebug("getDomainKEK(password) Success");
261 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
265 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
267 if (!m_isInitialized) {
268 ThrowErr(Exc::InternalError, "Object not initialized!");
271 if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)){
272 LogError("input size:" << DEKInWrapForm.size()
273 << " Expected: " << sizeof(WrappedKeyAndInfo));
274 ThrowErr(Exc::InternalError,
275 "buffer doesn't have proper size to store "
276 "WrappedKeyAndInfo in KeyProvider::getPureDEK");
279 KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
280 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(DEKInWrapForm.data());
282 uint8_t PKEK2[MAX_KEY_SIZE];
285 if (!PKCS5_PBKDF2_HMAC_SHA1(
286 wkmcDEK.getWrappedKeyAndInfo().keyInfo.label,
287 strlen(wkmcDEK.getWrappedKeyAndInfo().keyInfo.label),
288 m_kmcDKEK->getKeyAndInfo().key,
294 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
297 if (0 > (keyLength = decryptAes256Gcm(
298 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
299 wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
300 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
302 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
303 kmcDEK.getKeyAndInfo().key))) {
305 ThrowErr(Exc::InternalError,
306 "UnwrapDEK Failed in KeyProvider::getPureDEK");
309 kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
311 LogDebug("getPureDEK SUCCESS");
313 kmcDEK.getKeyAndInfo().key,
314 (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
317 RawBuffer KeyProvider::generateDEK(const std::string &smackLabel)
319 if (!m_isInitialized) {
320 ThrowErr(Exc::InternalError, "Object not initialized!");
323 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
324 std::string resized_smackLabel;
326 if (smackLabel.length() < APP_LABEL_SIZE)
327 resized_smackLabel = smackLabel;
329 resized_smackLabel = smackLabel.substr(0, APP_LABEL_SIZE-1);
331 uint8_t key[MAX_KEY_SIZE], PKEK2[MAX_KEY_SIZE];
333 if (!RAND_bytes(key, m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength) ||
334 !RAND_bytes(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE)) {
336 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
339 if (!PKCS5_PBKDF2_HMAC_SHA1(
340 resized_smackLabel.c_str(),
341 strlen(resized_smackLabel.c_str()),
342 m_kmcDKEK->getKeyAndInfo().key,
348 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
351 int wrappedKeyLength;
353 if (0 > (wrappedKeyLength = encryptAes256Gcm(
355 m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
357 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
358 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
359 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag))) {
361 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
364 wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
365 wkmcDEK.setKeyInfoSalt(m_kmcDKEK->getKeyAndInfo().key, MAX_SALT_SIZE);
366 wkmcDEK.setKeyInfoLabel(resized_smackLabel);
368 LogDebug("GenerateDEK Success");
369 return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
372 RawBuffer KeyProvider::reencrypt(
373 const RawBuffer &domainKEKInWrapForm,
374 const Password &oldPass,
375 const Password &newPass)
377 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
378 LogError("input size:" << domainKEKInWrapForm.size()
379 << " Expected: " << sizeof(WrappedKeyAndInfo));
380 ThrowErr(Exc::InternalError,
381 "buffer doesn't have proper size to store "
382 "WrappedKeyAndInfo in KeyProvider::reencrypt");
385 WrappedKeyAndInfoContainer wkmcOldDKEK = WrappedKeyAndInfoContainer(domainKEKInWrapForm.data());
386 WrappedKeyAndInfoContainer wkmcNewDKEK = WrappedKeyAndInfoContainer();
387 KeyAndInfoContainer kmcDKEK = KeyAndInfoContainer();
389 char *concat_user_pass = NULL;
390 uint8_t PKEK1[MAX_KEY_SIZE];
394 concat_user_pass = concat_password_user(
395 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.label,
398 if (!PKCS5_PBKDF2_HMAC_SHA1(
400 strlen(concat_user_pass),
401 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.salt,
407 delete[] concat_user_pass;
408 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
410 delete[] concat_user_pass;
412 if (0 > (keyLength = decryptAes256Gcm(
413 wkmcOldDKEK.getWrappedKeyAndInfo().wrappedKey,
414 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
415 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.tag,
417 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.iv,
418 kmcDKEK.getKeyAndInfo().key))) {
420 ThrowErr(Exc::AuthenticationFailed, "Incorrect Old Password ");
423 kmcDKEK.setKeyInfo(&(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo));
424 kmcDKEK.setKeyInfoKeyLength((unsigned int)keyLength);
426 concat_user_pass = concat_password_user(
427 kmcDKEK.getKeyAndInfo().keyInfo.label,
430 if (!PKCS5_PBKDF2_HMAC_SHA1(
432 strlen(concat_user_pass),
433 kmcDKEK.getKeyAndInfo().keyInfo.salt,
439 delete[] concat_user_pass;
440 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
443 delete[] concat_user_pass;
445 int wrappedKeyLength = 0;
446 wkmcNewDKEK.setKeyInfo(&(kmcDKEK.getKeyAndInfo().keyInfo));
448 if (0 > (wrappedKeyLength = encryptAes256Gcm(
449 kmcDKEK.getKeyAndInfo().key,
450 kmcDKEK.getKeyAndInfo().keyInfo.keyLength,
452 kmcDKEK.getKeyAndInfo().keyInfo.iv,
453 wkmcNewDKEK.getWrappedKeyAndInfo().wrappedKey,
454 wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo.tag))) {
456 ThrowErr(Exc::InternalError, "UpdateDomainKEK in KeyProvider::reencrypt Failed");
459 wkmcNewDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
461 LogDebug("reencrypt SUCCESS");
462 return toRawBuffer(wkmcNewDKEK.getWrappedKeyAndInfo());
466 RawBuffer KeyProvider::generateDomainKEK(
467 const std::string &user,
468 const Password &userPassword)
470 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
471 uint8_t key[MAX_KEY_SIZE], PKEK1[MAX_KEY_SIZE];
473 if (!RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt, MAX_SALT_SIZE) ||
474 !RAND_bytes(key, MAX_KEY_SIZE) ||
475 !RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE))
476 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
478 int wrappedKeyLength;
479 char *concat_user_pass = NULL;
480 concat_user_pass = concat_password_user(user.c_str(), userPassword.c_str());
481 if (!PKCS5_PBKDF2_HMAC_SHA1(
483 strlen(concat_user_pass),
484 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
490 delete[] concat_user_pass;
491 ThrowErr(Exc::InternalError, "OPENSSL_ENGINED_ERROR");
494 delete[] concat_user_pass;
496 if (0 > (wrappedKeyLength = encryptAes256Gcm(
500 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
501 wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
502 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag))) {
504 ThrowErr(Exc::InternalError,
505 "GenerateDomainKEK Failed in KeyProvider::generateDomainKEK");
508 wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
509 wkmcDKEK.setKeyInfoLabel(user);
511 LogDebug("generateDomainKEK Success");
512 return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
515 int KeyProvider::initializeLibrary()
517 LogDebug("initializeLibrary Success");
521 int KeyProvider::closeLibrary()
523 LogDebug("closeLibrary Success");
527 KeyProvider::~KeyProvider()
529 LogDebug("KeyProvider Destructor");
532 int KeyProvider::encryptAes256Gcm(const unsigned char *plaintext, int plaintext_len, const unsigned char *key, const unsigned char *iv, unsigned char *ciphertext, unsigned char *tag)
537 int ciphertext_len = 0;
539 if (!(ctx = EVP_CIPHER_CTX_new())) {
540 return OPENSSL_ENGINE_ERROR;
543 if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
544 return OPENSSL_ENGINE_ERROR;
547 if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) {
548 return OPENSSL_ENGINE_ERROR;
551 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL)) {
552 return OPENSSL_ENGINE_ERROR;
555 if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) {
556 return OPENSSL_ENGINE_ERROR;
558 ciphertext_len = len;
560 if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) {
561 return OPENSSL_ENGINE_ERROR;
563 ciphertext_len += len;
565 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag)) {
566 return OPENSSL_ENGINE_ERROR;
569 EVP_CIPHER_CTX_free(ctx);
571 return ciphertext_len;
574 int KeyProvider::decryptAes256Gcm(const unsigned char *ciphertext, int ciphertext_len, unsigned char *tag, const unsigned char *key, const unsigned char *iv, unsigned char *plaintext)
582 if (!(ctx = EVP_CIPHER_CTX_new())) {
583 return OPENSSL_ENGINE_ERROR;
586 if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) {
587 return OPENSSL_ENGINE_ERROR;
589 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) {
590 return OPENSSL_ENGINE_ERROR;
593 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL)) {
594 return OPENSSL_ENGINE_ERROR;
597 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag)) {
598 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;
610 EVP_CIPHER_CTX_free(ctx);
613 plaintext_len += len;
614 return plaintext_len;
621 char * KeyProvider::concat_password_user(const char *user, const char *password)
623 char *concat_user_pass = NULL;
624 char *resized_user = NULL;
625 int concat_user_pass_len = 0;
627 if (strlen(user) > MAX_LABEL_SIZE-1) {
628 resized_user = new char[MAX_LABEL_SIZE];
629 memcpy(resized_user, user, MAX_LABEL_SIZE-1);
630 resized_user[MAX_LABEL_SIZE-1] = '\0';
633 resized_user = new char[strlen(user)+1];
634 memcpy(resized_user, user, strlen(user));
635 resized_user[strlen(user)] = '\0';
637 concat_user_pass_len = strlen(resized_user) + strlen(password) + 1;
638 concat_user_pass = new char[concat_user_pass_len];
640 memset(concat_user_pass, '\0', concat_user_pass_len);
641 memcpy(concat_user_pass, password, strlen(password));
642 memcpy(&(concat_user_pass[strlen(password)]), resized_user, strlen(resized_user));
643 concat_user_pass[strlen(resized_user) + strlen(password)] = '\0';
645 delete[] resized_user;
646 return concat_user_pass;