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);
51 // not thread-safe because of static member
52 class KeyStoragePlugin {
54 explicit KeyStoragePlugin();
56 KeyStoragePlugin(KeyStoragePlugin&&) = default;
58 KeyStoragePlugin(const KeyStoragePlugin&) = delete;
59 KeyStoragePlugin& operator=(const KeyStoragePlugin&) = delete;
63 static KeyStoragePlugin& Instance();
65 BinaryData store(const BinaryData& key);
66 BinaryData load(const BinaryData& token);
67 void remove(const BinaryData& token);
71 KeyStoragePluginStoreFn storeFn;
72 KeyStoragePluginLoadFn loadFn;
73 KeyStoragePluginRemoveFn removeFn;
75 static std::unique_ptr<KeyStoragePlugin> plugin;
78 std::unique_ptr<KeyStoragePlugin> KeyStoragePlugin::plugin;
80 KeyStoragePlugin& KeyStoragePlugin::Instance()
83 plugin.reset(new KeyStoragePlugin());
88 KeyStoragePlugin::KeyStoragePlugin() : so(NULL)
90 std::string path = std::string(KEY_STORAGE_PLUGIN_DIR) + "/" + KEY_STORAGE_PLUGIN_LIB;
92 so = ::dlopen(path.c_str(), RTLD_LAZY);
94 throw runtime::Exception(std::string("Failed to load library: ") +
95 path + ". Error: " + ::dlerror());
97 storeFn = reinterpret_cast<KeyStoragePluginStoreFn>(::dlsym(so, "ode_ksp_store"));
99 throw runtime::Exception(
100 std::string("ode_ksp_store() symbol not found. Error: ") + ::dlerror());
102 loadFn = reinterpret_cast<KeyStoragePluginLoadFn>(::dlsym(so, "ode_ksp_load"));
104 throw runtime::Exception(
105 std::string("ode_ksp_load() symbol not found. Error: ") + ::dlerror());
107 removeFn = reinterpret_cast<KeyStoragePluginRemoveFn>(::dlsym(so, "ode_ksp_remove"));
108 if (removeFn == NULL)
109 throw runtime::Exception(
110 std::string("ode_ksp_remove() symbol not found. Error: ") + ::dlerror());
113 KeyStoragePlugin::~KeyStoragePlugin()
118 BinaryData KeyStoragePlugin::store(const BinaryData& key)
120 unsigned char* token = NULL;
121 size_t token_len = 0;
122 int ret = storeFn(key.data(), key.size(), &token, &token_len);
123 if (ret != ODE_KSP_ERROR_NONE)
124 throw runtime::Exception(std::string("Storing the key failed with ") +
125 std::to_string(ret));
127 BinaryData tokenVector(token, token + token_len);
132 BinaryData KeyStoragePlugin::load(const BinaryData& token)
134 unsigned char* key = NULL;
136 int ret = loadFn(token.data(), token.size(), &key, &key_len);
137 if (ret != ODE_KSP_ERROR_NONE)
138 throw runtime::Exception(std::string("Loading the key failed with ") +
139 std::to_string(ret));
141 BinaryData keyVector(key, key + key_len);
146 void KeyStoragePlugin::remove(const BinaryData& token)
148 int ret = removeFn(token.data(), token.size());
149 if (ret == ODE_KSP_ERROR_NO_SUCH_FILE) {
150 INFO(SINK, "Key storage plugin does not recognize the token. Ignoring.");
153 if (ret != ODE_KSP_ERROR_NONE)
154 throw runtime::Exception(std::string("Removing the key failed with ") +
155 std::to_string(ret));
158 std::string getTokenFileName(const std::string &device)
160 std::string filename(device);
161 std::replace(filename.begin(), filename.end(), '/', '_');
163 return std::string("/opt/etc/.ode_token") + filename;
166 void readToken(runtime::File &file, BinaryData& token)
170 if (!file.exists()) {
176 file.read(&tokenSize, sizeof(tokenSize));
177 token.resize(tokenSize);
178 file.read(token.data(), tokenSize);
183 void writeToken(runtime::File &file, const BinaryData& token)
185 size_t tokenSize(token.size());
189 file.write(&tokenSize, sizeof(tokenSize));
190 file.write(token.data(), token.size());
195 } // anonymous namespace
197 namespace UpgradeSupport {
199 void storeMasterKey(const std::string &device, const BinaryData& key)
201 std::lock_guard<std::mutex> lock(opGuard);
205 runtime::File file(getTokenFileName(device));
206 readToken(file, token);
208 auto& up = KeyStoragePlugin::Instance();
210 // remove previous entry if necessary
214 token = up.store(key);
216 writeToken(file, token);
219 BinaryData loadMasterKey(const std::string &device)
223 std::lock_guard<std::mutex> lock(opGuard);
225 runtime::File file(getTokenFileName(device));
226 readToken(file, token);
229 throw runtime::Exception("Token opening failed");
231 auto& up = KeyStoragePlugin::Instance();
232 return up.load(token);
235 void removeMasterKey(const std::string &device)
239 std::lock_guard<std::mutex> lock(opGuard);
241 runtime::File file(getTokenFileName(device));
242 readToken(file, token);
246 INFO(SINK, "Token for " + device + " does not exist. Ignoring.");
250 auto& up = KeyStoragePlugin::Instance();
256 } // namespace UpgradeSupport