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>
30 #include <klay/filesystem.h>
31 #include <klay/exception.h>
32 #include <klay/auth/group.h>
34 #include <rmi/common.h>
37 #include <ode-key-storage-plugin/ode-key-storage-plugin.h>
44 typedef int(*KeyStoragePluginStoreFn)(const unsigned char*, size_t,
45 unsigned char**, size_t*);
46 typedef int(*KeyStoragePluginLoadFn)(const unsigned char*, size_t,
47 unsigned char**, size_t*);
48 typedef int(*KeyStoragePluginRemoveFn)(const unsigned char*, size_t);
51 const std::string UPGRADE_FLAG_PATH = "/opt/etc/.ode_upgrade_started";
55 gid_t getSystemShareGid()
57 static runtime::Group systemShare("system_share");
59 return systemShare.getGid();
62 // not thread-safe because of static member
63 class KeyStoragePlugin {
65 explicit KeyStoragePlugin();
67 KeyStoragePlugin(KeyStoragePlugin&&) = default;
69 KeyStoragePlugin(const KeyStoragePlugin&) = delete;
70 KeyStoragePlugin& operator=(const KeyStoragePlugin&) = delete;
74 static KeyStoragePlugin& Instance();
76 BinaryData store(const BinaryData& key);
77 BinaryData load(const BinaryData& token);
78 void remove(const BinaryData& token);
82 KeyStoragePluginStoreFn storeFn;
83 KeyStoragePluginLoadFn loadFn;
84 KeyStoragePluginRemoveFn removeFn;
86 static std::unique_ptr<KeyStoragePlugin> plugin;
89 std::unique_ptr<KeyStoragePlugin> KeyStoragePlugin::plugin;
91 KeyStoragePlugin& KeyStoragePlugin::Instance()
94 plugin.reset(new KeyStoragePlugin());
99 KeyStoragePlugin::KeyStoragePlugin() : so(NULL)
101 std::string path = std::string(KEY_STORAGE_PLUGIN_DIR) + "/" + KEY_STORAGE_PLUGIN_LIB;
103 so = ::dlopen(path.c_str(), RTLD_LAZY);
105 throw runtime::Exception(std::string("Failed to load library: ") +
106 path + ". Error: " + ::dlerror());
108 storeFn = reinterpret_cast<KeyStoragePluginStoreFn>(::dlsym(so, "ode_ksp_store"));
110 throw runtime::Exception(
111 std::string("ode_ksp_store() symbol not found. Error: ") + ::dlerror());
113 loadFn = reinterpret_cast<KeyStoragePluginLoadFn>(::dlsym(so, "ode_ksp_load"));
115 throw runtime::Exception(
116 std::string("ode_ksp_load() symbol not found. Error: ") + ::dlerror());
118 removeFn = reinterpret_cast<KeyStoragePluginRemoveFn>(::dlsym(so, "ode_ksp_remove"));
119 if (removeFn == NULL)
120 throw runtime::Exception(
121 std::string("ode_ksp_remove() symbol not found. Error: ") + ::dlerror());
124 KeyStoragePlugin::~KeyStoragePlugin()
129 BinaryData KeyStoragePlugin::store(const BinaryData& key)
131 unsigned char* token = NULL;
132 size_t token_len = 0;
133 int ret = storeFn(key.data(), key.size(), &token, &token_len);
134 if (ret != ODE_KSP_ERROR_NONE)
135 throw runtime::Exception(std::string("Storing the key failed with ") +
136 std::to_string(ret));
138 BinaryData tokenVector(token, token + token_len);
143 BinaryData KeyStoragePlugin::load(const BinaryData& token)
145 unsigned char* key = NULL;
147 int ret = loadFn(token.data(), token.size(), &key, &key_len);
148 if (ret != ODE_KSP_ERROR_NONE)
149 throw runtime::Exception(std::string("Loading the key failed with ") +
150 std::to_string(ret));
152 BinaryData keyVector(key, key + key_len);
157 void KeyStoragePlugin::remove(const BinaryData& token)
159 int ret = removeFn(token.data(), token.size());
160 if (ret == ODE_KSP_ERROR_NO_SUCH_FILE) {
161 INFO(SINK, "Key storage plugin does not recognize the token. Ignoring.");
164 if (ret != ODE_KSP_ERROR_NONE)
165 throw runtime::Exception(std::string("Removing the key failed with ") +
166 std::to_string(ret));
169 std::string getTokenFileName(const std::string &device)
171 std::string filename(device);
172 std::replace(filename.begin(), filename.end(), '/', '_');
174 return std::string("/opt/etc/.ode_token") + filename;
177 void readToken(runtime::File &file, BinaryData& token)
181 if (!file.exists()) {
187 file.read(&tokenSize, sizeof(tokenSize));
188 token.resize(tokenSize);
189 file.read(token.data(), tokenSize);
194 void writeToken(runtime::File &file, const BinaryData& token)
196 size_t tokenSize(token.size());
198 file.create(S_IRUSR | S_IWUSR | S_IRGRP);
199 file.chown(getuid(), getSystemShareGid());
201 file.write(&tokenSize, sizeof(tokenSize));
202 file.write(token.data(), token.size());
207 } // anonymous namespace
209 namespace UpgradeSupport {
211 void storeMasterKey(const std::string &device, const BinaryData& key)
213 std::lock_guard<std::mutex> lock(opGuard);
217 runtime::File file(getTokenFileName(device));
218 readToken(file, token);
220 auto& up = KeyStoragePlugin::Instance();
222 // remove previous entry if necessary
226 token = up.store(key);
228 writeToken(file, token);
231 BinaryData loadMasterKey(const std::string &device)
235 std::lock_guard<std::mutex> lock(opGuard);
237 runtime::File file(getTokenFileName(device));
238 readToken(file, token);
240 auto& up = KeyStoragePlugin::Instance();
241 return up.load(token);
244 void removeMasterKey(const std::string &device)
248 std::lock_guard<std::mutex> lock(opGuard);
250 runtime::File file(getTokenFileName(device));
251 readToken(file, token);
253 auto& up = KeyStoragePlugin::Instance();
258 } catch (runtime::Exception &e) {
259 ERROR(SINK, "Failed to remove token: " + std::string(e.what()));
263 void createUpgradeFlag()
265 runtime::File file(UPGRADE_FLAG_PATH);
266 file.create(S_IRUSR | S_IWUSR); // 0600
269 void removeUpgradeFlag()
271 runtime::File file(UPGRADE_FLAG_PATH);
272 bool exists = file.exists();
277 bool checkUpgradeFlag()
279 runtime::File file(UPGRADE_FLAG_PATH);
280 return file.exists();
283 } // namespace UpgradeSupport