Add framework for master key storage 05/159505/23
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 9 Nov 2017 09:13:23 +0000 (10:13 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Tue, 28 Nov 2017 12:31:24 +0000 (13:31 +0100)
- Add wrapper for dlopen + dlsym + dlclose.
- Add functions for master key management

Change-Id: I6d988320e90e21aad9066899d3bd8ea14b41034c

CMakeLists.txt
packaging/ode.spec
server/CMakeLists.txt
server/upgrade-support.cpp [new file with mode: 0644]
server/upgrade-support.h [new file with mode: 0644]

index 229f1e6..51f5eb5 100755 (executable)
@@ -86,6 +86,15 @@ IF(NOT DEFINED SYSTEMD_UNIT_DIR)
        SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system")
 ENDIF(NOT DEFINED SYSTEMD_UNIT_DIR)
 
+IF(NOT DEFINED KEY_STORAGE_PLUGIN_DIR)
+       SET(KEY_STORAGE_PLUGIN_DIR "${CMAKE_INSTALL_LIBDIR}/ode-key-storage-plugin")
+ENDIF(NOT DEFINED KEY_STORAGE_PLUGIN_DIR)
+
+SET(KEY_STORAGE_PLUGIN "key-storage-plugin")
+
+ADD_DEFINITIONS(-DKEY_STORAGE_PLUGIN_DIR="${KEY_STORAGE_PLUGIN_DIR}")
+ADD_DEFINITIONS(-DKEY_STORAGE_PLUGIN_LIB="${CMAKE_SHARED_LIBRARY_PREFIX}${KEY_STORAGE_PLUGIN}${CMAKE_SHARED_LIBRARY_SUFFIX}")
+
 ADD_DEFINITIONS(-DUG_WAYLAND)
 
 ADD_SUBDIRECTORY(${ODE_LIB})
index 75340c0..9ddb80b 100755 (executable)
@@ -22,6 +22,8 @@ BuildRequires: pkgconfig(openssl)
 BuildRequires: pkgconfig(libsmack)
 Requires: cryptsetup
 
+%global key_storage_plugin_dir %{_libdir}/ode-key-storage-plugin/
+
 %description
 The ode package provides a daemon which is responsible for encrypting/decryption storages and secure erasing.
 
@@ -33,6 +35,7 @@ The ode package provides a daemon which is responsible for encrypting/decryption
 %{_unitdir}/multi-user.target.wants/ode.service
 %attr(700,root,root) %{_sbindir}/ode-admin-cli
 %{_datadir}/%{name}
+%dir %{key_storage_plugin_dir}
 
 %prep
 %setup -q
@@ -51,7 +54,8 @@ The ode package provides a daemon which is responsible for encrypting/decryption
          -DBIN_DIR=%{TZ_SYS_BIN} \
          -DSYSTEMD_UNIT_DIR=%{_unitdir} \
          -DAPP_INSTALL_PREFIX="%{TZ_SYS_RO_APP}" \
-         -DAPP_SHARE_PACKAGES_DIR="%{TZ_SYS_RO_PACKAGES}"
+         -DAPP_SHARE_PACKAGES_DIR="%{TZ_SYS_RO_PACKAGES}" \
+         -DKEY_STORAGE_PLUGIN_DIR="%{key_storage_plugin_dir}"
 
 make %{?jobs:-j%jobs}
 
index c51f696..2c115c9 100644 (file)
@@ -37,6 +37,7 @@ SET(SERVER_SRCS       main.cpp
                                key-manager/key-generator.cpp
                                key-manager/anti-forensics.cpp
                                key-manager/encrypted-key.cpp
+                               upgrade-support.cpp
 )
 
 SET(DEPENDENCY klay
@@ -60,7 +61,7 @@ PKG_CHECK_MODULES(SERVER_DEPS REQUIRED ${DEPENDENCY})
 
 INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${ODE_SERVER} ${PROJECT_SOURCE_DIR})
 
-TARGET_LINK_LIBRARIES(${SERVER_NAME} ${SERVER_DEPS_LIBRARIES} ${LFS_LDFLAGS} ${LFS_LIBS} pthread)
+TARGET_LINK_LIBRARIES(${SERVER_NAME} ${SERVER_DEPS_LIBRARIES} ${LFS_LDFLAGS} ${LFS_LIBS} pthread dl)
 
 SET_TARGET_PROPERTIES(${SERVER_NAME} PROPERTIES COMPILE_FLAGS "-fPIE")
 SET_TARGET_PROPERTIES(${SERVER_NAME} PROPERTIES LINK_FLAGS "-pie")
@@ -76,3 +77,4 @@ CONFIGURE_FILE(systemd/${PROJECT_NAME}.service.in systemd/${PROJECT_NAME}.servic
 INSTALL(TARGETS ${SERVER_NAME} DESTINATION ${BIN_DIR})
 INSTALL(FILES systemd/${PROJECT_NAME}.service DESTINATION ${SYSTEMD_UNIT_DIR})
 INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/engine/encryption/dummy_password DESTINATION ${PROJECT_DATA_DIR})
+INSTALL(DIRECTORY DESTINATION ${KEY_STORAGE_PLUGIN_DIR})
\ No newline at end of file
diff --git a/server/upgrade-support.cpp b/server/upgrade-support.cpp
new file mode 100644 (file)
index 0000000..0676337
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+#include "upgrade-support.h"
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+
+#include <string>
+#include <algorithm>
+#include <vector>
+#include <memory>
+#include <mutex>
+
+#include <klay/filesystem.h>
+#include <klay/exception.h>
+
+namespace ode {
+
+namespace {
+
+extern "C" {
+typedef int(*KeyStoragePluginStoreFn)(const unsigned char*, size_t,
+                                                                         unsigned char**, size_t*);
+typedef int(*KeyStoragePluginLoadFn)(const unsigned char*, size_t,
+                                                                        unsigned char**, size_t*);
+typedef int(*KeyStoragePluginRemoveFn)(const unsigned char*, size_t);
+}
+
+std::mutex opGuard;
+
+// not thread-safe because of static member
+class KeyStoragePlugin {
+public:
+       explicit KeyStoragePlugin();
+
+       KeyStoragePlugin(KeyStoragePlugin&&) = default;
+
+       KeyStoragePlugin(const KeyStoragePlugin&) = delete;
+       KeyStoragePlugin& operator=(const KeyStoragePlugin&) = delete;
+
+       ~KeyStoragePlugin();
+
+       static KeyStoragePlugin& Instance();
+
+       typedef std::vector<unsigned char> Data;
+
+       Data store(const Data& key);
+       Data load(const Data& token);
+       void remove(const Data& token);
+
+private:
+       void* so;
+       KeyStoragePluginStoreFn storeFn;
+       KeyStoragePluginLoadFn loadFn;
+       KeyStoragePluginRemoveFn removeFn;
+
+       static std::unique_ptr<KeyStoragePlugin> plugin;
+};
+
+std::unique_ptr<KeyStoragePlugin> KeyStoragePlugin::plugin;
+
+KeyStoragePlugin& KeyStoragePlugin::Instance()
+{
+       if (!plugin)
+               plugin.reset(new KeyStoragePlugin());
+
+       return *plugin;
+}
+
+KeyStoragePlugin::KeyStoragePlugin() : so(NULL)
+{
+       std::string path = std::string(KEY_STORAGE_PLUGIN_DIR) + "/" + KEY_STORAGE_PLUGIN_LIB;
+
+       so = ::dlopen(path.c_str(), RTLD_LAZY);
+       if (so == NULL)
+               throw runtime::Exception(std::string("Failed to load library: ") +
+                                                                path + ". Error: " + ::dlerror());
+
+       storeFn = reinterpret_cast<KeyStoragePluginStoreFn>(::dlsym(so, "ode_ksp_store"));
+       if (storeFn == NULL)
+               throw runtime::Exception(
+                       std::string("ode_ksp_store() symbol not found. Error: ") + ::dlerror());
+
+       loadFn = reinterpret_cast<KeyStoragePluginLoadFn>(::dlsym(so, "ode_ksp_load"));
+       if (loadFn == NULL)
+               throw runtime::Exception(
+                       std::string("ode_ksp_load() symbol not found. Error: ") + ::dlerror());
+
+       removeFn = reinterpret_cast<KeyStoragePluginRemoveFn>(::dlsym(so, "ode_ksp_remove"));
+       if (removeFn == NULL)
+               throw runtime::Exception(
+                       std::string("ode_ksp_remove() symbol not found. Error: ") + ::dlerror());
+}
+
+KeyStoragePlugin::~KeyStoragePlugin()
+{
+       ::dlclose(so);
+}
+
+KeyStoragePlugin::Data KeyStoragePlugin::store(const KeyStoragePlugin::Data& key)
+{
+       unsigned char* token = NULL;
+       size_t token_len = 0;
+       int ret = storeFn(key.data(), key.size(), &token, &token_len);
+       if (ret != 0)
+               throw runtime::Exception(std::string("Storing the key failed with ") +
+                                                                std::to_string(ret));
+
+       Data tokenVector(token, token + token_len);
+       free(token);
+       return tokenVector;
+}
+
+KeyStoragePlugin::Data KeyStoragePlugin::load(const KeyStoragePlugin::Data& token)
+{
+       unsigned char* key = NULL;
+       size_t key_len = 0;
+       int ret = loadFn(token.data(), token.size(), &key, &key_len);
+       if (ret != 0)
+               throw runtime::Exception(std::string("Loading the key failed with ") +
+                                                                std::to_string(ret));
+
+       Data keyVector(key, key + key_len);
+       free(key);
+       return keyVector;
+}
+
+void KeyStoragePlugin::remove(const KeyStoragePlugin::Data& token)
+{
+       int ret = removeFn(token.data(), token.size());
+       if (ret != 0)
+               throw runtime::Exception(std::string("Removing the key failed with ") +
+                                                                std::to_string(ret));
+}
+
+std::string getTokenFileName(const std::string &device)
+{
+       std::string filename(device);
+       std::replace(filename.begin(), filename.end(), '/', '_');
+
+       return std::string("/opt/etc/.ode_token") + filename;
+}
+
+void readToken(runtime::File &file, KeyStoragePlugin::Data& token)
+{
+       size_t tokenSize;
+
+       file.open(O_RDONLY);
+
+       file.read(&tokenSize, sizeof(tokenSize));
+       token.resize(tokenSize);
+       file.read(token.data(), tokenSize);
+
+       file.close();
+}
+
+void writeToken(runtime::File &file, const KeyStoragePlugin::Data& token)
+{
+       size_t tokenSize(token.size());
+
+       file.create(0600);
+
+       file.write(&tokenSize, sizeof(tokenSize));
+       file.write(token.data(), token.size());
+
+       file.close();
+}
+
+} // anonymous namespace
+
+namespace UpgradeSupport {
+
+void storeMasterKey(const std::string &device, const KeyStoragePlugin::Data& key)
+{
+       std::lock_guard<std::mutex> lock(opGuard);
+
+       auto& up = KeyStoragePlugin::Instance();
+       auto token = up.store(key);
+
+       runtime::File file(getTokenFileName(device));
+
+       writeToken(file, token);
+}
+
+KeyStoragePlugin::Data loadMasterKey(const std::string &device)
+{
+       KeyStoragePlugin::Data token;
+
+       std::lock_guard<std::mutex> lock(opGuard);
+
+       runtime::File file(getTokenFileName(device));
+       readToken(file, token);
+
+       auto& up = KeyStoragePlugin::Instance();
+       return up.load(token);
+}
+
+void removeMasterKey(const std::string &device)
+{
+       KeyStoragePlugin::Data token;
+
+       std::lock_guard<std::mutex> lock(opGuard);
+
+       runtime::File file(getTokenFileName(device));
+       readToken(file, token);
+
+       auto& up = KeyStoragePlugin::Instance();
+       up.remove(token);
+
+       file.remove();
+}
+
+} // namespace UpgradeSupport
+
+} // namespace ode
diff --git a/server/upgrade-support.h b/server/upgrade-support.h
new file mode 100644 (file)
index 0000000..509576f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (c) 2017 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
+ */
+
+#ifndef __ODE_UPGRADE_SUPPORT_H__
+#define __ODE_UPGRADE_SUPPORT_H__
+
+#include <string>
+
+#include <rmi/key.h>
+
+namespace ode {
+
+namespace UpgradeSupport {
+
+void storeMasterKey(const std::string &device, const Key::KeyData& key);
+Key::KeyData loadMasterKey(const std::string &device);
+void removeMasterKey(const std::string &device);
+
+} // namespace UpgradeSupport
+
+} // namespace ode
+
+#endif // __ODE_UPGRADE_SUPPORT_H__