Fix coverity issue
[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 #include <unistd.h>
24
25 #include <string>
26 #include <algorithm>
27 #include <memory>
28 #include <mutex>
29
30 #include <klay/filesystem.h>
31 #include <klay/exception.h>
32 #include <klay/auth/group.h>
33
34 #include <rmi/common.h>
35
36 #include <logger.h>
37 #include <ode-key-storage-plugin/ode-key-storage-plugin.h>
38
39 namespace ode {
40
41 namespace {
42
43 extern "C" {
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);
49 }
50
51 const std::string UPGRADE_FLAG_PATH = "/opt/etc/.ode_upgrade_started";
52
53 std::mutex opGuard;
54
55 gid_t getSystemShareGid()
56 {
57         static runtime::Group systemShare("system_share");
58
59         return systemShare.getGid();
60 }
61
62 // not thread-safe because of static member
63 class KeyStoragePlugin {
64 public:
65         explicit KeyStoragePlugin();
66
67         KeyStoragePlugin(KeyStoragePlugin&&) = default;
68
69         KeyStoragePlugin(const KeyStoragePlugin&) = delete;
70         KeyStoragePlugin& operator=(const KeyStoragePlugin&) = delete;
71
72         ~KeyStoragePlugin();
73
74         static KeyStoragePlugin& Instance();
75
76         BinaryData store(const BinaryData& key);
77         BinaryData load(const BinaryData& token);
78         void remove(const BinaryData& token);
79
80 private:
81         void* so;
82         KeyStoragePluginStoreFn storeFn;
83         KeyStoragePluginLoadFn loadFn;
84         KeyStoragePluginRemoveFn removeFn;
85
86         static std::unique_ptr<KeyStoragePlugin> plugin;
87 };
88
89 std::unique_ptr<KeyStoragePlugin> KeyStoragePlugin::plugin;
90
91 KeyStoragePlugin& KeyStoragePlugin::Instance()
92 {
93         if (!plugin)
94                 plugin.reset(new KeyStoragePlugin());
95
96         return *plugin;
97 }
98
99 KeyStoragePlugin::KeyStoragePlugin() : so(NULL)
100 {
101         std::string path = std::string(KEY_STORAGE_PLUGIN_DIR) + "/" + KEY_STORAGE_PLUGIN_LIB;
102
103         so = ::dlopen(path.c_str(), RTLD_LAZY);
104         if (so == NULL)
105                 throw runtime::Exception(std::string("Failed to load library: ") +
106                                                                  path + ". Error: " + ::dlerror());
107
108         storeFn = reinterpret_cast<KeyStoragePluginStoreFn>(::dlsym(so, "ode_ksp_store"));
109         if (storeFn == NULL)
110                 throw runtime::Exception(
111                         std::string("ode_ksp_store() symbol not found. Error: ") + ::dlerror());
112
113         loadFn = reinterpret_cast<KeyStoragePluginLoadFn>(::dlsym(so, "ode_ksp_load"));
114         if (loadFn == NULL)
115                 throw runtime::Exception(
116                         std::string("ode_ksp_load() symbol not found. Error: ") + ::dlerror());
117
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());
122 }
123
124 KeyStoragePlugin::~KeyStoragePlugin()
125 {
126         ::dlclose(so);
127 }
128
129 BinaryData KeyStoragePlugin::store(const BinaryData& key)
130 {
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));
137
138         BinaryData tokenVector(token, token + token_len);
139         free(token);
140         return tokenVector;
141 }
142
143 BinaryData KeyStoragePlugin::load(const BinaryData& token)
144 {
145         unsigned char* key = NULL;
146         size_t key_len = 0;
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));
151
152         BinaryData keyVector(key, key + key_len);
153         free(key);
154         return keyVector;
155 }
156
157 void KeyStoragePlugin::remove(const BinaryData& token)
158 {
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.");
162                 return;
163         }
164         if (ret != ODE_KSP_ERROR_NONE)
165                 throw runtime::Exception(std::string("Removing the key failed with ") +
166                                                                  std::to_string(ret));
167 }
168
169 std::string getTokenFileName(const std::string &device)
170 {
171         std::string filename(device);
172         std::replace(filename.begin(), filename.end(), '/', '_');
173
174         return std::string("/opt/etc/.ode_token") + filename;
175 }
176
177 void readToken(runtime::File &file, BinaryData& token)
178 {
179         size_t tokenSize;
180
181         if (!file.exists()) {
182                 token.clear();
183                 return;
184         }
185         file.open(O_RDONLY);
186
187         file.read(&tokenSize, sizeof(tokenSize));
188         token.resize(tokenSize);
189         file.read(token.data(), tokenSize);
190
191         file.close();
192 }
193
194 void writeToken(runtime::File &file, const BinaryData& token)
195 {
196         size_t tokenSize(token.size());
197
198         file.create(S_IRUSR | S_IWUSR | S_IRGRP);
199         file.chown(getuid(), getSystemShareGid());
200
201         file.write(&tokenSize, sizeof(tokenSize));
202         file.write(token.data(), token.size());
203
204         file.close();
205 }
206
207 } // anonymous namespace
208
209 namespace UpgradeSupport {
210
211 void storeMasterKey(const std::string &device, const BinaryData& key)
212 {
213         std::lock_guard<std::mutex> lock(opGuard);
214
215         BinaryData token;
216
217         runtime::File file(getTokenFileName(device));
218         readToken(file, token);
219
220         auto& up = KeyStoragePlugin::Instance();
221
222         // remove previous entry if necessary
223         if (!token.empty())
224                 up.remove(token);
225
226         token = up.store(key);
227
228         writeToken(file, token);
229 }
230
231 BinaryData loadMasterKey(const std::string &device)
232 {
233         BinaryData token;
234
235         std::lock_guard<std::mutex> lock(opGuard);
236
237         runtime::File file(getTokenFileName(device));
238         readToken(file, token);
239
240         auto& up = KeyStoragePlugin::Instance();
241         return up.load(token);
242 }
243
244 void removeMasterKey(const std::string &device)
245 {
246         BinaryData token;
247
248         std::lock_guard<std::mutex> lock(opGuard);
249
250         runtime::File file(getTokenFileName(device));
251         readToken(file, token);
252
253         auto& up = KeyStoragePlugin::Instance();
254         up.remove(token);
255
256         try {
257                 file.remove();
258         } catch (runtime::Exception &e) {
259                 ERROR(SINK, "Failed to remove token: " + std::string(e.what()));
260         }
261 }
262
263 void createUpgradeFlag()
264 {
265         runtime::File file(UPGRADE_FLAG_PATH);
266         file.create(S_IRUSR | S_IWUSR); // 0600
267 }
268
269 void removeUpgradeFlag()
270 {
271         runtime::File file(UPGRADE_FLAG_PATH);
272         bool exists = file.exists();
273         if (exists)
274                 file.remove();
275 }
276
277 bool checkUpgradeFlag()
278 {
279         runtime::File file(UPGRADE_FLAG_PATH);
280         return file.exists();
281 }
282
283 } // namespace UpgradeSupport
284
285 } // namespace ode