* limitations under the License
*/
-#include <exception.h>
+#include <array>
+
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
#include <key-provider.h>
-#include <dpl/log/log.h>
#include <ckm/ckm-zero-memory.h>
#include <utils.h>
#include <string.h>
-#include <array>
#include <crypto-backend.h>
#ifdef SE_BACKEND_ENABLED
#include <se-backend/internals.h>
namespace {
+constexpr int PBKDF2_ITERATIONS = 4096;
+constexpr uint32_t KEYCOMPONENT_VERSION = 2;
+constexpr int OPENSSL_ENGINE_ERROR = -4;
+
template<typename T>
RawBuffer toRawBuffer(const T &data)
{
}
typedef std::array<uint8_t, MAX_KEY_SIZE> KeyData;
+
+KeyData PBKDF(const std::string& pass, const unsigned char *salt, int saltlen)
+{
+ KeyData key;
+ if (!PKCS5_PBKDF2_HMAC_SHA1(pass.c_str(),
+ pass.size(),
+ salt,
+ saltlen,
+ PBKDF2_ITERATIONS,
+ key.size(),
+ key.data())) {
+ ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
+ }
+ return key;
+}
+
// derives a key used for DomainKEK encryption (aka PKEK1) from random salt & user password
-KeyData makePKEK1(const KeyComponentsInfoDKEK& keyInfo, const Password &password)
+KeyData makePKEK1(const DomainKEKInfo& domainKEKInfo, const Password &password)
{
std::string concatPasswordClient(password.c_str());
- concatPasswordClient += std::string(keyInfo.client);
- KeyData key;
- if (keyInfo.version != KEYCOMPONENT_VERSION)
+ concatPasswordClient += std::string(domainKEKInfo.client);
+
+ if (domainKEKInfo.version != KEYCOMPONENT_VERSION)
ThrowErr(Exc::InternalError, "It's not expected version");
-#if SE_BACKEND_ENABLED
RawBuffer salt;
- if (keyInfo.backend == (int)CryptoBackend::SecureElement) {
- salt = Crypto::SE::Internals::encryptWithDbpKey((unsigned char*)keyInfo.salt, MAX_SALT_SIZE,
- (unsigned char*)keyInfo.iv, MAX_IV_SIZE);
- } else {
- salt = RawBuffer(keyInfo.salt, keyInfo.salt + MAX_SALT_SIZE);
- }
+ if (domainKEKInfo.backend == (int)CryptoBackend::SecureElement) {
+#if SE_BACKEND_ENABLED
+ salt = Crypto::SE::Internals::encryptWithDbpKey((unsigned char*)domainKEKInfo.salt,
+ MAX_SALT_SIZE,
+ (unsigned char*)domainKEKInfo.iv,
+ MAX_IV_SIZE);
#else
- if (keyInfo.backend != (int)CryptoBackend::OpenSSL)
ThrowErr(Exc::InternalError, "It's not expected backend");
-
- RawBuffer salt(keyInfo.salt, keyInfo.salt + MAX_SALT_SIZE);
#endif
- if (!PKCS5_PBKDF2_HMAC_SHA1(concatPasswordClient.c_str(),
- concatPasswordClient.size(),
- salt.data(),
- salt.size(),
- PBKDF2_ITERATIONS,
- key.size(),
- key.data())) {
- ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
+ } else if (domainKEKInfo.backend == (int)CryptoBackend::OpenSSL) {
+ salt = RawBuffer(domainKEKInfo.salt, domainKEKInfo.salt + MAX_SALT_SIZE);
+ } else {
+ ThrowErr(Exc::InternalError, "It's not expected backend");
}
- return key;
+
+ return PBKDF(concatPasswordClient, salt.data(), salt.size());
}
// derives a key (PKEK2) from DomainKEK and custom client string (may be a client id or uid)
KeyData makePKEK2(const uint8_t *domainKEK, const std::string &client)
{
- KeyData key;
- if (!PKCS5_PBKDF2_HMAC_SHA1(client.c_str(),
- client.size(),
- domainKEK,
- MAX_SALT_SIZE,
- PBKDF2_ITERATIONS,
- key.size(),
- key.data())) {
- ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
- }
- return key;
+ return PBKDF(client, domainKEK, MAX_SALT_SIZE);
}
void unwrapDomainKEK(const RawBuffer &wrappedDomainKEKbuffer,
const Password &password,
- KeyAndInfoContainer &domainKEK)
+ DomainKEKAndInfo &domainKEK)
{
- WrappedKeyAndInfoContainer wrappedDomainKEK;
- wrappedDomainKEK.setWrappedDKEKAndInfo(wrappedDomainKEKbuffer.data());
- KeyData PKEK1 = makePKEK1(wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo, password);
+ DomainKEKAndInfo wrappedDomainKEK(wrappedDomainKEKbuffer);
+ KeyData PKEK1 = makePKEK1(wrappedDomainKEK.info, password);
int keyLength;
- if (0 > (keyLength = decryptAes256Gcm(wrappedDomainKEK.getWrappedDKEKAndInfo().wrappedKey,
- wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.keyLength,
- wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.tag,
+ if (0 > (keyLength = decryptAes256Gcm(wrappedDomainKEK.key,
+ wrappedDomainKEK.info.keyLength,
+ wrappedDomainKEK.info.tag,
PKEK1.data(),
- wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.iv,
- domainKEK.getDKEKAndInfo().key)))
+ wrappedDomainKEK.info.iv,
+ domainKEK.key)))
ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
- domainKEK.setKeyInfo(&(wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo));
- domainKEK.setDKEKInfo(wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.version,
- wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.backend);
- domainKEK.setKeyInfoKeyLength(static_cast<unsigned int>(keyLength));
+ domainKEK.setKeyInfo(wrappedDomainKEK.info);
+ domainKEK.info.keyLength = static_cast<uint32_t>(keyLength);
}
-RawBuffer wrapDomainKEK(KeyAndInfoContainer &domainKEK, const Password &password)
+RawBuffer wrapDomainKEK(DomainKEKAndInfo &domainKEK, const Password &password)
{
- KeyData PKEK1 = makePKEK1(domainKEK.getDKEKAndInfo().keyInfo, password);
+ KeyData PKEK1 = makePKEK1(domainKEK.info, password);
- WrappedKeyAndInfoContainer wrappedDomainKEK = WrappedKeyAndInfoContainer();
- wrappedDomainKEK.setKeyInfo(&(domainKEK.getDKEKAndInfo().keyInfo));
- wrappedDomainKEK.setDKEKInfo(domainKEK.getDKEKAndInfo().keyInfo.version,
- domainKEK.getDKEKAndInfo().keyInfo.backend);
+ DomainKEKAndInfo wrappedDomainKEK;
+ wrappedDomainKEK.setKeyInfo(domainKEK.info);
int wrappedLength;
- if (0 > (wrappedLength = encryptAes256Gcm(domainKEK.getDKEKAndInfo().key,
- domainKEK.getDKEKAndInfo().keyInfo.keyLength,
+ if (0 > (wrappedLength = encryptAes256Gcm(domainKEK.key,
+ domainKEK.info.keyLength,
PKEK1.data(),
- domainKEK.getDKEKAndInfo().keyInfo.iv,
- wrappedDomainKEK.getWrappedDKEKAndInfo().wrappedKey,
- wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.tag)))
+ domainKEK.info.iv,
+ wrappedDomainKEK.key,
+ wrappedDomainKEK.info.tag)))
ThrowErr(Exc::InternalError, "DomainKEK encryption failed");
- wrappedDomainKEK.setKeyInfoKeyLength(static_cast<unsigned int>(wrappedLength));
- return toRawBuffer(wrappedDomainKEK.getWrappedDKEKAndInfo());
+ wrappedDomainKEK.info.keyLength = static_cast<uint32_t>(wrappedLength);
+ return toRawBuffer(wrappedDomainKEK);
}
template <size_t N>
} // anonymous namespace
-WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
-{
- memset(&wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
- memset(&wrappedDKEKAndInfo, 0, sizeof(WrappedKeyAndInfoDKEK));
-}
-
-WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
-{
- return wrappedKeyAndInfo;
-}
-
-WrappedKeyAndInfoDKEK &WrappedKeyAndInfoContainer::getWrappedDKEKAndInfo()
-{
- return wrappedDKEKAndInfo;
-}
-
-void WrappedKeyAndInfoContainer::setWrappedKeyAndInfo(
- const unsigned char *data)
-{
- memcpy(&wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
-
- if (wrappedKeyAndInfo.keyInfo.keyLength > sizeof(wrappedKeyAndInfo.wrappedKey)) {
- ThrowErr(Exc::InternalError,
- "Wrapped key info is corrupted. Key length exceeds the size of the key buffer.");
- }
-
- size_t maxlen = sizeof(wrappedKeyAndInfo.keyInfo.client);
- if (strnlen(wrappedKeyAndInfo.keyInfo.client, maxlen) == maxlen) {
- ThrowErr(Exc::InternalError,
- "Wrapped key info is corrupted. Client id is not NULL terminated.");
- }
-}
-
-void WrappedKeyAndInfoContainer::setWrappedDKEKAndInfo(
- const unsigned char *data)
-{
- memcpy(&wrappedDKEKAndInfo, data, sizeof(WrappedKeyAndInfoDKEK));
-
- if (wrappedDKEKAndInfo.keyInfo.keyLength > sizeof(wrappedDKEKAndInfo.wrappedKey)) {
- ThrowErr(Exc::InternalError,
- "Wrapped key info is corrupted. Key length exceeds the size of the key buffer.");
- }
-
- size_t maxlen = sizeof(wrappedDKEKAndInfo.keyInfo.client);
- if (strnlen(wrappedDKEKAndInfo.keyInfo.client, maxlen) == maxlen) {
- ThrowErr(Exc::InternalError,
- "Wrapped key info is corrupted. Client id is not NULL terminated.");
- }
-}
-
-void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const uint32_t length)
-{
- wrappedKeyAndInfo.keyInfo.keyLength = length;
- wrappedDKEKAndInfo.keyInfo.keyLength = length;
-}
-
-void WrappedKeyAndInfoContainer::setKeyInfoClient(const std::string resized_client)
-{
- if (resized_client.size() >= sizeof(wrappedKeyAndInfo.keyInfo.client)) {
- ThrowErr(Exc::InternalError, "Client name too long");
- }
-
- strncpy(wrappedKeyAndInfo.keyInfo.client, resized_client.c_str(), resized_client.size());
- strncpy(wrappedDKEKAndInfo.keyInfo.client, resized_client.c_str(), resized_client.size());
-}
-
-void WrappedKeyAndInfoContainer::setKeyInfoSalt(const unsigned char *salt,
- const int size)
-{
- memcpy(wrappedKeyAndInfo.keyInfo.salt, salt, size);
- memcpy(wrappedDKEKAndInfo.keyInfo.salt, salt, size);
-}
-
-void WrappedKeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo
- *keyComponentsInfo)
-{
- memcpy(&(wrappedKeyAndInfo.keyInfo), keyComponentsInfo,
- sizeof(KeyComponentsInfo));
- wrappedDKEKAndInfo.keyInfo.set(wrappedKeyAndInfo.keyInfo);
-}
-
-void WrappedKeyAndInfoContainer::setDKEKInfo(const uint32_t version, const uint32_t backend)
-{
- wrappedDKEKAndInfo.keyInfo.version = version;
- wrappedDKEKAndInfo.keyInfo.backend = backend;
-}
-
-WrappedKeyAndInfoContainer::~WrappedKeyAndInfoContainer()
-{
-}
-
-KeyAndInfoContainer::KeyAndInfoContainer()
-{
- memset(&keyAndInfo, 0, sizeof(KeyAndInfo));
- memset(&DKEKAndInfo, 0, sizeof(KeyAndInfoDKEK));
-}
-
-KeyAndInfo &KeyAndInfoContainer::getKeyAndInfo()
-{
- return keyAndInfo;
-}
-
-KeyAndInfoDKEK &KeyAndInfoContainer::getDKEKAndInfo()
-{
- return DKEKAndInfo;
-}
-
-void KeyAndInfoContainer::setKeyAndInfo(const unsigned char *data)
-{
- memcpy(&keyAndInfo, data, sizeof(KeyAndInfo));
-}
-
-void KeyAndInfoContainer::setDKEKAndInfo(const unsigned char *data)
-{
- memcpy(&DKEKAndInfo, data, sizeof(KeyAndInfoDKEK));
-}
-
-void KeyAndInfoContainer::setKeyInfoKeyLength(const uint32_t length)
-{
- keyAndInfo.keyInfo.keyLength = length;
- DKEKAndInfo.keyInfo.keyLength = length;
-}
-
-void KeyAndInfoContainer::setKeyInfo(const KeyComponentsInfo *keyComponentsInfo)
-{
- memcpy(&(keyAndInfo.keyInfo), keyComponentsInfo, sizeof(KeyComponentsInfo));
- DKEKAndInfo.keyInfo.set(keyAndInfo.keyInfo);
-}
-
-void KeyAndInfoContainer::setDKEKInfo(const uint32_t version, const uint32_t backend)
-{
- DKEKAndInfo.keyInfo.version = version;
- DKEKAndInfo.keyInfo.backend = backend;
-}
-
-KeyAndInfoContainer::~KeyAndInfoContainer()
-{
- // overwrite key
- ZeroMemory(reinterpret_cast<unsigned char*>(&keyAndInfo), sizeof(KeyAndInfo));
- ZeroMemory(reinterpret_cast<unsigned char*>(&DKEKAndInfo), sizeof(KeyAndInfoDKEK));
-}
-
KeyProvider::KeyProvider() :
m_domainKEK(NULL),
m_isInitialized(false)
KeyProvider::KeyProvider(
const RawBuffer &domainKEKInWrapForm,
const Password &password) :
- m_domainKEK(new KeyAndInfoContainer()),
+ m_domainKEK(new DomainKEKAndInfo()),
m_isInitialized(true)
{
- if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfoDKEK)) {
- LogWarning("input size:" << domainKEKInWrapForm.size()
- << " Expected: " << sizeof(WrappedKeyAndInfoDKEK));
- LogWarning("buffer doesn't have proper size to store WrappedKeyAndInfoDKEK in KeyProvider Constructor");
+ if (domainKEKInWrapForm.size() != sizeof(DomainKEKAndInfo)) {
+ LogWarning("Input size:" << domainKEKInWrapForm.size()
+ << " Expected: " << sizeof(DomainKEKAndInfo));
+ LogWarning("Buffer doesn't have proper size to store DomainKEKAndInfo in KeyProvider"
+ "Constructor");
m_isInitialized = false;
return;
}
ThrowErr(Exc::InternalError, "Object not initialized!");
// TODO secure
- return RawBuffer(m_domainKEK->getDKEKAndInfo().key,
- (m_domainKEK->getDKEKAndInfo().key) +
- m_domainKEK->getDKEKAndInfo().keyInfo.keyLength);
+ return RawBuffer(m_domainKEK->key, m_domainKEK->key + m_domainKEK->info.keyLength);
}
RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
return wrapDomainKEK(*m_domainKEK, password);
}
-
-RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
+RawBuffer KeyProvider::getPureDEK(const RawBuffer &wrappedDEKbuffer)
{
if (!m_isInitialized)
ThrowErr(Exc::InternalError, "Object not initialized!");
- if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
- LogError("input size:" << DEKInWrapForm.size()
- << " Expected: " << sizeof(WrappedKeyAndInfo));
+ if (wrappedDEKbuffer.size() != sizeof(DEKAndInfo)) {
+ LogError("input size:" << wrappedDEKbuffer.size() << " Expected: " << sizeof(DEKAndInfo));
ThrowErr(Exc::InternalError,
- "buffer doesn't have proper size to store "
- "WrappedKeyAndInfo in KeyProvider::getPureDEK");
+ "buffer doesn't have proper size to store KeyAndInfo in KeyProvider::getPureDEK");
}
- KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
- WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
- wkmcDEK.setWrappedKeyAndInfo(DEKInWrapForm.data());
+ DEKAndInfo DEK;
+ DEKAndInfo wrappedDEK(wrappedDEKbuffer);
- KeyData PKEK2 = makePKEK2(m_domainKEK->getDKEKAndInfo().key,
- wkmcDEK.getWrappedKeyAndInfo().keyInfo.client);
+ KeyData PKEK2 = makePKEK2(m_domainKEK->key, wrappedDEK.info.client);
int keyLength;
- if (0 > (keyLength = decryptAes256Gcm(
- wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
- wkmcDEK.getWrappedKeyAndInfo().keyInfo.keyLength,
- wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag,
- PKEK2.data(),
- wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
- kmcDEK.getKeyAndInfo().key)))
- ThrowErr(Exc::InternalError,
- "UnwrapDEK Failed in KeyProvider::getPureDEK");
+ if (0 > (keyLength = decryptAes256Gcm(wrappedDEK.key,
+ wrappedDEK.info.keyLength,
+ wrappedDEK.info.tag,
+ PKEK2.data(),
+ wrappedDEK.info.iv,
+ DEK.key)))
+ ThrowErr(Exc::InternalError, "UnwrapDEK Failed in KeyProvider::getPureDEK");
- kmcDEK.setKeyInfoKeyLength((unsigned int)keyLength);
+ DEK.info.keyLength = static_cast<uint32_t>(keyLength);
LogDebug("getPureDEK SUCCESS");
- return RawBuffer(
- kmcDEK.getKeyAndInfo().key,
- (kmcDEK.getKeyAndInfo().key) + kmcDEK.getKeyAndInfo().keyInfo.keyLength);
+ return RawBuffer(DEK.key, DEK.key + DEK.info.keyLength);
}
RawBuffer KeyProvider::generateDEK(const std::string &client)
if (!m_isInitialized)
ThrowErr(Exc::InternalError, "Object not initialized!");
- WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
+ DEKAndInfo wrappedDEK;
std::string resized_client;
if (client.length() < MAX_CLIENT_ID_SIZE)
else
resized_client = client.substr(0, MAX_CLIENT_ID_SIZE - 1);
- uint8_t key[MAX_KEY_SIZE];
+ uint8_t DEK[MAX_KEY_SIZE];
- if (!randomize(key) || !randomize(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv))
+ if (!randomize(DEK) || !randomize(wrappedDEK.info.iv))
ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
- KeyData PKEK2 = makePKEK2(m_domainKEK->getDKEKAndInfo().key, resized_client);
+ KeyData PKEK2 = makePKEK2(m_domainKEK->key, resized_client);
int wrappedKeyLength;
- if (0 > (wrappedKeyLength = encryptAes256Gcm(key,
- m_domainKEK->getDKEKAndInfo().keyInfo.keyLength,
+ if (0 > (wrappedKeyLength = encryptAes256Gcm(DEK,
+ sizeof(DEK),
PKEK2.data(),
- wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
- wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
- wkmcDEK.getWrappedKeyAndInfo().keyInfo.tag)))
+ wrappedDEK.info.iv,
+ wrappedDEK.key,
+ wrappedDEK.info.tag)))
ThrowErr(Exc::InternalError, "GenerateDEK Failed in KeyProvider::generateDEK");
- wkmcDEK.setKeyInfoKeyLength((unsigned int)wrappedKeyLength);
- wkmcDEK.setKeyInfoClient(resized_client);
+ wrappedDEK.info.keyLength = static_cast<uint32_t>(wrappedKeyLength);
+ wrappedDEK.setKeyInfoClient(resized_client);
LogDebug("GenerateDEK Success");
- return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
+ return toRawBuffer(wrappedDEK);
}
-void KeyProvider::migrateDKEK(const RawBuffer &wrappedDomainKEKbuffer,
- const Password &password)
+void KeyProvider::migrateDomainKEK(const RawBuffer &wrappedDomainKEKbuffer,
+ const Password &password)
{
- WrappedKeyAndInfo wrappedInfo;
- if (wrappedDomainKEKbuffer.size() != sizeof(WrappedKeyAndInfo)) {
- LogError("[migrateDKEK] Input size:" << wrappedDomainKEKbuffer.size() <<
- " Expected: " << sizeof(WrappedKeyAndInfo));
- ThrowErr(Exc::InternalError,
- "buffer doesn't have proper size to store ");
- }
- memcpy(&wrappedInfo, wrappedDomainKEKbuffer.data(), sizeof(WrappedKeyAndInfo));
-
- size_t maxlen = sizeof(wrappedInfo.keyInfo.client);
- if (strnlen(wrappedInfo.keyInfo.client, maxlen) == maxlen) {
- ThrowErr(Exc::InternalError,
- "Wrapped key info is corrupted. Client id is not NULL terminated.");
- }
+ DEKAndInfo wrappedOldDomainKEK(wrappedDomainKEKbuffer);
- KeyComponentsInfo keyInfo = wrappedInfo.keyInfo;
std::string concatPasswordClient(password.c_str());
- concatPasswordClient += std::string(keyInfo.client);
+ concatPasswordClient += std::string(wrappedOldDomainKEK.info.client);
- KeyData PKEK1;
- if (!PKCS5_PBKDF2_HMAC_SHA1(concatPasswordClient.c_str(),
- concatPasswordClient.size(),
- keyInfo.salt,
- MAX_SALT_SIZE,
- PBKDF2_ITERATIONS,
- PKEK1.size(),
- PKEK1.data())) {
- ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
- }
+ KeyData PKEK1 = PBKDF(concatPasswordClient, wrappedOldDomainKEK.info.salt, MAX_SALT_SIZE);
int keyLength;
- if (0 > (keyLength = decryptAes256Gcm(wrappedInfo.wrappedKey,
- keyInfo.keyLength,
- keyInfo.tag,
+ if (0 > (keyLength = decryptAes256Gcm(wrappedOldDomainKEK.key,
+ wrappedOldDomainKEK.info.keyLength,
+ wrappedOldDomainKEK.info.tag,
PKEK1.data(),
- keyInfo.iv,
- m_domainKEK->getDKEKAndInfo().key)))
+ wrappedOldDomainKEK.info.iv,
+ m_domainKEK->key)))
ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
- m_domainKEK->getDKEKAndInfo().keyInfo.set(keyInfo);
- m_domainKEK->setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::OpenSSL);
+ DomainKEKInfo info(wrappedOldDomainKEK.info);
+ info.version = KEYCOMPONENT_VERSION;
+ info.backend = static_cast<uint32_t>(CryptoBackend::OpenSSL);
#ifdef SE_BACKEND_ENABLED
- m_domainKEK->setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::SecureElement);
+ info.backend = static_cast<uint32_t>(CryptoBackend::SecureElement);
#endif
- m_domainKEK->setKeyInfoKeyLength(static_cast<unsigned int>(keyLength));
- m_isInitialized = true;
- LogDebug("Migrate DKEK Success");
-}
+ m_domainKEK->setKeyInfo(info);
-RawBuffer KeyProvider::reencrypt(
- const RawBuffer &domainKEKInWrapForm,
- const Password &oldPass,
- const Password &newPass)
-{
- if (domainKEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
- LogError("input size:" << domainKEKInWrapForm.size()
- << " Expected: " << sizeof(WrappedKeyAndInfo));
- ThrowErr(Exc::InternalError,
- "buffer doesn't have proper size to store "
- "WrappedKeyAndInfo in KeyProvider::reencrypt");
- }
-
- KeyAndInfoContainer domainKEK;
- unwrapDomainKEK(domainKEKInWrapForm, oldPass, domainKEK);
- return wrapDomainKEK(domainKEK, newPass);
+ m_domainKEK->info.keyLength = static_cast<uint32_t>(keyLength);
+ m_isInitialized = true;
+ LogDebug("Migrate DomainKEK Success");
}
-RawBuffer KeyProvider::generateDomainKEK(
- const std::string &user,
- const Password &userPassword)
+RawBuffer KeyProvider::generateDomainKEK(const std::string &user, const Password &userPassword)
{
- KeyAndInfoContainer domainKEK;
+ DomainKEKAndInfo domainKEK;
- if (!randomize(domainKEK.getDKEKAndInfo().keyInfo.salt) ||
- !randomize(domainKEK.getDKEKAndInfo().key) ||
- !randomize(domainKEK.getDKEKAndInfo().keyInfo.iv)) {
+ if (!randomize(domainKEK.info.salt) ||
+ !randomize(domainKEK.key) ||
+ !randomize(domainKEK.info.iv)) {
ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
}
- domainKEK.setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::OpenSSL);
+ domainKEK.info.version = KEYCOMPONENT_VERSION;
+ domainKEK.info.backend = static_cast<uint32_t>(CryptoBackend::OpenSSL);
#ifdef SE_BACKEND_ENABLED
- domainKEK.setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::SecureElement);
+ domainKEK.info.backend = static_cast<uint32_t>(CryptoBackend::SecureElement);
#endif
- domainKEK.setKeyInfoKeyLength(sizeof(domainKEK.getDKEKAndInfo().key));
- if (user.size() >= sizeof(domainKEK.getDKEKAndInfo().keyInfo.client)) {
- ThrowErr(Exc::InternalError, "Client name too long");
- }
- strncpy(domainKEK.getDKEKAndInfo().keyInfo.client, user.c_str(), user.size());
+ domainKEK.info.keyLength = sizeof(domainKEK.key);
+ domainKEK.setKeyInfoClient(user);
return wrapDomainKEK(domainKEK, userPassword);
}
-
-int KeyProvider::initializeLibrary()
-{
- LogDebug("initializeLibrary Success");
- return SUCCESS;
-}
-
-int KeyProvider::closeLibrary()
-{
- LogDebug("closeLibrary Success");
- return SUCCESS;
-}
-
-KeyProvider::~KeyProvider()
-{
- LogDebug("KeyProvider Destructor");
-}
#pragma once
-#include <string.h>
#include <stdint.h>
-#include <openssl/rand.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-#include <memory>
+#include <string.h>
-#include <ckm/ckm-type.h>
+#include <string>
-#ifndef SUCCESS
-#define SUCCESS 0
-#endif
-#ifndef ERROR
-#define ERROR -1
-#endif
-#ifndef INVALID_ARGUMENTS
-#define INVALID_ARGUMENTS -2
-#endif
-#ifndef VERIFY_DATA_ERROR
-#define VERIFY_DATA_ERROR -3
-#endif
-#ifndef OPENSSL_ENGINE_ERROR
-#define OPENSSL_ENGINE_ERROR -4
-#endif
-#ifndef UNKNOWN_ERROR
-#define UNKNOWN_ERROR -5
-#endif
-
-#define AES256_KEY_LEN_BITS 256
-#define AES256_KEY_LEN_BYTSE (AES256_KEY_LEN_BITS / 8)
-// Unused
-//#define AES_GCM_TAG_SIZE 32
-
-#define PBKDF2_SALT_LEN 16
-#define PBKDF2_ITERATIONS 4096
+#include <exception.h>
+#include <ckm/ckm-type.h>
+#include <dpl/log/log.h>
#define MAX_IV_SIZE 16
#define MAX_SALT_SIZE 16
#define MAX_KEY_SIZE 32
-#define MAX_WRAPPED_KEY_SIZE 32
#define MAX_CLIENT_ID_SIZE 32
-#define DOMAIN_NAME_SIZE 32
namespace CKM {
-const uint32_t KEYCOMPONENT_VERSION = 2;
-
-typedef struct KeyComponentsInfo_ {
+struct KeyInfo {
uint32_t keyLength;
char client[MAX_CLIENT_ID_SIZE];
uint8_t salt[MAX_SALT_SIZE];
uint8_t iv[MAX_IV_SIZE];
uint8_t tag[MAX_IV_SIZE];
-} KeyComponentsInfo;
-
-typedef struct KeyAndInfo_ {
- KeyComponentsInfo keyInfo;
- uint8_t key[MAX_KEY_SIZE];
-} KeyAndInfo;
-
-typedef struct WrappedKeyAndInfo_ {
- KeyComponentsInfo keyInfo;
- uint8_t wrappedKey[MAX_WRAPPED_KEY_SIZE];
-} WrappedKeyAndInfo;
+};
-typedef struct KeyComponentsInfoDKEK_ : KeyComponentsInfo{
+struct DomainKEKInfo : KeyInfo {
+ DomainKEKInfo() = default;
+ DomainKEKInfo(const KeyInfo& info) : KeyInfo(info) {}
uint32_t version;
uint32_t backend;
- void set(const KeyComponentsInfo &src) {
- keyLength = src.keyLength;
- memcpy(&client, &src.client, MAX_CLIENT_ID_SIZE);
- memcpy(&salt, &src.salt, MAX_SALT_SIZE);
- memcpy(&iv, &src.iv, MAX_IV_SIZE);
- memcpy(&tag, &src.tag, MAX_IV_SIZE);
+};
+
+template <typename T>
+struct KeyAndInfo final {
+ KeyAndInfo() {
+ memset(this, 0, sizeof(*this));
}
-} KeyComponentsInfoDKEK;
-typedef struct KeyAndInfoDKEK_ {
- KeyComponentsInfoDKEK keyInfo;
- uint8_t key[MAX_KEY_SIZE];
-} KeyAndInfoDKEK;
+ explicit KeyAndInfo(const RawBuffer& data) {
+ if (data.size() != sizeof(*this)) {
+ LogError("Data size: " << data.size() << " Expected: " << sizeof(*this));
+ ThrowErr(Exc::InternalError, "buffer doesn't have proper size to store ");
+ }
-typedef struct WrappedKeyAndInfoDKEK_ {
- KeyComponentsInfoDKEK keyInfo;
- uint8_t wrappedKey[MAX_WRAPPED_KEY_SIZE];
-} WrappedKeyAndInfoDKEK;
+ memcpy(this, data.data(), sizeof(*this));
-class WrappedKeyAndInfoContainer {
-public:
- WrappedKeyAndInfoContainer();
- WrappedKeyAndInfo &getWrappedKeyAndInfo();
- WrappedKeyAndInfoDKEK &getWrappedDKEKAndInfo();
- void setWrappedKeyAndInfo(const unsigned char *);
- void setWrappedDKEKAndInfo(const unsigned char *);
- void setKeyInfoKeyLength(const uint32_t);
- void setKeyInfoClient(const std::string);
- void setKeyInfoSalt(const unsigned char *, const int);
- void setKeyInfo(const KeyComponentsInfo *);
- void setDKEKInfo(const uint32_t, const uint32_t);
- ~WrappedKeyAndInfoContainer();
+ if (info.keyLength > sizeof(key)) {
+ ThrowErr(Exc::InternalError,
+ "Key info is corrupted. Key length exceeds the size of the key buffer.");
+ }
-private:
- WrappedKeyAndInfo wrappedKeyAndInfo;
- WrappedKeyAndInfoDKEK wrappedDKEKAndInfo;
-};
+ size_t maxlen = sizeof(info.client);
+ if (strnlen(info.client, maxlen) == maxlen) {
+ ThrowErr(Exc::InternalError,
+ "Key info is corrupted. Client id is not NULL terminated.");
+ }
+ }
-class KeyAndInfoContainer {
-public:
- KeyAndInfoContainer();
- KeyAndInfo &getKeyAndInfo();
- KeyAndInfoDKEK &getDKEKAndInfo();
- void setKeyAndInfo(const unsigned char *);
- void setDKEKAndInfo(const unsigned char *);
- void setKeyInfoKeyLength(const uint32_t);
- void setKeyInfo(const KeyComponentsInfo *);
- void setDKEKInfo(const uint32_t, const uint32_t);
- ~KeyAndInfoContainer();
+ void setKeyInfo(const T& info_) {
+ memcpy(&(info), &info_, sizeof(info));
+ }
-private:
- KeyAndInfo keyAndInfo;
- KeyAndInfoDKEK DKEKAndInfo;
+ void setKeyInfoClient(const std::string& resized_client) {
+ if (resized_client.size() >= sizeof(info.client)) {
+ ThrowErr(Exc::InternalError, "Client name too long");
+ }
+
+ strncpy(info.client, resized_client.c_str(), resized_client.size());
+ }
+
+ ~KeyAndInfo() {
+ // overwrite key
+ ZeroMemory(key, sizeof(key));
+ }
+
+ T info;
+ uint8_t key[MAX_KEY_SIZE];
};
+typedef KeyAndInfo<DomainKEKInfo> DomainKEKAndInfo;
+typedef KeyAndInfo<KeyInfo> DEKAndInfo; // it's also old DomainKEK form
+
// This is internal api so all functions should throw exception on errors.
class KeyProvider {
public:
- // To store in std containers
KeyProvider();
- // In constructor you must check if SKMM is initialized. On error -> exception
- // keyInWrapForm should be used like this:
- // if (keyInWrapForm.size() != sizeof(WrappedKeyAndInfo))
- // throw exception; // buffer does not have proper size to store WrappedKeyAndInfo
- // WrappedKeyAndInfo *wkm = static_cast<WrappedKeyAndInfo>(keyInWrapForm.data());
- KeyProvider(const RawBuffer &domainKEKInWrapForm, const Password &password);
+ KeyProvider(const RawBuffer &wrappedDomainKEKbuffer, const Password &password);
KeyProvider(KeyProvider &&);
KeyProvider(const KeyProvider &) = delete;
RawBuffer getPureDomainKEK();
// Returns Key in form used to store key in file
- // Requied by Control::resetPassword(const RawBuffer &newPassword);
- // This api should be used only on Tizen 2.2.1
RawBuffer getWrappedDomainKEK(const Password &password);
// Unwraps (decrypts) a DEK using a key derived from DomainKEK and data stored in wrapped key
// info. It returns the DEK in unencrypted form.
- RawBuffer getPureDEK(const RawBuffer &DEKInWrapForm);
+ RawBuffer getPureDEK(const RawBuffer &wrappedDEKbuffer);
// Generates a random DEK and encrypts it using a key derived from DomainKEK and custom client
// string (not to be confused with ClientId). The function returns the DEK in wrapped
// application keys.
RawBuffer generateDEK(const std::string &client);
- // used by change user password. On error -> exception
- static RawBuffer reencrypt(
- const RawBuffer &domainKEKInWrapForm,
- const Password &oldPass,
- const Password &newPass);
-
// First run of application for some user. DomainKEK was not created yet. We must create one.
// This key will be used to encrypt user database.
- static RawBuffer generateDomainKEK(const std::string &user,
- const Password &userPassword);
-
- void migrateDKEK(const RawBuffer &wrappedDomainKEKbuffer,
- const Password &password);
- RawBuffer migrateDBDEK(const RawBuffer &DEKInWrapForm);
-
- // This will be called by framework at the begin of the program
- static int initializeLibrary();
- // This will be called by framework at the end of the program
- static int closeLibrary();
+ static RawBuffer generateDomainKEK(const std::string &user, const Password &userPassword);
- virtual ~KeyProvider();
+ void migrateDomainKEK(const RawBuffer &wrappedDomainKEKbuffer, const Password &password);
private:
- // KeyAndInfoContainer class
- std::shared_ptr<KeyAndInfoContainer> m_domainKEK;
+ std::shared_ptr<DomainKEKAndInfo> m_domainKEK;
bool m_isInitialized;
};
NEGATIVE_TEST_CASE(KeyProvider_wrong_size)
{
RawBuffer wdkek = makeDefaultWrappedDomainKEK();
+ KeyProvider kp;
wdkek.push_back(0);
- BOOST_REQUIRE_THROW(KeyProvider(wdkek, PASSWORD), Exc::InternalError);
+ BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
+ BOOST_REQUIRE(!kp.isInitialized());
wdkek.pop_back();
wdkek.pop_back();
- BOOST_REQUIRE_THROW(KeyProvider(wdkek, PASSWORD), Exc::InternalError);
+ BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
+ BOOST_REQUIRE(!kp.isInitialized());
}
NEGATIVE_TEST_CASE(KeyProvider_garbage)
{
- BOOST_REQUIRE_THROW(KeyProvider(RawBuffer(sizeof(WrappedKeyAndInfo)), PASSWORD),
- Exc::AuthenticationFailed);
+ BOOST_REQUIRE_THROW(KeyProvider(RawBuffer(sizeof(DomainKEKAndInfo)), PASSWORD),
+ Exc::InternalError);
}
NEGATIVE_TEST_CASE(KeyDomainKek_invalid_password)
NEGATIVE_TEST_CASE(KeyGetPureDEK_uninitialized)
{
KeyProvider kp;
- RawBuffer wdek(sizeof(WrappedKeyAndInfo));
+ RawBuffer wdek(sizeof(DEKAndInfo));
BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
}
NEGATIVE_TEST_CASE(KeyGetPureDEK_garbage)
{
KeyProvider kp = makeDefaultKeyProvider();
- RawBuffer wdek(sizeof(WrappedKeyAndInfo));
+ RawBuffer wdek(sizeof(DEKAndInfo));
BOOST_REQUIRE_THROW(kp.getPureDEK(wdek), Exc::InternalError);
}
{
RawBuffer wdkek = makeDefaultWrappedDomainKEK();
RawBuffer wdkek2;
+ KeyProvider keyProvider;
- BOOST_REQUIRE_NO_THROW(wdkek2 = KeyProvider::reencrypt(wdkek, PASSWORD, NEW_PASSWORD));
+ BOOST_REQUIRE_NO_THROW(keyProvider = KeyProvider(wdkek, PASSWORD));
+ BOOST_REQUIRE_NO_THROW(wdkek2 = keyProvider.getWrappedDomainKEK(NEW_PASSWORD));
BOOST_REQUIRE(!wdkek2.empty());
}
-NEGATIVE_TEST_CASE(KeyReencrypt_incorrect_password)
-{
- RawBuffer wdkek = makeDefaultWrappedDomainKEK();
- BOOST_REQUIRE_THROW(KeyProvider::reencrypt(wdkek, INCORRECT_PASSWORD, NEW_PASSWORD),
- Exc::AuthenticationFailed);
-}
-
-NEGATIVE_TEST_CASE(KeyReencrypt_wrong_size)
-{
- RawBuffer wdkek = makeDefaultWrappedDomainKEK();
-
- wdkek.push_back(0);
- BOOST_REQUIRE_THROW(KeyProvider::reencrypt(wdkek, PASSWORD, NEW_PASSWORD), Exc::InternalError);
-
- wdkek.pop_back();
- wdkek.pop_back();
- BOOST_REQUIRE_THROW(KeyProvider::reencrypt(wdkek, PASSWORD, NEW_PASSWORD), Exc::InternalError);
-}
-
POSITIVE_TEST_CASE(KeyGetPureDEK_after_reencrypt)
{
KeyProvider kp;
RawBuffer wdek, dek, wdkek2;
RawBuffer wdkek = makeDefaultWrappedDomainKEK();
- BOOST_REQUIRE_NO_THROW(wdkek2 = KeyProvider::reencrypt(wdkek, PASSWORD, NEW_PASSWORD));
+ BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek, PASSWORD));
+ BOOST_REQUIRE_NO_THROW(wdkek2 = kp.getWrappedDomainKEK(NEW_PASSWORD));
BOOST_REQUIRE(!wdkek2.empty());
BOOST_REQUIRE_NO_THROW(kp = KeyProvider(wdkek2, NEW_PASSWORD));
BOOST_REQUIRE(dek.size() <= MAX_KEY_SIZE);
}
-POSITIVE_TEST_CASE(wrapped_container)
+POSITIVE_TEST_CASE(dek_and_info)
{
- WrappedKeyAndInfoContainer wkic;
+ DEKAndInfo dai;
auto salt = createRandom(20);
- BOOST_REQUIRE_NO_THROW(wkic.setKeyInfoSalt(salt.data(), salt.size()));
- BOOST_REQUIRE_NO_THROW(wkic.setKeyInfoClient("key_info_client"));
-
- WrappedKeyAndInfoContainer wkic2;
- BOOST_REQUIRE_NO_THROW(wkic2.setKeyInfo(&wkic.getWrappedKeyAndInfo().keyInfo));
-
- BOOST_REQUIRE(wkic.getWrappedKeyAndInfo().keyInfo.keyLength ==
- wkic2.getWrappedKeyAndInfo().keyInfo.keyLength);
- BOOST_REQUIRE(memcmp(wkic.getWrappedKeyAndInfo().keyInfo.salt,
- wkic2.getWrappedKeyAndInfo().keyInfo.salt,
- sizeof(wkic.getWrappedKeyAndInfo().keyInfo.salt)) == 0);
- BOOST_REQUIRE(memcmp(wkic.getWrappedKeyAndInfo().keyInfo.client,
- wkic2.getWrappedKeyAndInfo().keyInfo.client,
- sizeof(wkic.getWrappedKeyAndInfo().keyInfo.client)) == 0);
-
- WrappedKeyAndInfo wki;
- wki.keyInfo.keyLength = MAX_WRAPPED_KEY_SIZE;
- BOOST_REQUIRE_NO_THROW(wkic.setWrappedKeyAndInfo(reinterpret_cast<unsigned char*>(&wki)));
-}
+ memcpy(dai.info.salt, salt.data(), sizeof(dai.info.salt));
+ BOOST_REQUIRE_NO_THROW(dai.setKeyInfoClient("key_info_client"));
+ dai.info.keyLength = 10;
-NEGATIVE_TEST_CASE(wrapped_container)
-{
- WrappedKeyAndInfoContainer wkic;
+ DEKAndInfo dai2;
+ BOOST_REQUIRE_NO_THROW(dai2.setKeyInfo(dai.info));
- BOOST_REQUIRE_THROW(wkic.setKeyInfoClient("key_info_client_waaaaay_too_long"),
- Exc::InternalError);
-
- WrappedKeyAndInfo wki;
- wki.keyInfo.keyLength = MAX_WRAPPED_KEY_SIZE + 1;
- BOOST_REQUIRE_THROW(wkic.setWrappedKeyAndInfo(reinterpret_cast<unsigned char*>(&wki)),
- Exc::InternalError);
-
- // missing NULL termination in wki2.keyInfo.client
- WrappedKeyAndInfo wki2;
- memset(&wki2, 0x01, sizeof(WrappedKeyAndInfo));
- BOOST_REQUIRE_THROW(wkic.setWrappedKeyAndInfo(reinterpret_cast<unsigned char*>(&wki2)),
- Exc::InternalError);
+ BOOST_REQUIRE(dai.info.keyLength == dai2.info.keyLength);
+ BOOST_REQUIRE(memcmp(dai.info.salt, dai2.info.salt, sizeof(dai.info.salt)) == 0);
+ BOOST_REQUIRE(memcmp(dai.info.client, dai2.info.client, sizeof(dai.info.client)) == 0);
}
-POSITIVE_TEST_CASE(container)
+NEGATIVE_TEST_CASE(dek_and_info)
{
- KeyAndInfoContainer kic;
- BOOST_REQUIRE_NO_THROW(kic.setKeyInfoKeyLength(10));
+ DEKAndInfo dai;
+ BOOST_REQUIRE_THROW(dai.setKeyInfoClient("key_info_client_waaaaay_too_long"),
+ Exc::InternalError);
+
+ DEKAndInfo dai2;
+ dai2.info.keyLength = MAX_KEY_SIZE + 1;
- KeyAndInfoContainer kic2;
- BOOST_REQUIRE_NO_THROW(kic2.setKeyInfo(&kic.getKeyAndInfo().keyInfo));
+ const unsigned char *ptr = reinterpret_cast<const unsigned char *>(&dai2);
+ RawBuffer buffer(ptr, ptr + sizeof(dai2));
+ BOOST_REQUIRE_THROW(new DEKAndInfo((buffer)), Exc::InternalError);
- BOOST_REQUIRE(kic.getKeyAndInfo().keyInfo.keyLength == kic2.getKeyAndInfo().keyInfo.keyLength);
+ // missing NULL termination in dai3.info.client
+ RawBuffer garbage(0x01, sizeof(DEKAndInfo));
+ BOOST_REQUIRE_THROW(new DEKAndInfo((garbage)), Exc::InternalError);
}
POSITIVE_TEST_CASE(moves)