4ca4f038642dc85b84d08bad1ce1f7e09fc86bc0
[platform/core/security/key-manager.git] / src / manager / service / key-provider.cpp
1 #include <exception.h>
2 #include <key-provider.h>
3 #include <dpl/log/log.h>
4
5 namespace {
6
7 template<typename T>
8 CKM::RawBuffer toRawBuffer(const T &data)
9 {
10         CKM::RawBuffer output;
11         const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
12         output.assign(ptr, ptr + sizeof(T));
13         return output;
14 }
15
16 // You cannot use toRawBuffer template with pointers
17 template<typename T>
18 CKM::RawBuffer toRawBuffer(T *)
19 {
20         class NoPointerAllowed {
21                 NoPointerAllowed() {}
22         };
23         NoPointerAllowed a;
24         return CKM::RawBuffer();
25 }
26
27 } // anonymous namespace
28
29 using namespace CKM;
30
31 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
32 {
33         wrappedKeyAndInfo = new WrappedKeyAndInfo;
34         memset(wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
35 }
36
37 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char
38                 *data)
39 {
40         wrappedKeyAndInfo = new WrappedKeyAndInfo;
41         memcpy(wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
42 }
43
44 WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
45 {
46         return *wrappedKeyAndInfo;
47 }
48
49 void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const unsigned int length)
50 {
51         wrappedKeyAndInfo->keyInfo.keyLength = length;
52 }
53
54 void WrappedKeyAndInfoContainer::setKeyInfoLabel(const std::string label)
55 {
56         strncpy(
57                 wrappedKeyAndInfo->keyInfo.label,
58                 label.c_str(),
59                 MAX_LABEL_SIZE);
60 }
61
62 void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt,
63                 const int size)
64 {
65         memcpy(wrappedKeyAndInfo->keyInfo.salt, salt, size);
66 }
67
68 void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo
69                 *keyComponentsInfo)
70 {
71         memcpy(&(wrappedKeyAndInfo->keyInfo), keyComponentsInfo,
72                    sizeof(KeyComponentsInfo));
73 }
74
75 WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
76 {
77         delete wrappedKeyAndInfo;
78 }
79
80 KeyAndInfoContainer::KeyAndInfoContainer()
81 {
82         keyAndInfo = new KeyAndInfo;
83         memset(keyAndInfo, 0, sizeof(KeyAndInfo));
84 }
85
86 KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
87 {
88         keyAndInfo = new KeyAndInfo;
89         memcpy(keyAndInfo, data, sizeof(KeyAndInfo));
90 }
91
92 KeyAndInfo &KeyAndInfoContainer::getKeyAndInfo()
93 {
94         return *keyAndInfo;
95 }
96
97 void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
98 {
99         keyAndInfo->keyInfo.keyLength = length;
100 }
101
102 void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
103 {
104         memcpy(&(keyAndInfo->keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
105 }
106
107 KeyAndInfoContainer::~KeyAndInfoContainer()
108 {
109         // overwrite key
110         char *ptr = reinterpret_cast<char *>(keyAndInfo);
111         memset(ptr, 0, sizeof(KeyAndInfo));
112
113         // verification
114         for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) {
115                 if (ptr[size])
116                         LogError("Write momory error! Memory used by key was not owerwritten.");
117         }
118
119         delete keyAndInfo;
120 }
121
122 KeyProvider::KeyProvider() :
123         m_kmcDKEK(NULL),
124         m_isInitialized(false)
125 {
126         LogDebug("Created empty KeyProvider");
127 }
128
129 KeyProvider::KeyProvider(
130         const RawBuffer &domainKEKInWrapForm,
131         const Password &password) :
132         m_kmcDKEK(new KeyAndInfoContainer()),
133         m_isInitialized(true)
134 {
135         if (!m_isInitialized)
136                 ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
137
138         if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
139                 LogError("input size:" << domainKEKInWrapForm.size()
140                                  << " Expected: " << sizeof(WrappedKeyAndInfo));
141                 ThrowErr(Exc::InternalError,
142                                  "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
143         }
144
145         WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer(
146                         domainKEKInWrapForm.data());
147
148         char *concat_user_pass = NULL;
149         uint8_t PKEK1[MAX_KEY_SIZE];
150
151         concat_user_pass = concat_password_user(
152                                                    wkmcDKEK.getWrappedKeyAndInfo().keyInfo.label,
153                                                    password.c_str());
154
155         if (!PKCS5_PBKDF2_HMAC_SHA1(
156                                 concat_user_pass,
157                                 strlen(concat_user_pass),
158                                 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
159                                 MAX_SALT_SIZE,
160                                 PBKDF2_ITERATIONS,
161                                 MAX_KEY_SIZE,
162                                 PKEK1)) {
163                 delete[] concat_user_pass;
164                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
165         }
166
167         delete[] concat_user_pass;
168
169         int keyLength;
170
171         if (0 > (keyLength = decryptAes256Gcm(
172                                                          wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
173                                                          wkmcDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
174                                                          wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag,
175                                                          PKEK1,
176                                                          wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
177                                                          m_kmcDKEK->getKeyAndInfo().key))) {
178                 ThrowErr(Exc::AuthenticationFailed,
179                                  "VerifyDomainKEK failed in KeyProvider Constructor");
180         }
181
182         m_kmcDKEK->setKeyInfo(&(wkmcDKEK.getWrappedKeyAndInfo().keyInfo));
183         m_kmcDKEK->setKeyInfoKeyLength((unsigned int)keyLength);
184 }
185
186 KeyProvider &KeyProvider::operator=(KeyProvider &&second)
187 {
188         LogDebug("Moving KeyProvider");
189
190         if (this == &second)
191                 return *this;
192
193         m_isInitialized = second.m_isInitialized;
194         m_kmcDKEK = second.m_kmcDKEK;
195         second.m_isInitialized = false;
196         second.m_kmcDKEK = NULL;
197         return *this;
198 }
199
200 KeyProvider::KeyProvider(KeyProvider &&second)
201 {
202         LogDebug("Moving KeyProvider");
203         m_isInitialized = second.m_isInitialized;
204         m_kmcDKEK = second.m_kmcDKEK;
205         second.m_isInitialized = false;
206         second.m_kmcDKEK = NULL;
207 }
208
209 bool KeyProvider::isInitialized()
210 {
211         return m_isInitialized;
212 }
213
214 RawBuffer KeyProvider::getPureDomainKEK()
215 {
216         if (!m_isInitialized)
217                 ThrowErr(Exc::InternalError, "Object not initialized!");
218
219         // TODO secure
220         return RawBuffer(m_kmcDKEK->getKeyAndInfo().key,
221                                          (m_kmcDKEK->getKeyAndInfo().key) +
222                                          m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength);
223 }
224
225 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
226 {
227         if (!m_isInitialized)
228                 ThrowErr(Exc::InternalError, "Object not initialized!");
229
230         WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
231
232         char *concat_user_pass = NULL;
233         uint8_t PKEK1[MAX_KEY_SIZE];
234
235         concat_user_pass = concat_password_user(
236                                                    m_kmcDKEK->getKeyAndInfo().keyInfo.label,
237                                                    password.c_str());
238
239         if (!PKCS5_PBKDF2_HMAC_SHA1(
240                                 concat_user_pass,
241                                 strlen(concat_user_pass),
242                                 m_kmcDKEK->getKeyAndInfo().keyInfo.salt,
243                                 MAX_SALT_SIZE,
244                                 PBKDF2_ITERATIONS,
245                                 MAX_KEY_SIZE,
246                                 PKEK1)) {
247                 delete[] concat_user_pass;
248                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
249         }
250
251         delete[] concat_user_pass;
252
253         wkmcDKEK.setKeyInfo(&(m_kmcDKEK->getKeyAndInfo().keyInfo));
254
255         int wrappedKeyLength;
256
257         if (0 > (wrappedKeyLength = encryptAes256Gcm(
258                                                                         m_kmcDKEK->getKeyAndInfo().key,
259                                                                         m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
260                                                                         PKEK1,
261                                                                         m_kmcDKEK->getKeyAndInfo().keyInfo.iv,
262                                                                         wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
263                                                                         wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
264                 ThrowErr(Exc::InternalError, "WrapDKEK Failed in KeyProvider::getDomainKEK");
265
266         wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
267
268         LogDebug("getDomainKEK(password) Success");
269         return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
270 }
271
272
273 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
274 {
275         if (!m_isInitialized)
276                 ThrowErr(Exc::InternalError, "Object not initialized!");
277
278         if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
279                 LogError("input size:" << DEKInWrapForm.size()
280                                  << " Expected: " << sizeof(WrappedKeyAndInfo));
281                 ThrowErr(Exc::InternalError,
282                                  "buffer doesn't have proper size to store "
283                                  "WrappedKeyAndInfo in KeyProvider::getPureDEK");
284         }
285
286         KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
287         WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(
288                         DEKInWrapForm.data());
289
290         uint8_t PKEK2[MAX_KEY_SIZE];
291         int keyLength;
292
293         if (!PKCS5_PBKDF2_HMAC_SHA1(
294                                 wkmcDEK.getWrappedKeyAndInfo().keyInfo.label,
295                                 strlen(wkmcDEK.getWrappedKeyAndInfo().keyInfo.label),
296                                 m_kmcDKEK->getKeyAndInfo().key,
297                                 MAX_SALT_SIZE,
298                                 PBKDF2_ITERATIONS,
299                                 MAX_KEY_SIZE,
300                                 PKEK2))
301                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
302
303         if (0 > (keyLength = decryptAes256Gcm(
304                                                          wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
305                                                          wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
306                                                          wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
307                                                          PKEK2,
308                                                          wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
309                                                          kmcDEK.getKeyAndInfo().key)))
310                 ThrowErr(Exc::InternalError,
311                                  "UnwrapDEK Failed in KeyProvider::getPureDEK");
312
313         kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
314
315         LogDebug("getPureDEK SUCCESS");
316         return RawBuffer(
317                            kmcDEK.getKeyAndInfo().key,
318                            (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
319 }
320
321 RawBuffer KeyProvider::generateDEK(const std::string &smackLabel)
322 {
323         if (!m_isInitialized)
324                 ThrowErr(Exc::InternalError, "Object not initialized!");
325
326         WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
327         std::string resized_smackLabel;
328
329         if (smackLabel.length() < APP_LABEL_SIZE)
330                 resized_smackLabel = smackLabel;
331         else
332                 resized_smackLabel = smackLabel.substr(0, APP_LABEL_SIZE - 1);
333
334         uint8_t key[MAX_KEY_SIZE], PKEK2[MAX_KEY_SIZE];
335
336         if (!RAND_bytes(key, m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength) ||
337                         !RAND_bytes(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE))
338                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
339
340         if (!PKCS5_PBKDF2_HMAC_SHA1(
341                                 resized_smackLabel.c_str(),
342                                 strlen(resized_smackLabel.c_str()),
343                                 m_kmcDKEK->getKeyAndInfo().key,
344                                 MAX_SALT_SIZE,
345                                 PBKDF2_ITERATIONS,
346                                 MAX_KEY_SIZE,
347                                 PKEK2))
348                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
349
350         int wrappedKeyLength;
351
352         if (0 > (wrappedKeyLength = encryptAes256Gcm(
353                                                                         key,
354                                                                         m_kmcDKEK->getKeyAndInfo().keyInfo.keyLength,
355                                                                         PKEK2,
356                                                                         wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
357                                                                         wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
358                                                                         wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag)))
359                 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
360
361         wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
362         wkmcDEK.setKeyInfoLabel(resized_smackLabel);
363
364         LogDebug("GenerateDEK Success");
365         return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
366 }
367
368 RawBuffer KeyProvider::reencrypt(
369         const RawBuffer &domainKEKInWrapForm,
370         const Password &oldPass,
371         const Password &newPass)
372 {
373         if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
374                 LogError("input size:" << domainKEKInWrapForm.size()
375                                  << " Expected: " << sizeof(WrappedKeyAndInfo));
376                 ThrowErr(Exc::InternalError,
377                                  "buffer doesn't have proper size to store "
378                                  "WrappedKeyAndInfo in KeyProvider::reencrypt");
379         }
380
381         WrappedKeyAndInfoContainer wkmcOldDKEK = WrappedKeyAndInfoContainer(
382                                 domainKEKInWrapForm.data());
383         WrappedKeyAndInfoContainer wkmcNewDKEK = WrappedKeyAndInfoContainer();
384         KeyAndInfoContainer kmcDKEK = KeyAndInfoContainer();
385
386         char *concat_user_pass = NULL;
387         uint8_t PKEK1[MAX_KEY_SIZE];
388         int keyLength = 0;
389
390
391         concat_user_pass = concat_password_user(
392                                                    wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.label,
393                                                    oldPass.c_str());
394
395         if (!PKCS5_PBKDF2_HMAC_SHA1(
396                                 concat_user_pass,
397                                 strlen(concat_user_pass),
398                                 wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.salt,
399                                 MAX_SALT_SIZE,
400                                 PBKDF2_ITERATIONS,
401                                 MAX_KEY_SIZE,
402                                 PKEK1)) {
403                 delete[] concat_user_pass;
404                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
405         }
406
407         delete[] concat_user_pass;
408
409         if (0 > (keyLength = decryptAes256Gcm(
410                                                          wkmcOldDKEK.getWrappedKeyAndInfo().wrappedKey,
411                                                          wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
412                                                          wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.tag,
413                                                          PKEK1,
414                                                          wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo.iv,
415                                                          kmcDKEK.getKeyAndInfo().key)))
416                 ThrowErr(Exc::AuthenticationFailed, "Incorrect Old Password ");
417
418         kmcDKEK.setKeyInfo(&(wkmcOldDKEK.getWrappedKeyAndInfo().keyInfo));
419         kmcDKEK.setKeyInfoKeyLength((unsigned int)keyLength);
420
421         concat_user_pass = concat_password_user(
422                                                    kmcDKEK.getKeyAndInfo().keyInfo.label,
423                                                    newPass.c_str());
424
425         if (!PKCS5_PBKDF2_HMAC_SHA1(
426                                 concat_user_pass,
427                                 strlen(concat_user_pass),
428                                 kmcDKEK.getKeyAndInfo().keyInfo.salt,
429                                 MAX_SALT_SIZE,
430                                 PBKDF2_ITERATIONS,
431                                 MAX_KEY_SIZE,
432                                 PKEK1)) {
433                 delete[] concat_user_pass;
434                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
435         }
436
437         delete[] concat_user_pass;
438
439         int wrappedKeyLength = 0;
440         wkmcNewDKEK.setKeyInfo(&(kmcDKEK.getKeyAndInfo().keyInfo));
441
442         if (0 > (wrappedKeyLength = encryptAes256Gcm(
443                                                                         kmcDKEK.getKeyAndInfo().key,
444                                                                         kmcDKEK.getKeyAndInfo().keyInfo.keyLength,
445                                                                         PKEK1,
446                                                                         kmcDKEK.getKeyAndInfo().keyInfo.iv,
447                                                                         wkmcNewDKEK.getWrappedKeyAndInfo().wrappedKey,
448                                                                         wkmcNewDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
449                 ThrowErr(Exc::InternalError,
450                                  "UpdateDomainKEK in KeyProvider::reencrypt Failed");
451
452         wkmcNewDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
453
454         LogDebug("reencrypt SUCCESS");
455         return toRawBuffer(wkmcNewDKEK.getWrappedKeyAndInfo());
456 }
457
458
459 RawBuffer KeyProvider::generateDomainKEK(
460         const std::string &user,
461         const Password &userPassword)
462 {
463         WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
464         uint8_t key[MAX_KEY_SIZE], PKEK1[MAX_KEY_SIZE];
465
466         if (!RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt, MAX_SALT_SIZE) ||
467                         !RAND_bytes(key, MAX_KEY_SIZE) ||
468                         !RAND_bytes(wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv, MAX_IV_SIZE))
469                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
470
471         int wrappedKeyLength;
472         char *concat_user_pass = NULL;
473         concat_user_pass = concat_password_user(user.c_str(), userPassword.c_str());
474
475         if (!PKCS5_PBKDF2_HMAC_SHA1(
476                                 concat_user_pass,
477                                 strlen(concat_user_pass),
478                                 wkmcDKEK.getWrappedKeyAndInfo().keyInfo.salt,
479                                 MAX_SALT_SIZE,
480                                 PBKDF2_ITERATIONS,
481                                 MAX_KEY_SIZE,
482                                 PKEK1)) {
483                 delete[] concat_user_pass;
484                 ThrowErr(Exc::InternalError, "OPENSSL_ENGINED_ERROR");
485         }
486
487         delete[] concat_user_pass;
488
489         if (0 > (wrappedKeyLength = encryptAes256Gcm(
490                                                                         key,
491                                                                         MAX_KEY_SIZE,
492                                                                         PKEK1,
493                                                                         wkmcDKEK.getWrappedKeyAndInfo().keyInfo.iv,
494                                                                         wkmcDKEK.getWrappedKeyAndInfo().wrappedKey,
495                                                                         wkmcDKEK.getWrappedKeyAndInfo().keyInfo.tag)))
496                 ThrowErr(Exc::InternalError,
497                                  "GenerateDomainKEK Failed in KeyProvider::generateDomainKEK");
498
499         wkmcDKEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
500         wkmcDKEK.setKeyInfoLabel(user);
501
502         LogDebug("generateDomainKEK Success");
503         return toRawBuffer(wkmcDKEK.getWrappedKeyAndInfo());
504 }
505
506 int KeyProvider::initializeLibrary()
507 {
508         LogDebug("initializeLibrary Success");
509         return SUCCESS;
510 }
511
512 int KeyProvider::closeLibrary()
513 {
514         LogDebug("closeLibrary Success");
515         return SUCCESS;
516 }
517
518 KeyProvider::~KeyProvider()
519 {
520         LogDebug("KeyProvider Destructor");
521 }
522
523 int KeyProvider::encryptAes256Gcm(const unsigned char *plaintext,
524                                                                   int plaintext_len, const unsigned char *key, const unsigned char *iv,
525                                                                   unsigned char *ciphertext, unsigned char *tag)
526 {
527         EVP_CIPHER_CTX *ctx;
528         int len;
529         int ciphertext_len = 0;
530
531         if (!(ctx = EVP_CIPHER_CTX_new()))
532                 return OPENSSL_ENGINE_ERROR;
533
534         if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
535                 return OPENSSL_ENGINE_ERROR;
536
537         if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
538                 return OPENSSL_ENGINE_ERROR;
539
540         if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
541                 return OPENSSL_ENGINE_ERROR;
542
543         if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
544                 return OPENSSL_ENGINE_ERROR;
545
546         ciphertext_len = len;
547
548         if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
549                 return OPENSSL_ENGINE_ERROR;
550
551         ciphertext_len += len;
552
553         if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag))
554                 return OPENSSL_ENGINE_ERROR;
555
556         EVP_CIPHER_CTX_free(ctx);
557
558         return ciphertext_len;
559 }
560
561 int KeyProvider::decryptAes256Gcm(const unsigned char *ciphertext,
562                                                                   int ciphertext_len, unsigned char *tag, const unsigned char *key,
563                                                                   const unsigned char *iv, unsigned char *plaintext)
564 {
565         EVP_CIPHER_CTX *ctx;
566         int len;
567         int plaintext_len;
568         int ret;
569
570         if (!(ctx = EVP_CIPHER_CTX_new()))
571                 return OPENSSL_ENGINE_ERROR;
572
573         if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
574                 return OPENSSL_ENGINE_ERROR;
575
576         if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
577                 return OPENSSL_ENGINE_ERROR;
578
579         if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
580                 return OPENSSL_ENGINE_ERROR;
581
582         if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag))
583                 return OPENSSL_ENGINE_ERROR;
584
585         if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
586                 return OPENSSL_ENGINE_ERROR;
587
588         plaintext_len = len;
589
590         if (!(ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len)))
591                 return OPENSSL_ENGINE_ERROR;
592
593         EVP_CIPHER_CTX_free(ctx);
594
595         if (ret > 0) {
596                 plaintext_len += len;
597                 return plaintext_len;
598         } else {
599                 return -1;
600         }
601 }
602
603 char *KeyProvider::concat_password_user(const char *user, const char *password)
604 {
605         char *concat_user_pass = NULL;
606         char *resized_user = NULL;
607         int concat_user_pass_len = 0;
608
609         if (strlen(user) > MAX_LABEL_SIZE - 1) {
610                 resized_user = new char[MAX_LABEL_SIZE];
611                 memcpy(resized_user, user, MAX_LABEL_SIZE - 1);
612                 resized_user[MAX_LABEL_SIZE - 1] = '\0';
613         } else {
614                 resized_user = new char[strlen(user) + 1];
615                 memcpy(resized_user, user, strlen(user));
616                 resized_user[strlen(user)] = '\0';
617         }
618
619         concat_user_pass_len = strlen(resized_user) + strlen(password) + 1;
620         concat_user_pass = new char[concat_user_pass_len];
621
622         memset(concat_user_pass, '\0', concat_user_pass_len);
623         memcpy(concat_user_pass, password, strlen(password));
624         memcpy(&(concat_user_pass[strlen(password)]), resized_user,
625                    strlen(resized_user));
626         concat_user_pass[strlen(resized_user) + strlen(password)] = '\0';
627
628         delete[] resized_user;
629         return concat_user_pass;
630 }