2 * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
17 #include "upgrade-support.h"
19 #include <sys/types.h>
29 #include <klay/filesystem.h>
30 #include <klay/exception.h>
32 #include <rmi/common.h>
35 #include <ode-key-storage-plugin/ode-key-storage-plugin.h>
42 typedef int(*KeyStoragePluginStoreFn)(const unsigned char*, size_t,
43 unsigned char**, size_t*);
44 typedef int(*KeyStoragePluginLoadFn)(const unsigned char*, size_t,
45 unsigned char**, size_t*);
46 typedef int(*KeyStoragePluginRemoveFn)(const unsigned char*, size_t);
49 const std::string UPGRADE_FLAG_PATH = "/opt/etc/.ode_upgrade_started";
53 // not thread-safe because of static member
54 class KeyStoragePlugin {
56 explicit KeyStoragePlugin();
58 KeyStoragePlugin(KeyStoragePlugin&&) = default;
60 KeyStoragePlugin(const KeyStoragePlugin&) = delete;
61 KeyStoragePlugin& operator=(const KeyStoragePlugin&) = delete;
65 static KeyStoragePlugin& Instance();
67 BinaryData store(const BinaryData& key);
68 BinaryData load(const BinaryData& token);
69 void remove(const BinaryData& token);
73 KeyStoragePluginStoreFn storeFn;
74 KeyStoragePluginLoadFn loadFn;
75 KeyStoragePluginRemoveFn removeFn;
77 static std::unique_ptr<KeyStoragePlugin> plugin;
80 std::unique_ptr<KeyStoragePlugin> KeyStoragePlugin::plugin;
82 KeyStoragePlugin& KeyStoragePlugin::Instance()
85 plugin.reset(new KeyStoragePlugin());
90 KeyStoragePlugin::KeyStoragePlugin() : so(NULL)
92 std::string path = std::string(KEY_STORAGE_PLUGIN_DIR) + "/" + KEY_STORAGE_PLUGIN_LIB;
94 so = ::dlopen(path.c_str(), RTLD_LAZY);
96 throw runtime::Exception(std::string("Failed to load library: ") +
97 path + ". Error: " + ::dlerror());
99 storeFn = reinterpret_cast<KeyStoragePluginStoreFn>(::dlsym(so, "ode_ksp_store"));
101 throw runtime::Exception(
102 std::string("ode_ksp_store() symbol not found. Error: ") + ::dlerror());
104 loadFn = reinterpret_cast<KeyStoragePluginLoadFn>(::dlsym(so, "ode_ksp_load"));
106 throw runtime::Exception(
107 std::string("ode_ksp_load() symbol not found. Error: ") + ::dlerror());
109 removeFn = reinterpret_cast<KeyStoragePluginRemoveFn>(::dlsym(so, "ode_ksp_remove"));
110 if (removeFn == NULL)
111 throw runtime::Exception(
112 std::string("ode_ksp_remove() symbol not found. Error: ") + ::dlerror());
115 KeyStoragePlugin::~KeyStoragePlugin()
120 BinaryData KeyStoragePlugin::store(const BinaryData& key)
122 unsigned char* token = NULL;
123 size_t token_len = 0;
124 int ret = storeFn(key.data(), key.size(), &token, &token_len);
125 if (ret != ODE_KSP_ERROR_NONE)
126 throw runtime::Exception(std::string("Storing the key failed with ") +
127 std::to_string(ret));
129 BinaryData tokenVector(token, token + token_len);
134 BinaryData KeyStoragePlugin::load(const BinaryData& token)
136 unsigned char* key = NULL;
138 int ret = loadFn(token.data(), token.size(), &key, &key_len);
139 if (ret != ODE_KSP_ERROR_NONE)
140 throw runtime::Exception(std::string("Loading the key failed with ") +
141 std::to_string(ret));
143 BinaryData keyVector(key, key + key_len);
148 void KeyStoragePlugin::remove(const BinaryData& token)
150 int ret = removeFn(token.data(), token.size());
151 if (ret == ODE_KSP_ERROR_NO_SUCH_FILE) {
152 INFO(SINK, "Key storage plugin does not recognize the token. Ignoring.");
155 if (ret != ODE_KSP_ERROR_NONE)
156 throw runtime::Exception(std::string("Removing the key failed with ") +
157 std::to_string(ret));
160 std::string getTokenFileName(const std::string &device)
162 std::string filename(device);
163 std::replace(filename.begin(), filename.end(), '/', '_');
165 return std::string("/opt/etc/.ode_token") + filename;
168 void readToken(runtime::File &file, BinaryData& token)
172 if (!file.exists()) {
178 file.read(&tokenSize, sizeof(tokenSize));
179 token.resize(tokenSize);
180 file.read(token.data(), tokenSize);
185 void writeToken(runtime::File &file, const BinaryData& token)
187 size_t tokenSize(token.size());
191 file.write(&tokenSize, sizeof(tokenSize));
192 file.write(token.data(), token.size());
197 } // anonymous namespace
199 namespace UpgradeSupport {
201 void storeMasterKey(const std::string &device, const BinaryData& key)
203 std::lock_guard<std::mutex> lock(opGuard);
207 runtime::File file(getTokenFileName(device));
208 readToken(file, token);
210 auto& up = KeyStoragePlugin::Instance();
212 // remove previous entry if necessary
216 token = up.store(key);
218 writeToken(file, token);
221 BinaryData loadMasterKey(const std::string &device)
225 std::lock_guard<std::mutex> lock(opGuard);
227 runtime::File file(getTokenFileName(device));
228 readToken(file, token);
230 auto& up = KeyStoragePlugin::Instance();
231 return up.load(token);
234 void removeMasterKey(const std::string &device)
238 std::lock_guard<std::mutex> lock(opGuard);
240 runtime::File file(getTokenFileName(device));
241 readToken(file, token);
243 auto& up = KeyStoragePlugin::Instance();
248 } catch (runtime::Exception &e) {
249 ERROR(SINK, "Failed to remove token: " + std::string(e.what()));
253 void createUpgradeFlag()
255 runtime::File file(UPGRADE_FLAG_PATH);
256 file.create(S_IRUSR | S_IWUSR); // 0600
259 void removeUpgradeFlag()
261 runtime::File file(UPGRADE_FLAG_PATH);
262 bool exists = file.exists();
267 bool checkUpgradeFlag()
269 runtime::File file(UPGRADE_FLAG_PATH);
270 return file.exists();
273 } // namespace UpgradeSupport