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>
20 #include <ckm/ckm-zero-memory.h>
31 RawBuffer toRawBuffer(const T &data)
34 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&data);
35 output.assign(ptr, ptr + sizeof(T));
39 // You cannot use toRawBuffer template with pointers
41 RawBuffer toRawBuffer(T *)
43 class NoPointerAllowed {
50 typedef std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)> CipherCtxPtr;
52 int encryptAes256Gcm(const unsigned char *plaintext,
53 int plaintext_len, const unsigned char *key, const unsigned char *iv,
54 unsigned char *ciphertext, unsigned char *tag)
57 int ciphertext_len = 0;
59 CipherCtxPtr ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
61 return OPENSSL_ENGINE_ERROR;
63 if (!EVP_EncryptInit_ex(ctx.get(), EVP_aes_256_gcm(), NULL, NULL, NULL))
64 return OPENSSL_ENGINE_ERROR;
66 if (!EVP_EncryptInit_ex(ctx.get(), NULL, NULL, key, iv))
67 return OPENSSL_ENGINE_ERROR;
69 if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
70 return OPENSSL_ENGINE_ERROR;
72 if (!EVP_EncryptUpdate(ctx.get(), ciphertext, &len, plaintext, plaintext_len))
73 return OPENSSL_ENGINE_ERROR;
77 if (!EVP_EncryptFinal_ex(ctx.get(), ciphertext + len, &len))
78 return OPENSSL_ENGINE_ERROR;
80 ciphertext_len += len;
82 if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, MAX_IV_SIZE, tag))
83 return OPENSSL_ENGINE_ERROR;
85 return ciphertext_len;
88 int decryptAes256Gcm(const unsigned char *ciphertext,
89 int ciphertext_len, unsigned char *tag, const unsigned char *key,
90 const unsigned char *iv, unsigned char *plaintext)
96 CipherCtxPtr ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
98 return OPENSSL_ENGINE_ERROR;
100 if (!EVP_DecryptInit_ex(ctx.get(), EVP_aes_256_gcm(), NULL, NULL, NULL))
101 return OPENSSL_ENGINE_ERROR;
103 if (!EVP_DecryptInit_ex(ctx.get(), NULL, NULL, key, iv))
104 return OPENSSL_ENGINE_ERROR;
106 if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, MAX_IV_SIZE, NULL))
107 return OPENSSL_ENGINE_ERROR;
109 if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, MAX_IV_SIZE, tag))
110 return OPENSSL_ENGINE_ERROR;
112 if (!EVP_DecryptUpdate(ctx.get(), plaintext, &len, ciphertext, ciphertext_len))
113 return OPENSSL_ENGINE_ERROR;
117 if (!(ret = EVP_DecryptFinal_ex(ctx.get(), plaintext + len, &len)))
118 return OPENSSL_ENGINE_ERROR;
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 (PKEK2) from DomainKEK and custom client string (may be a client id or uid)
150 KeyData makePKEK2(const uint8_t *domainKEK, const std::string &client)
153 if (!PKCS5_PBKDF2_HMAC_SHA1(client.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 strncpy(wrappedKeyAndInfo.keyInfo.client, resized_client.c_str(), resized_client.size());
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 ZeroMemory(reinterpret_cast<unsigned char*>(&keyAndInfo), sizeof(KeyAndInfo));
303 KeyProvider::KeyProvider() :
305 m_isInitialized(false)
307 LogDebug("Created empty KeyProvider");
310 KeyProvider::KeyProvider(
311 const RawBuffer &domainKEKInWrapForm,
312 const Password &password) :
313 m_domainKEK(new KeyAndInfoContainer()),
314 m_isInitialized(true)
316 if (!m_isInitialized)
317 ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
319 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
320 LogError("input size:" << domainKEKInWrapForm.size()
321 << " Expected: " << sizeof(WrappedKeyAndInfo));
322 ThrowErr(Exc::InternalError,
323 "buffer doesn't have proper size to store WrappedKeyAndInfo in KeyProvider Constructor");
326 unwrapDomainKEK(domainKEKInWrapForm, password, *m_domainKEK);
329 KeyProvider &KeyProvider::operator=(KeyProvider &&second)
331 LogDebug("Moving KeyProvider");
336 m_isInitialized = second.m_isInitialized;
337 m_domainKEK = second.m_domainKEK;
338 second.m_isInitialized = false;
339 second.m_domainKEK = NULL;
343 KeyProvider::KeyProvider(KeyProvider &&second)
345 LogDebug("Moving KeyProvider");
346 m_isInitialized = second.m_isInitialized;
347 m_domainKEK = second.m_domainKEK;
348 second.m_isInitialized = false;
349 second.m_domainKEK = NULL;
352 bool KeyProvider::isInitialized()
354 return m_isInitialized;
357 RawBuffer KeyProvider::getPureDomainKEK()
359 if (!m_isInitialized)
360 ThrowErr(Exc::InternalError, "Object not initialized!");
363 return RawBuffer(m_domainKEK->getKeyAndInfo().key,
364 (m_domainKEK->getKeyAndInfo().key) +
365 m_domainKEK->getKeyAndInfo().keyInfo.keyLength);
368 RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
370 if (!m_isInitialized)
371 ThrowErr(Exc::InternalError, "Object not initialized!");
373 return wrapDomainKEK(*m_domainKEK, password);
377 RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
379 if (!m_isInitialized)
380 ThrowErr(Exc::InternalError, "Object not initialized!");
382 if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
383 LogError("input size:" << DEKInWrapForm.size()
384 << " Expected: " << sizeof(WrappedKeyAndInfo));
385 ThrowErr(Exc::InternalError,
386 "buffer doesn't have proper size to store "
387 "WrappedKeyAndInfo in KeyProvider::getPureDEK");
390 KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
391 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(
392 DEKInWrapForm.data());
394 KeyData PKEK2 = makePKEK2(m_domainKEK->getKeyAndInfo().key,
395 wkmcDEK.getWrappedKeyAndInfo().keyInfo.client);
398 if (0 > (keyLength = decryptAes256Gcm(
399 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
400 wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
401 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
403 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
404 kmcDEK.getKeyAndInfo().key)))
405 ThrowErr(Exc::InternalError,
406 "UnwrapDEK Failed in KeyProvider::getPureDEK");
408 kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
410 LogDebug("getPureDEK SUCCESS");
412 kmcDEK.getKeyAndInfo().key,
413 (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
416 RawBuffer KeyProvider::generateDEK(const std::string &client)
418 if (!m_isInitialized)
419 ThrowErr(Exc::InternalError, "Object not initialized!");
421 WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
422 std::string resized_client;
424 if (client.length() < MAX_CLIENT_ID_SIZE)
425 resized_client = client;
427 resized_client = client.substr(0, MAX_CLIENT_ID_SIZE - 1);
429 uint8_t key[MAX_KEY_SIZE];
431 if (!randomize(key) || !randomize(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv))
432 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
434 KeyData PKEK2 = makePKEK2(m_domainKEK->getKeyAndInfo().key, resized_client);
436 int wrappedKeyLength;
437 if (0 > (wrappedKeyLength = encryptAes256Gcm(key,
438 m_domainKEK->getKeyAndInfo().keyInfo.keyLength,
440 wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
441 wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
442 wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag)))
443 ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
445 wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
446 wkmcDEK.setKeyInfoClient(resized_client);
448 LogDebug("GenerateDEK Success");
449 return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
452 RawBuffer KeyProvider::reencrypt(
453 const RawBuffer &domainKEKInWrapForm,
454 const Password &oldPass,
455 const Password &newPass)
457 if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
458 LogError("input size:" << domainKEKInWrapForm.size()
459 << " Expected: " << sizeof(WrappedKeyAndInfo));
460 ThrowErr(Exc::InternalError,
461 "buffer doesn't have proper size to store "
462 "WrappedKeyAndInfo in KeyProvider::reencrypt");
465 KeyAndInfoContainer domainKEK;
466 unwrapDomainKEK(domainKEKInWrapForm, oldPass, domainKEK);
467 return wrapDomainKEK(domainKEK, newPass);
470 RawBuffer KeyProvider::generateDomainKEK(
471 const std::string &user,
472 const Password &userPassword)
474 WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
476 KeyAndInfoContainer domainKEK;
478 if (!randomize(domainKEK.getKeyAndInfo().keyInfo.salt) ||
479 !randomize(domainKEK.getKeyAndInfo().key) ||
480 !randomize(domainKEK.getKeyAndInfo().keyInfo.iv)) {
481 ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
484 domainKEK.setKeyInfoKeyLength(sizeof(domainKEK.getKeyAndInfo().key));
486 if (user.size() >= sizeof(domainKEK.getKeyAndInfo().keyInfo.client)) {
487 ThrowErr(Exc::InternalError, "Client name too long");
489 strncpy(domainKEK.getKeyAndInfo().keyInfo.client, user.c_str(), user.size());
491 return wrapDomainKEK(domainKEK, userPassword);
494 int KeyProvider::initializeLibrary()
496 LogDebug("initializeLibrary Success");
500 int KeyProvider::closeLibrary()
502 LogDebug("closeLibrary Success");
506 KeyProvider::~KeyProvider()
508 LogDebug("KeyProvider Destructor");