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