Print force killed process list for debugging
[platform/core/security/ode.git] / server / upgrade-support.cpp
1 /*
2  *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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
15  */
16
17 #include "upgrade-support.h"
18
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <dlfcn.h>
22 #include <fcntl.h>
23
24 #include <string>
25 #include <algorithm>
26 #include <memory>
27 #include <mutex>
28
29 #include <klay/filesystem.h>
30 #include <klay/exception.h>
31
32 #include <rmi/common.h>
33
34 #include <logger.h>
35 #include <ode-key-storage-plugin/ode-key-storage-plugin.h>
36
37 namespace ode {
38
39 namespace {
40
41 extern "C" {
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);
47 }
48
49 const std::string UPGRADE_FLAG_PATH = "/opt/etc/.ode_upgrade_started";
50
51 std::mutex opGuard;
52
53 // not thread-safe because of static member
54 class KeyStoragePlugin {
55 public:
56         explicit KeyStoragePlugin();
57
58         KeyStoragePlugin(KeyStoragePlugin&&) = default;
59
60         KeyStoragePlugin(const KeyStoragePlugin&) = delete;
61         KeyStoragePlugin& operator=(const KeyStoragePlugin&) = delete;
62
63         ~KeyStoragePlugin();
64
65         static KeyStoragePlugin& Instance();
66
67         BinaryData store(const BinaryData& key);
68         BinaryData load(const BinaryData& token);
69         void remove(const BinaryData& token);
70
71 private:
72         void* so;
73         KeyStoragePluginStoreFn storeFn;
74         KeyStoragePluginLoadFn loadFn;
75         KeyStoragePluginRemoveFn removeFn;
76
77         static std::unique_ptr<KeyStoragePlugin> plugin;
78 };
79
80 std::unique_ptr<KeyStoragePlugin> KeyStoragePlugin::plugin;
81
82 KeyStoragePlugin& KeyStoragePlugin::Instance()
83 {
84         if (!plugin)
85                 plugin.reset(new KeyStoragePlugin());
86
87         return *plugin;
88 }
89
90 KeyStoragePlugin::KeyStoragePlugin() : so(NULL)
91 {
92         std::string path = std::string(KEY_STORAGE_PLUGIN_DIR) + "/" + KEY_STORAGE_PLUGIN_LIB;
93
94         so = ::dlopen(path.c_str(), RTLD_LAZY);
95         if (so == NULL)
96                 throw runtime::Exception(std::string("Failed to load library: ") +
97                                                                  path + ". Error: " + ::dlerror());
98
99         storeFn = reinterpret_cast<KeyStoragePluginStoreFn>(::dlsym(so, "ode_ksp_store"));
100         if (storeFn == NULL)
101                 throw runtime::Exception(
102                         std::string("ode_ksp_store() symbol not found. Error: ") + ::dlerror());
103
104         loadFn = reinterpret_cast<KeyStoragePluginLoadFn>(::dlsym(so, "ode_ksp_load"));
105         if (loadFn == NULL)
106                 throw runtime::Exception(
107                         std::string("ode_ksp_load() symbol not found. Error: ") + ::dlerror());
108
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());
113 }
114
115 KeyStoragePlugin::~KeyStoragePlugin()
116 {
117         ::dlclose(so);
118 }
119
120 BinaryData KeyStoragePlugin::store(const BinaryData& key)
121 {
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));
128
129         BinaryData tokenVector(token, token + token_len);
130         free(token);
131         return tokenVector;
132 }
133
134 BinaryData KeyStoragePlugin::load(const BinaryData& token)
135 {
136         unsigned char* key = NULL;
137         size_t key_len = 0;
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));
142
143         BinaryData keyVector(key, key + key_len);
144         free(key);
145         return keyVector;
146 }
147
148 void KeyStoragePlugin::remove(const BinaryData& token)
149 {
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.");
153                 return;
154         }
155         if (ret != ODE_KSP_ERROR_NONE)
156                 throw runtime::Exception(std::string("Removing the key failed with ") +
157                                                                  std::to_string(ret));
158 }
159
160 std::string getTokenFileName(const std::string &device)
161 {
162         std::string filename(device);
163         std::replace(filename.begin(), filename.end(), '/', '_');
164
165         return std::string("/opt/etc/.ode_token") + filename;
166 }
167
168 void readToken(runtime::File &file, BinaryData& token)
169 {
170         size_t tokenSize;
171
172         if (!file.exists()) {
173                 token.clear();
174                 return;
175         }
176         file.open(O_RDONLY);
177
178         file.read(&tokenSize, sizeof(tokenSize));
179         token.resize(tokenSize);
180         file.read(token.data(), tokenSize);
181
182         file.close();
183 }
184
185 void writeToken(runtime::File &file, const BinaryData& token)
186 {
187         size_t tokenSize(token.size());
188
189         file.create(0640);
190
191         file.write(&tokenSize, sizeof(tokenSize));
192         file.write(token.data(), token.size());
193
194         file.close();
195 }
196
197 } // anonymous namespace
198
199 namespace UpgradeSupport {
200
201 void storeMasterKey(const std::string &device, const BinaryData& key)
202 {
203         std::lock_guard<std::mutex> lock(opGuard);
204
205         BinaryData token;
206
207         runtime::File file(getTokenFileName(device));
208         readToken(file, token);
209
210         auto& up = KeyStoragePlugin::Instance();
211
212         // remove previous entry if necessary
213         if (!token.empty())
214                 up.remove(token);
215
216         token = up.store(key);
217
218         writeToken(file, token);
219 }
220
221 BinaryData loadMasterKey(const std::string &device)
222 {
223         BinaryData token;
224
225         std::lock_guard<std::mutex> lock(opGuard);
226
227         runtime::File file(getTokenFileName(device));
228         readToken(file, token);
229
230         auto& up = KeyStoragePlugin::Instance();
231         return up.load(token);
232 }
233
234 void removeMasterKey(const std::string &device)
235 {
236         BinaryData token;
237
238         std::lock_guard<std::mutex> lock(opGuard);
239
240         runtime::File file(getTokenFileName(device));
241         readToken(file, token);
242
243         auto& up = KeyStoragePlugin::Instance();
244         up.remove(token);
245
246         try {
247                 file.remove();
248         } catch (runtime::Exception &e) {
249                 ERROR(SINK, "Failed to remove token: " + std::string(e.what()));
250         }
251 }
252
253 void createUpgradeFlag()
254 {
255         runtime::File file(UPGRADE_FLAG_PATH);
256         file.create(S_IRUSR | S_IWUSR); // 0600
257 }
258
259 void removeUpgradeFlag()
260 {
261         runtime::File file(UPGRADE_FLAG_PATH);
262         bool exists = file.exists();
263         if (exists)
264                 file.remove();
265 }
266
267 bool checkUpgradeFlag()
268 {
269         runtime::File file(UPGRADE_FLAG_PATH);
270         return file.exists();
271 }
272
273 } // namespace UpgradeSupport
274
275 } // namespace ode