ADD_DEFINITIONS("-DTZ_BACKEND_ENABLED")
ENDIF()
+IF (SE_BACKEND_ENABLED)
+ ADD_DEFINITIONS("-DSE_BACKEND_ENABLED")
+ENDIF()
+
IF (DEFINED WATCHDOG_ENABLED)
MESSAGE("WATCHDOG ENABELD!")
ADD_DEFINITIONS("-DWATCHDOG_ENABLED")
%global watchdog_timeout_sec 60
%global watchdog_notify_sec 20
%global tz_backend_enabled %{?tz_backend:%tz_backend}%{!?tz_backend:OFF}
+%global se_backend_enabled %{?se_backend:%se_backend}%{!?se_backend:OFF}
Name: key-manager
Summary: Central Key Manager and utilities
BuildRequires: key-manager-ta-serialization-devel
BuildRequires: pkgconfig(tef-libteec)
%endif
+%if %{se_backend_enabled} == ON
+BuildRequires: pkgconfig(key-manager-se-backend)
+%endif
Requires: libkey-manager-common = %{version}-%{release}
%{?systemd_requires}
%else
-DTZ_BACKEND_ENABLED=OFF \
%endif
+%if %{se_backend_enabled} == ON
+ -DSE_BACKEND_ENABLED=ON \
+%else
+ -DSE_BACKEND_ENABLED=OFF \
+%endif
-DTEST_DIR=%{test_dir} \
-DDUMP_LEGACY_DB_LIBNAME=%{dump_legacy_db_libname}
)
ENDIF()
+IF(SE_BACKEND_ENABLED)
+SET(KEY_MANAGER_SOURCES
+ ${KEY_MANAGER_SOURCES}
+ ${KEY_MANAGER_PATH}/crypto/se-backend/internals.cpp
+ )
+SET(KM_LINK_EXTRA_DEPS ${KM_LINK_EXTRA_DEPS} key-manager-se-backend)
+ENDIF()
+
SET_SOURCE_FILES_PROPERTIES(
${KEY_MANAGER_SOURCES}
PROPERTIES
--- /dev/null
+/*
+ * Copyright (c) 2017-2022 Samsung Electronics Co., Ltd. All rights reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file internals.cpp
+ * @author isaac2.lee (isaac2.lee@samsung.com)
+ * @version 1.0
+ */
+
+#include <functional>
+#include <unistd.h>
+#include <generic-backend/exception.h>
+#include <generic-backend/algo-validation.h>
+#include <generic-backend/crypto-params.h>
+#include <dpl/log/log.h>
+#include <ckm/ckm-type.h>
+
+#include <se-backend/internals.h>
+#include <key-manager-se-backend.h>
+#include <key-provider.h>
+
+#ifndef UNUSED_PARAMETER
+#define UNUSED_PARAMETER(x) (void)(x)
+#endif
+
+namespace CKM {
+namespace Crypto {
+namespace SE {
+namespace Internals {
+
+RawBuffer toRawBuffer(unsigned char* buf, uint32_t buf_len)
+{
+ RawBuffer output;
+ output.assign(buf, buf + buf_len);
+ return output;
+}
+
+kmsb_hash_algo_e getHashType(const CryptoAlgorithm &alg)
+{
+ HashAlgorithm hash = unpack<HashAlgorithm>(alg, ParamName::SV_HASH_ALGO);
+ switch (hash)
+ {
+ case HashAlgorithm::SHA1:
+ return KMSB_HASH_SHA1;
+ case HashAlgorithm::SHA256:
+ return KMSB_HASH_SHA256;
+ case HashAlgorithm::SHA384:
+ return KMSB_HASH_SHA384;
+ case HashAlgorithm::SHA512:
+ return KMSB_HASH_SHA512;
+ default:
+ break;
+ }
+ return KMSB_HASH_SHA256;
+}
+
+kmsb_ec_type_e getEcType(const ElipticCurve ecType)
+{
+ if (ecType == ElipticCurve::prime192v1)
+ return KMSB_EC_PRIME192V1;
+ else if (ecType == ElipticCurve::prime256v1)
+ return KMSB_EC_PRIME256V1;
+ else if (ecType == ElipticCurve::secp384r1)
+ return KMSB_EC_SECP384R1;
+ return KMSB_EC_PRIME256V1;
+}
+
+int kmsb_failure_retry(std::function<int()> func)
+{
+ int result = KMSB_ERROR_NONE;
+ for (size_t attempt = 0; attempt < 3; ++attempt) {
+ result = func();
+ if (result == KMSB_ERROR_NONE || result == KMSB_ERROR_NO_KEY)
+ break;
+ LogError("occured err inside SE(errcode:" << result << ")");
+ usleep(100000);
+ }
+ return result;
+}
+
+void generateSKey(const CryptoAlgorithm &alg,
+ const uint32_t key_idx)
+{
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(key_idx);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported");
+}
+
+void generateAKey(const CryptoAlgorithm &alg,
+ const uint32_t key_idx)
+{
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(key_idx);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported");
+}
+
+/// @brief encrypt key data using SE api for DB metadata
+/// @param key: target data for encryption
+/// @param key_len: target data length
+/// @param iv: iv data
+/// @param iv_len: iv data length
+/// @return Rawbuffer encrypted output
+RawBuffer encryptWithDbpKey(const unsigned char* key, const uint32_t key_len,
+ const unsigned char* iv, const uint32_t iv_len)
+{
+
+ unsigned char* output_data;
+ uint32_t output_len;
+
+ int ret = kmsb_failure_retry(std::bind(kmsb_encrypt_with_dbp_key,
+ SE_BACKEND_DBP_SCHEME_VERSION,
+ key, key_len,
+ iv, iv_len,
+ &output_data, &output_len));
+ if (ret == KMSB_ERROR_NO_KEY) {
+ ret = kmsb_failure_retry(std::bind(kmsb_generate_dbp_key,
+ false));
+ if (ret != KMSB_ERROR_NONE) {
+ LogError("Generate Key: SE Internal error: " << ret);
+ ThrowErr(Exc::Crypto::InternalError, "Generate Key: SE Internal error");
+ }
+ ret = kmsb_failure_retry(std::bind(kmsb_encrypt_with_dbp_key,
+ SE_BACKEND_DBP_SCHEME_VERSION,
+ key, key_len,
+ iv, iv_len,
+ &output_data, &output_len));
+ }
+ if (ret != KMSB_ERROR_NONE) {
+ LogError("Encrypt Key: SE Internal error: " << ret);
+ ThrowErr(Exc::Crypto::InternalError, "Encrypt key: SE Internal error");
+ }
+ return toRawBuffer(output_data, output_len);
+}
+
+RawBuffer halAES(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data,
+ const bool isEncrypt)
+{
+ UNUSED_PARAMETER(key_idx);
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(data);
+ UNUSED_PARAMETER(isEncrypt);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported AES yet");
+}
+
+RawBuffer symmetricEncrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data)
+{
+ return halAES(key_idx, alg, data, true);
+}
+
+RawBuffer symmetricDecrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data)
+{
+ return halAES(key_idx, alg, data, false);
+}
+
+RawBuffer asymmetricEncrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data)
+{
+ UNUSED_PARAMETER(key_idx);
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(data);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported RSA");
+}
+
+RawBuffer asymmetricDecrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data)
+{
+ UNUSED_PARAMETER(key_idx);
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(data);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported RSA");
+}
+
+RawBuffer sign(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &message)
+{
+ UNUSED_PARAMETER(key_idx);
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(message);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported signing yet");
+}
+
+int verify(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &hash,
+ RawBuffer &signature)
+{
+ UNUSED_PARAMETER(key_idx);
+ UNUSED_PARAMETER(alg);
+ UNUSED_PARAMETER(hash);
+ UNUSED_PARAMETER(signature);
+
+ ThrowErr(Exc::Crypto::OperationNotSupported, "SE Backend not supported verifying yet");
+}
+
+} // namespace Internals
+} // namespace SE
+} // namespace Crypto
+} // namespace CKM
--- /dev/null
+/*
+ * Copyright (c) 2017-2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+/*
+ * @file internals.h
+ * @author isaac2.lee (isaac2.lee@samsung.com)
+ * @version 1.0
+ */
+#pragma once
+
+#include <ckm/ckm-type.h>
+#include <data-type.h>
+#include <generic-backend/gstore.h>
+
+namespace CKM {
+namespace Crypto {
+namespace SE {
+namespace Internals {
+
+void generateSKey(const CryptoAlgorithm &alg, const uint32_t key_idx);
+
+void generateAKey(const CryptoAlgorithm &alg, const uint32_t key_idx);
+
+// encrypt key data using SE api
+RawBuffer encryptWithDbpKey(const unsigned char* key, const uint32_t key_len,
+ const unsigned char* iv, const uint32_t iv_len);
+
+RawBuffer symmetricEncrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data);
+RawBuffer symmetricDecrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data);
+
+RawBuffer asymmetricEncrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data);
+
+RawBuffer asymmetricDecrypt(const uint32_t key_idx,
+ const CryptoAlgorithm &alg,
+ RawBuffer &data);
+
+RawBuffer sign(const uint32_t key_idx, const CryptoAlgorithm &alg,
+ RawBuffer &message);
+
+int verify(const uint32_t key_idx, const CryptoAlgorithm &alg,
+ RawBuffer &hash, RawBuffer &signature);
+
+} // namespace Internals
+} // namespace SE
+} // namespace Crypto
+} // namespace CKM
}
handle.keyProvider = KeyProvider(wrappedDKEK, password);
+ if (!handle.keyProvider.isInitialized()) {
+ handle.keyProvider.migrateDKEK(wrappedDKEK, password);
+ fs.saveDKEK(handle.keyProvider.getWrappedDomainKEK(password));
+ LogInfo("DKEK migrated");
+ }
}
void CKMLogic::saveDKEKFile(uid_t user, const Password &password)
enum class CryptoBackend {
None = 0,
OpenSSL = 1,
- TrustZone = 2
+ TrustZone = 2,
+ SecureElement = 3
};
} // namespace CKM
const std::string CKM_DB_PREFIX = "db0-";
const std::string CKM_REMOVED_APP_PREFIX = "removed-app-";
const std::string CKM_LOCK_FILE = RUN_DIR "/" SERVICE_NAME "/key-manager.pid";
+const std::string CKM_TEMP_POSTFIX = ".tmp";
wur std::string getPath(const std::string &prefix, uid_t uid)
{
void FileSystem::saveFile(const std::string &path,
const RawBuffer &buffer) const
{
- std::ofstream os(path, std::ios::out | std::ofstream::binary |
- std::ofstream::trunc);
+ std::ofstream os(path + CKM_TEMP_POSTFIX, std::ios::out |
+ std::ofstream::binary | std::ofstream::trunc);
if (os.fail())
ThrowErr(Exc::FileSystemFailed, "Can't open file for writing: ", path);
if (os.fail())
ThrowErr(Exc::FileSystemFailed, "Failed to save file: ", path);
+
+ if (std::rename((path + CKM_TEMP_POSTFIX).c_str(), path.c_str()))
+ ThrowErr(Exc::FileSystemFailed, "Can't rename file: ", path);
}
void FileSystem::saveDKEK(const RawBuffer &buffer) const
{
- saveFile(getDKEKPath(), buffer);
+ std::string path(getDKEKPath());
+ saveFile(path, buffer);
}
void FileSystem::saveDBDEK(const RawBuffer &buffer) const
{
- saveFile(getDBDEKPath(), buffer);
+ std::string path(getDBDEKPath());
+ saveFile(path, buffer);
}
void FileSystem::addRemovedApp(const ClientId &app) const
#include <array>
#include <memory>
-
+#include <crypto-backend.h>
+#ifdef SE_BACKEND_ENABLED
+#include <se-backend/internals.h>
+#endif
using namespace CKM;
namespace {
}
typedef std::array<uint8_t, MAX_KEY_SIZE> KeyData;
-
// derives a key used for DomainKEK encryption (aka PKEK1) from random salt & user password
-KeyData makePKEK1(const KeyComponentsInfo& keyInfo, const Password &password)
+KeyData makePKEK1(const KeyComponentsInfoDKEK& keyInfo, const Password &password)
{
std::string concatPasswordClient(password.c_str());
concatPasswordClient += std::string(keyInfo.client);
-
KeyData key;
+ if (keyInfo.version != KEYCOMPONENT_VERSION)
+ ThrowErr(Exc::InternalError, "It's not expected version");
+
+#if SE_BACKEND_ENABLED
+ RawBuffer salt;
+ if (keyInfo.backend == (int)CryptoBackend::SecureElement) {
+ RawBuffer 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);
+ }
+#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(),
- keyInfo.salt,
- MAX_SALT_SIZE,
+ salt.data(),
+ salt.size(),
PBKDF2_ITERATIONS,
key.size(),
key.data())) {
const Password &password,
KeyAndInfoContainer &domainKEK)
{
- WrappedKeyAndInfoContainer wrappedDomainKEK(wrappedDomainKEKbuffer.data());
-
- KeyData PKEK1 = makePKEK1(wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo, password);
+ WrappedKeyAndInfoContainer wrappedDomainKEK;
+ wrappedDomainKEK.setWrappedDKEKAndInfo(wrappedDomainKEKbuffer.data());
+ KeyData PKEK1 = makePKEK1(wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo, password);
int keyLength;
- if (0 > (keyLength = decryptAes256Gcm(wrappedDomainKEK.getWrappedKeyAndInfo().wrappedKey,
- wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.keyLength,
- wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.tag,
+ if (0 > (keyLength = decryptAes256Gcm(wrappedDomainKEK.getWrappedDKEKAndInfo().wrappedKey,
+ wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.keyLength,
+ wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.tag,
PKEK1.data(),
- wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.iv,
- domainKEK.getKeyAndInfo().key)))
+ wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.iv,
+ domainKEK.getDKEKAndInfo().key)))
ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
- domainKEK.setKeyInfo(&(wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo));
+ domainKEK.setKeyInfo(&(wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo));
+ domainKEK.setDKEKInfo(wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.version,
+ wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.backend);
domainKEK.setKeyInfoKeyLength(static_cast<unsigned int>(keyLength));
}
RawBuffer wrapDomainKEK(KeyAndInfoContainer &domainKEK, const Password &password)
{
- KeyData PKEK1 = makePKEK1(domainKEK.getKeyAndInfo().keyInfo, password);
+ KeyData PKEK1 = makePKEK1(domainKEK.getDKEKAndInfo().keyInfo, password);
WrappedKeyAndInfoContainer wrappedDomainKEK = WrappedKeyAndInfoContainer();
- wrappedDomainKEK.setKeyInfo(&(domainKEK.getKeyAndInfo().keyInfo));
+ wrappedDomainKEK.setKeyInfo(&(domainKEK.getDKEKAndInfo().keyInfo));
+ wrappedDomainKEK.setDKEKInfo(domainKEK.getDKEKAndInfo().keyInfo.version,
+ domainKEK.getDKEKAndInfo().keyInfo.backend);
int wrappedLength;
- if (0 > (wrappedLength = encryptAes256Gcm(domainKEK.getKeyAndInfo().key,
- domainKEK.getKeyAndInfo().keyInfo.keyLength,
+ if (0 > (wrappedLength = encryptAes256Gcm(domainKEK.getDKEKAndInfo().key,
+ domainKEK.getDKEKAndInfo().keyInfo.keyLength,
PKEK1.data(),
- domainKEK.getKeyAndInfo().keyInfo.iv,
- wrappedDomainKEK.getWrappedKeyAndInfo().wrappedKey,
- wrappedDomainKEK.getWrappedKeyAndInfo().keyInfo.tag)))
+ domainKEK.getDKEKAndInfo().keyInfo.iv,
+ wrappedDomainKEK.getWrappedDKEKAndInfo().wrappedKey,
+ wrappedDomainKEK.getWrappedDKEKAndInfo().keyInfo.tag)))
ThrowErr(Exc::InternalError, "DomainKEK encryption failed");
wrappedDomainKEK.setKeyInfoKeyLength(static_cast<unsigned int>(wrappedLength));
- return toRawBuffer(wrappedDomainKEK.getWrappedKeyAndInfo());
+ return toRawBuffer(wrappedDomainKEK.getWrappedDKEKAndInfo());
}
template <size_t N>
WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer()
{
memset(&wrappedKeyAndInfo, 0, sizeof(WrappedKeyAndInfo));
+ memset(&wrappedDKEKAndInfo, 0, sizeof(WrappedKeyAndInfoDKEK));
}
-WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char
- *data)
+WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
+{
+ return wrappedKeyAndInfo;
+}
+
+WrappedKeyAndInfoDKEK &WrappedKeyAndInfoContainer::getWrappedDKEKAndInfo()
+{
+ return wrappedDKEKAndInfo;
+}
+
+void WrappedKeyAndInfoContainer::setWrappedKeyAndInfo(
+ const unsigned char *data)
{
memcpy(&wrappedKeyAndInfo, data, sizeof(WrappedKeyAndInfo));
}
}
-WrappedKeyAndInfo &WrappedKeyAndInfoContainer::getWrappedKeyAndInfo()
+void WrappedKeyAndInfoContainer::setWrappedDKEKAndInfo(
+ const unsigned char *data)
{
- return wrappedKeyAndInfo;
+ 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 unsigned int length)
+void WrappedKeyAndInfoContainer::setKeyInfoKeyLength(const uint32_t length)
{
wrappedKeyAndInfo.keyInfo.keyLength = length;
+ wrappedDKEKAndInfo.keyInfo.keyLength = length;
}
void WrappedKeyAndInfoContainer::setKeyInfoClient(const std::string resized_client)
}
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
{
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;
}
-KeyAndInfoContainer::KeyAndInfoContainer(const unsigned char *data)
+void KeyAndInfoContainer::setKeyAndInfo(const unsigned char *data)
{
memcpy(&keyAndInfo, data, sizeof(KeyAndInfo));
}
-KeyAndInfo &KeyAndInfoContainer::getKeyAndInfo()
+void KeyAndInfoContainer::setDKEKAndInfo(const unsigned char *data)
{
- return keyAndInfo;
+ memcpy(&DKEKAndInfo, data, sizeof(KeyAndInfoDKEK));
}
-void KeyAndInfoContainer::setKeyInfoKeyLength(unsigned int length)
+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() :
if (!m_isInitialized)
ThrowErr(Exc::InternalError, "Object not initialized!. Should not happened");
- 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 Constructor");
+ 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");
+ m_isInitialized = false;
+ return;
}
unwrapDomainKEK(domainKEKInWrapForm, password, *m_domainKEK);
ThrowErr(Exc::InternalError, "Object not initialized!");
// TODO secure
- return RawBuffer(m_domainKEK->getKeyAndInfo().key,
- (m_domainKEK->getKeyAndInfo().key) +
- m_domainKEK->getKeyAndInfo().keyInfo.keyLength);
+ return RawBuffer(m_domainKEK->getDKEKAndInfo().key,
+ (m_domainKEK->getDKEKAndInfo().key) +
+ m_domainKEK->getDKEKAndInfo().keyInfo.keyLength);
}
RawBuffer KeyProvider::getWrappedDomainKEK(const Password &password)
if (DEKInWrapForm.size() != sizeof(WrappedKeyAndInfo)) {
LogError("input size:" << DEKInWrapForm.size()
<< " Expected: " << sizeof(WrappedKeyAndInfo));
+
ThrowErr(Exc::InternalError,
"buffer doesn't have proper size to store "
"WrappedKeyAndInfo in KeyProvider::getPureDEK");
}
KeyAndInfoContainer kmcDEK = KeyAndInfoContainer();
- WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer(
- DEKInWrapForm.data());
+ WrappedKeyAndInfoContainer wkmcDEK = WrappedKeyAndInfoContainer();
+ wkmcDEK.setWrappedKeyAndInfo(DEKInWrapForm.data());
- KeyData PKEK2 = makePKEK2(m_domainKEK->getKeyAndInfo().key,
+ KeyData PKEK2 = makePKEK2(m_domainKEK->getDKEKAndInfo().key,
wkmcDEK.getWrappedKeyAndInfo().keyInfo.client);
int keyLength;
if (!randomize(key) || !randomize(wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv))
ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
- KeyData PKEK2 = makePKEK2(m_domainKEK->getKeyAndInfo().key, resized_client);
+ KeyData PKEK2 = makePKEK2(m_domainKEK->getDKEKAndInfo().key, resized_client);
int wrappedKeyLength;
if (0 > (wrappedKeyLength = encryptAes256Gcm(key,
- m_domainKEK->getKeyAndInfo().keyInfo.keyLength,
+ m_domainKEK->getDKEKAndInfo().keyInfo.keyLength,
PKEK2.data(),
wkmcDEK.getWrappedKeyAndInfo().keyInfo.iv,
wkmcDEK.getWrappedKeyAndInfo().wrappedKey,
return toRawBuffer(wkmcDEK.getWrappedKeyAndInfo());
}
+void KeyProvider::migrateDKEK(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.");
+ }
+
+ KeyComponentsInfo keyInfo = wrappedInfo.keyInfo;
+ std::string concatPasswordClient(password.c_str());
+ concatPasswordClient += std::string(keyInfo.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");
+ }
+
+ int keyLength;
+ if (0 > (keyLength = decryptAes256Gcm(wrappedInfo.wrappedKey,
+ keyInfo.keyLength,
+ keyInfo.tag,
+ PKEK1.data(),
+ keyInfo.iv,
+ m_domainKEK->getDKEKAndInfo().key)))
+ ThrowErr(Exc::AuthenticationFailed, "DomainKEK decryption failed");
+
+ m_domainKEK->getDKEKAndInfo().keyInfo.set(keyInfo);
+ m_domainKEK->setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::OpenSSL);
+#ifdef SE_BACKEND_ENABLED
+ m_domainKEK->setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::SecureElement);
+#endif
+ m_domainKEK->setKeyInfoKeyLength(static_cast<unsigned int>(keyLength));
+ m_isInitialized = true;
+ LogDebug("Migrate DKEK Success");
+}
+
RawBuffer KeyProvider::reencrypt(
const RawBuffer &domainKEKInWrapForm,
const Password &oldPass,
const std::string &user,
const Password &userPassword)
{
- WrappedKeyAndInfoContainer wkmcDKEK = WrappedKeyAndInfoContainer();
-
KeyAndInfoContainer domainKEK;
- if (!randomize(domainKEK.getKeyAndInfo().keyInfo.salt) ||
- !randomize(domainKEK.getKeyAndInfo().key) ||
- !randomize(domainKEK.getKeyAndInfo().keyInfo.iv)) {
+ if (!randomize(domainKEK.getDKEKAndInfo().keyInfo.salt) ||
+ !randomize(domainKEK.getDKEKAndInfo().key) ||
+ !randomize(domainKEK.getDKEKAndInfo().keyInfo.iv)) {
ThrowErr(Exc::InternalError, "OPENSSL_ENGINE_ERROR");
}
- domainKEK.setKeyInfoKeyLength(sizeof(domainKEK.getKeyAndInfo().key));
-
- if (user.size() >= sizeof(domainKEK.getKeyAndInfo().keyInfo.client)) {
+ domainKEK.setDKEKInfo(KEYCOMPONENT_VERSION, (uint32_t)CryptoBackend::OpenSSL);
+#ifdef SE_BACKEND_ENABLED
+ domainKEK.setDKEKInfo(KEYCOMPONENT_VERSION, (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.getKeyAndInfo().keyInfo.client, user.c_str(), user.size());
+ strncpy(domainKEK.getDKEKAndInfo().keyInfo.client, user.c_str(), user.size());
return wrapDomainKEK(domainKEK, userPassword);
}
namespace CKM {
+const uint32_t KEYCOMPONENT_VERSION = 2;
+
typedef struct KeyComponentsInfo_ {
uint32_t keyLength;
char client[MAX_CLIENT_ID_SIZE];
uint8_t wrappedKey[MAX_WRAPPED_KEY_SIZE];
} WrappedKeyAndInfo;
+typedef struct KeyComponentsInfoDKEK_ : KeyComponentsInfo{
+ 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);
+ }
+} KeyComponentsInfoDKEK;
+
+typedef struct KeyAndInfoDKEK_ {
+ KeyComponentsInfoDKEK keyInfo;
+ uint8_t key[MAX_KEY_SIZE];
+} KeyAndInfoDKEK;
+
+typedef struct WrappedKeyAndInfoDKEK_ {
+ KeyComponentsInfoDKEK keyInfo;
+ uint8_t wrappedKey[MAX_WRAPPED_KEY_SIZE];
+} WrappedKeyAndInfoDKEK;
+
class WrappedKeyAndInfoContainer {
public:
WrappedKeyAndInfoContainer();
- WrappedKeyAndInfoContainer(const unsigned char *);
WrappedKeyAndInfo &getWrappedKeyAndInfo();
- void setKeyInfoKeyLength(const unsigned int);
+ 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();
private:
WrappedKeyAndInfo wrappedKeyAndInfo;
+ WrappedKeyAndInfoDKEK wrappedDKEKAndInfo;
};
class KeyAndInfoContainer {
public:
KeyAndInfoContainer();
- explicit KeyAndInfoContainer(const unsigned char *);
KeyAndInfo &getKeyAndInfo();
- void setKeyInfoKeyLength(const unsigned int);
+ 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();
private:
KeyAndInfo keyAndInfo;
+ KeyAndInfoDKEK DKEKAndInfo;
};
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
${CMAKE_CURRENT_SOURCE_DIR}/encryption-scheme/generate-db.cpp
)
+IF(SE_BACKEND_ENABLED)
+SET(ENCRYPTION_SCHEME_SOURCES
+ ${ENCRYPTION_SCHEME_SOURCES}
+ ${KEY_MANAGER_PATH}/crypto/se-backend/internals.cpp
+ )
+SET(ENCRYPTION_SCHEME_DEP_LIBRARIES ${TEST_LINK_EXTRA_DEPS} key-manager-se-backend)
+ENDIF()
+
ADD_EXECUTABLE(${TARGET_CKM_GENERATOR} ${GENERATOR_SOURCES} ${ENCRYPTION_SCHEME_SOURCES})
SET(SCHEME_TEST_LIBRARIES
)
ENDIF()
+IF(SE_BACKEND_ENABLED)
+SET(TEST_MERGED_SOURCES
+ ${TEST_MERGED_SOURCES}
+ ${KEY_MANAGER_PATH}/crypto/se-backend/internals.cpp
+ )
+SET(TEST_LINK_EXTRA_DEPS ${TEST_LINK_EXTRA_DEPS} key-manager-se-backend)
+ENDIF()
+
LINK_DIRECTORIES(${KEY_MANAGER_DEP_LIBRARY_DIRS})
ADD_EXECUTABLE(${TARGET_TEST_MERGED} ${TEST_MERGED_SOURCES} ${ENCRYPTION_SCHEME_SOURCES})
CKM::WrappedKeyAndInfo wrapped3;
wrapped3.keyInfo.keyLength = MAX_WRAPPED_KEY_SIZE;
- BOOST_REQUIRE_NO_THROW(CKM::WrappedKeyAndInfoContainer wrappedContainer3(
+ CKM::WrappedKeyAndInfoContainer wrappedContainer3;
+ BOOST_REQUIRE_NO_THROW(wrappedContainer3.setWrappedKeyAndInfo(
reinterpret_cast<unsigned char*>(&wrapped3)));
}
CKM::WrappedKeyAndInfo wrapped3;
wrapped3.keyInfo.keyLength = MAX_WRAPPED_KEY_SIZE + 1;
- BOOST_REQUIRE_THROW(CKM::WrappedKeyAndInfoContainer wrappedContainer3(
+ CKM::WrappedKeyAndInfoContainer wrappedContainer3;
+ BOOST_REQUIRE_THROW(wrappedContainer3.setWrappedKeyAndInfo(
reinterpret_cast<unsigned char*>(&wrapped3)),
CKM::Exc::InternalError);
// missing NULL termination in wrapped4.keyInfo.client
CKM::WrappedKeyAndInfo wrapped4;
memset(&wrapped4, 0x01, sizeof(CKM::WrappedKeyAndInfo));
- BOOST_REQUIRE_THROW(CKM::WrappedKeyAndInfoContainer wrappedContainer3(
+ CKM::WrappedKeyAndInfoContainer wrappedContainer4;
+ BOOST_REQUIRE_THROW(wrappedContainer4.setWrappedKeyAndInfo(
reinterpret_cast<unsigned char*>(&wrapped4)),
CKM::Exc::InternalError);
}
)
ENDIF()
+IF(SE_BACKEND_ENABLED)
+SET(CKM_DB_TOOLS_SOURCES
+ ${CKM_DB_TOOLS_SOURCES}
+ ${KEY_MANAGER_PATH}/crypto/se-backend/internals.cpp
+ )
+SET(CKM_DB_TOOL_LINK_EXTRA_DEPS ${CKM_DB_TOOL_LINK_EXTRA_DEPS} key-manager-se-backend)
+ENDIF()
+
LINK_DIRECTORIES(${CKM_DB_TOOL_DEP_LIBRARY_DIRS})
ADD_EXECUTABLE(${CKM_DB_TOOL} ${CKM_DB_TOOLS_SOURCES} ${PROJECT_SOURCE_DIR}/tools/ckm_db_tool/ckm_db_tool.cpp)