2 * Copyright (c) 2014 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 #include <exception.h>
18 #include <key-provider.h>
19 #include <dpl/log/log.h>
29 RawBuffer toRawBuffer(const T &data)
32 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
33 output.assign(ptr, ptr + sizeof(T));
37 // You cannot use toRawBuffer template with pointers
39 RawBuffer toRawBuffer(T *)
41 class NoPointerAllowed {
48 int encryptAes256Gcm(const unsigned char *plaintext,
49 int plaintext_len, const unsigned char *key, const unsigned char *iv,
50 unsigned char *ciphertext, unsigned char *tag)
54 int ciphertext_len = 0;
56 if (!(ctx = EVP_CIPHER_CTX_new()))
57 return OPENSSL_ENGINE_ERROR;
59 if (!EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
60 return OPENSSL_ENGINE_ERROR;
62 if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv))
63 return OPENSSL_ENGINE_ERROR;
65 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
66 return OPENSSL_ENGINE_ERROR;
68 if (!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
69 return OPENSSL_ENGINE_ERROR;
73 if (!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
74 return OPENSSL_ENGINE_ERROR;
76 ciphertext_len += len;
78 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag))
79 return OPENSSL_ENGINE_ERROR;
81 EVP_CIPHER_CTX_free(ctx);
83 return ciphertext_len;
86 int decryptAes256Gcm(const unsigned char *ciphertext,
87 int ciphertext_len, unsigned char *tag, const unsigned char *key,
88 const unsigned char *iv, unsigned char *plaintext)
95 if (!(ctx = EVP_CIPHER_CTX_new()))
96 return OPENSSL_ENGINE_ERROR;
98 if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL))
99 return OPENSSL_ENGINE_ERROR;
101 if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
102 return OPENSSL_ENGINE_ERROR;
104 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
105 return OPENSSL_ENGINE_ERROR;
107 if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag))
108 return OPENSSL_ENGINE_ERROR;
110 if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
111 return OPENSSL_ENGINE_ERROR;
115 if (!(ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len)))
116 return OPENSSL_ENGINE_ERROR;
118 EVP_CIPHER_CTX_free(ctx);
121 plaintext_len += len;
122 return plaintext_len;
128 typedef std::array<uint8_t, MAX_KEY_SIZE> KeyData;
130 // derives a key used for DomainKEK encryption (aka PKEK1) from random salt & user password
131 KeyData makePKEK1(const KeyComponentsInfo& keyInfo, const Password &password)
133 std::string concatPasswordClient(password.c_str());
134 concatPasswordClient += std::string(keyInfo.client);
137 if (!PKCS5_PBKDF2_HMAC_SHA1(concatPasswordClient.c_str(),
138 concatPasswordClient.size(),
144 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
149 // derives a key used for DB DEK encryption (aka PKEK2) from DomainKEK and user id
150 KeyData makePKEK2(const uint8_t *domainKEK, const std::string &user)
153 if (!PKCS5_PBKDF2_HMAC_SHA1(user.c_str(),
160 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
165 void unwrapDomainKEK(const RawBuffer &wrappedDomainKEKbuffer,
166 const Password &password,
167 KeyAndInfoContainer &domainKEK)
169 WrappedKeyAndInfoContainer wrappedDomainKEK(wrappedDomainKEKbuffer.data());
171 KeyData PKEK1 = makePKEK1(wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo, password);
174 if (0 > (keyLength = decryptAes256Gcm(wrappedDomainKEK.getWrappedKeyAndInfo().wrappedKey,
175 wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
176 wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.tag,
178 wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.iv,
179 domainKEK.getKeyAndInfo().key)))
180 ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
182 domainKEK.setKeyInfo(&(wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo));
183 domainKEK.setKeyInfoKeyLength(static_cast<unsigned int>(keyLength));
186 RawBuffer wrapDomainKEK(KeyAndInfoContainer &domainKEK, const Password &password)
188 KeyData PKEK1 = makePKEK1(domainKEK.getKeyAndInfo().keyInfo, password);
190 WrappedKeyAndInfoContainer wrappedDomainKEK = WrappedKeyAndInfoContainer();
191 wrappedDomainKEK.setKeyInfo(&(domainKEK.getKeyAndInfo().keyInfo));
194 if (0 > (wrappedLength = encryptAes256Gcm(domainKEK.getKeyAndInfo().key,
195 domainKEK.getKeyAndInfo().keyInfo.keyLength,
197 domainKEK.getKeyAndInfo().keyInfo.iv,
198 wrappedDomainKEK.getWrappedKeyAndInfo().wrappedKey,
199 wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.tag)))
200 ThrowErr(Exc::InternalError, "DomainKEK encryption failed");
202 wrappedDomainKEK.setKeyInfoKeyLength(static_cast<unsigned int>(wrappedLength));
203 return toRawBuffer(wrappedDomainKEK.getWrappedKeyAndInfo());
207 bool randomize(uint8_t (&array)[N])
209 return RAND_bytes(array, N) == 1;
212 } // anonymous namespace
214 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
216 memset(&wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
219 WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char
222 memcpy(&wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
224 if (wrappedKeyAndInfo.keyInfo.keyLength > sizeof(wrappedKeyAndInfo.wrappedKey)) {
225 ThrowErr(Exc::InternalError,
226 "Wrapped key info is corrupted. Key length exceeds the size of the key buffer.");
229 size_t maxlen = sizeof(wrappedKeyAndInfo.keyInfo.client);
230 if (strnlen(wrappedKeyAndInfo.keyInfo.client, maxlen) == maxlen) {
231 ThrowErr(Exc::InternalError,
232 "Wrapped key info is corrupted. Client id is not NULL terminated.");
236 WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
238 return wrappedKeyAndInfo;
241 void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const unsigned int length)
243 wrappedKeyAndInfo.keyInfo.keyLength = length;
246 void WrappedKeyAndInfoContainer::setKeyInfoClient(const std::string resized_client)
248 if (resized_client.size() >= sizeof(wrappedKeyAndInfo.keyInfo.client)) {
249 ThrowErr(Exc::InternalError, "Client name too long");
252 strcpy(wrappedKeyAndInfo.keyInfo.client, resized_client.c_str());
255 void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt,
258 memcpy(wrappedKeyAndInfo.keyInfo.salt, salt, size);
261 void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo
264 memcpy(&(wrappedKeyAndInfo.keyInfo), keyComponentsInfo,
265 sizeof(KeyComponentsInfo));
268 WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
272 KeyAndInfoContainer::KeyAndInfoContainer()
274 memset(&keyAndInfo, 0, sizeof(KeyAndInfo));
277 KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
279 memcpy(&keyAndInfo, data, sizeof(KeyAndInfo));
282 KeyAndInfo &KeyAndInfoContainer::getKeyAndInfo()
287 void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
289 keyAndInfo.keyInfo.keyLength = length;
292 void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
294 memcpy(&(keyAndInfo.keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
297 KeyAndInfoContainer::~KeyAndInfoContainer()
300 char *ptr = reinterpret_cast<char *>(&keyAndInfo);
301 memset(ptr, 0, sizeof(KeyAndInfo));
304 for (size_t size = 0; size < sizeof(KeyAndInfo); ++size) {
306 LogError("Write memory error! Memory used by key was not owerwritten.");
310 KeyProvider::KeyProvider() :
312 m_isInitialized(false)
314 LogDebug("Created empty KeyProvider");
317 KeyProvider::KeyProvider(
318 const RawBuffer &domainKEKInWrapForm,
319 const Password &password) :
320 m_domainKEK(new KeyAndInfoContainer()),
321 m_isInitialized(true)
323 if (!m_isInitialized)
324 ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
326 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
327 LogError("input size:" << domainKEKInWrapForm.size()
328 << " Expected: " << sizeof(WrappedKeyAndInfo));
329 ThrowErr(Exc::InternalError,
330 "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
333 unwrapDomainKEK(domainKEKInWrapForm, password, *m_domainKEK);
336 KeyProvider &KeyProvider::operator=(KeyProvider &&second)
338 LogDebug("Moving KeyProvider");
343 m_isInitialized = second.m_isInitialized;
344 m_domainKEK = second.m_domainKEK;
345 second.m_isInitialized = false;
346 second.m_domainKEK = NULL;
350 KeyProvider::KeyProvider(KeyProvider &&second)
352 LogDebug("Moving KeyProvider");
353 m_isInitialized = second.m_isInitialized;
354 m_domainKEK = second.m_domainKEK;
355 second.m_isInitialized = false;
356 second.m_domainKEK = NULL;
359 bool KeyProvider::isInitialized()
361 return m_isInitialized;
364 RawBuffer KeyProvider::getPureDomainKEK()
366 if (!m_isInitialized)
367 ThrowErr(Exc::InternalError, "Object not initialized!");
370 return RawBuffer(m_domainKEK->getKeyAndInfo().key,
371 (m_domainKEK->getKeyAndInfo().key) +
372 m_domainKEK->getKeyAndInfo().keyInfo.keyLength);
375 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
377 if (!m_isInitialized)
378 ThrowErr(Exc::InternalError, "Object not initialized!");
380 return wrapDomainKEK(*m_domainKEK, password);
384 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
386 if (!m_isInitialized)
387 ThrowErr(Exc::InternalError, "Object not initialized!");
389 if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
390 LogError("input size:" << DEKInWrapForm.size()
391 << " Expected: " << sizeof(WrappedKeyAndInfo));
392 ThrowErr(Exc::InternalError,
393 "buffer doesn't have proper size to store "
394 "WrappedKeyAndInfo in KeyProvider::getPureDEK");
397 KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
398 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(
399 DEKInWrapForm.data());
401 KeyData PKEK2 = makePKEK2(m_domainKEK->getKeyAndInfo().key,
402 wkmcDEK.getWrappedKeyAndInfo().keyInfo.client);
405 if (0 > (keyLength = decryptAes256Gcm(
406 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
407 wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
408 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
410 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
411 kmcDEK.getKeyAndInfo().key)))
412 ThrowErr(Exc::InternalError,
413 "UnwrapDEK Failed in KeyProvider::getPureDEK");
415 kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
417 LogDebug("getPureDEK SUCCESS");
419 kmcDEK.getKeyAndInfo().key,
420 (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
423 RawBuffer KeyProvider::generateDEK(const ClientId &client)
425 if (!m_isInitialized)
426 ThrowErr(Exc::InternalError, "Object not initialized!");
428 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
429 std::string resized_client;
431 if (client.length() < MAX_CLIENT_ID_SIZE)
432 resized_client = client;
434 resized_client = client.substr(0, MAX_CLIENT_ID_SIZE - 1);
436 uint8_t key[MAX_KEY_SIZE];
438 if (!randomize(key) || !randomize(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv))
439 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
441 KeyData PKEK2 = makePKEK2(m_domainKEK->getKeyAndInfo().key, resized_client);
443 int wrappedKeyLength;
444 if (0 > (wrappedKeyLength = encryptAes256Gcm(key,
445 m_domainKEK->getKeyAndInfo().keyInfo.keyLength,
447 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
448 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
449 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag)))
450 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
452 wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
453 wkmcDEK.setKeyInfoClient(resized_client);
455 LogDebug("GenerateDEK Success");
456 return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
459 RawBuffer KeyProvider::reencrypt(
460 const RawBuffer &domainKEKInWrapForm,
461 const Password &oldPass,
462 const Password &newPass)
464 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
465 LogError("input size:" << domainKEKInWrapForm.size()
466 << " Expected: " << sizeof(WrappedKeyAndInfo));
467 ThrowErr(Exc::InternalError,
468 "buffer doesn't have proper size to store "
469 "WrappedKeyAndInfo in KeyProvider::reencrypt");
472 KeyAndInfoContainer domainKEK;
473 unwrapDomainKEK(domainKEKInWrapForm, oldPass, domainKEK);
474 return wrapDomainKEK(domainKEK, newPass);
477 RawBuffer KeyProvider::generateDomainKEK(
478 const std::string &user,
479 const Password &userPassword)
481 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
483 KeyAndInfoContainer domainKEK;
485 if (!randomize(domainKEK.getKeyAndInfo().keyInfo.salt) ||
486 !randomize(domainKEK.getKeyAndInfo().key) ||
487 !randomize(domainKEK.getKeyAndInfo().keyInfo.iv)) {
488 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
491 domainKEK.setKeyInfoKeyLength(sizeof(domainKEK.getKeyAndInfo().key));
493 if (user.size() >= sizeof(domainKEK.getKeyAndInfo().keyInfo.client)) {
494 ThrowErr(Exc::InternalError, "Client name too long");
496 strcpy(domainKEK.getKeyAndInfo().keyInfo.client, user.c_str());
498 return wrapDomainKEK(domainKEK, userPassword);
501 int KeyProvider::initializeLibrary()
503 LogDebug("initializeLibrary Success");
507 int KeyProvider::closeLibrary()
509 LogDebug("closeLibrary Success");
513 KeyProvider::~KeyProvider()
515 LogDebug("KeyProvider Destructor");