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