add the se-backend for db encryption 06/282606/1
author이이삭/System Security Lab(SR)/삼성전자 <isaac2.lee@samsung.com>
Wed, 5 Oct 2022 07:10:38 +0000 (16:10 +0900)
committerisaac2.lee <isaac2.lee@samsung.com>
Thu, 6 Oct 2022 07:58:31 +0000 (16:58 +0900)
* add the se-backend for db encryption
* change se-backend include dependancy and remove the unavailable codes
* remove migration DBDEK and rearrange KeyProvider structures

Change-Id: I52e07ac5af7b41d0f79b7fee818221f25b1d60cd

13 files changed:
CMakeLists.txt
packaging/key-manager.spec
src/CMakeLists.txt
src/manager/crypto/se-backend/internals.cpp [new file with mode: 0644]
src/manager/crypto/se-backend/internals.h [new file with mode: 0644]
src/manager/service/ckm-logic.cpp
src/manager/service/crypto-backend.h
src/manager/service/file-system.cpp
src/manager/service/key-provider.cpp
src/manager/service/key-provider.h
tests/CMakeLists.txt
tests/test_key-provider.cpp
tools/ckm_db_tool/CMakeLists.txt

index 20309dd..dd54573 100644 (file)
@@ -71,6 +71,10 @@ IF (TZ_BACKEND_ENABLED)
     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")
index 4040365..6272fa0 100644 (file)
@@ -2,6 +2,7 @@
 %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
@@ -42,6 +43,9 @@ BuildRequires: key-manager-ta-devel
 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}
@@ -182,6 +186,11 @@ export LDFLAGS+="-Wl,--rpath=%{_libdir},-Bsymbolic-functions"
 %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}
 
index 7369a67..e66bb78 100644 (file)
@@ -96,6 +96,14 @@ SET(KEY_MANAGER_SOURCES
     )
 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
diff --git a/src/manager/crypto/se-backend/internals.cpp b/src/manager/crypto/se-backend/internals.cpp
new file mode 100644 (file)
index 0000000..4dae68c
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ *  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
diff --git a/src/manager/crypto/se-backend/internals.h b/src/manager/crypto/se-backend/internals.h
new file mode 100644 (file)
index 0000000..b90bfba
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ *  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
index c26dc6a..ae5b316 100644 (file)
@@ -95,6 +95,11 @@ void CKMLogic::loadDKEKFile(uid_t user, const Password &password)
        }
 
        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)
index 2e1455e..5a5e28f 100644 (file)
@@ -25,7 +25,8 @@ namespace CKM {
 enum class CryptoBackend {
        None = 0,
        OpenSSL = 1,
-       TrustZone = 2
+       TrustZone = 2,
+       SecureElement = 3
 };
 
 } // namespace CKM
index e1ef844..4b18e10 100644 (file)
@@ -50,6 +50,7 @@ const std::string CKM_LEGACY_DB_PREFIX = "db-";
 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)
 {
@@ -125,8 +126,8 @@ RawBuffer FileSystem::getDBDEK() const
 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);
@@ -143,16 +144,21 @@ void FileSystem::saveFile(const std::string &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
index 6049acb..c35b775 100644 (file)
 
 #include <array>
 #include <memory>
-
+#include <crypto-backend.h>
+#ifdef SE_BACKEND_ENABLED
+#include <se-backend/internals.h>
+#endif
 using namespace CKM;
 
 namespace {
@@ -126,18 +129,33 @@ int decryptAes256Gcm(const unsigned char *ciphertext,
 }
 
 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())) {
@@ -166,41 +184,45 @@ void unwrapDomainKEK(const RawBuffer &wrappedDomainKEKbuffer,
                      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>
@@ -214,10 +236,21 @@ bool randomize(uint8_t (&array)[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));
 
@@ -233,14 +266,27 @@ WrappedKeyAndInfoContainer::WrappedKeyAndInfoContainer(const unsigned char
        }
 }
 
-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)
@@ -250,12 +296,14 @@ void WrappedKeyAndInfoContainer::setKeyInfoClient(const std::string resized_clie
        }
 
        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
@@ -263,6 +311,13 @@ 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()
@@ -272,32 +327,52 @@ 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() :
@@ -316,11 +391,12 @@ 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);
@@ -360,9 +436,9 @@ RawBuffer KeyProvider::getPureDomainKEK()
                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)
@@ -382,16 +458,17 @@ RawBuffer KeyProvider::getPureDEK(const RawBuffer &DEKInWrapForm)
        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;
@@ -431,11 +508,11 @@ RawBuffer KeyProvider::generateDEK(const std::string &client)
        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,
@@ -449,6 +526,58 @@ RawBuffer KeyProvider::generateDEK(const std::string &client)
        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,
@@ -471,22 +600,23 @@ RawBuffer KeyProvider::generateDomainKEK(
        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);
 }
index 713e952..dcc695e 100644 (file)
@@ -62,6 +62,8 @@
 
 namespace CKM {
 
+const uint32_t KEYCOMPONENT_VERSION = 2;
+
 typedef struct KeyComponentsInfo_ {
        uint32_t keyLength;
        char client[MAX_CLIENT_ID_SIZE];
@@ -80,32 +82,62 @@ typedef struct WrappedKeyAndInfo_ {
        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;
 };
 
 
@@ -157,6 +189,10 @@ public:
        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
index 27078e4..0ce18e6 100644 (file)
@@ -57,6 +57,14 @@ SET(GENERATOR_SOURCES
     ${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
@@ -163,6 +171,14 @@ SET(TEST_MERGED_SOURCES
     )
 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})
index ea369d1..b26e82c 100644 (file)
@@ -189,7 +189,8 @@ POSITIVE_TEST_CASE(wrapped_container)
 
        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)));
 }
 
@@ -203,14 +204,16 @@ NEGATIVE_TEST_CASE(wrapped_container)
        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);
 }
index e282e79..1b20ec4 100644 (file)
@@ -91,6 +91,14 @@ SET(CKM_DB_TOOLS_SOURCES
     )
 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)