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