Add internal encryption with key-manager and engine
[platform/core/security/ode.git] / server / internal-encryption.cpp
1 /*
2  *  Copyright (c) 2015 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 #include <unistd.h>
17 #include <sys/mount.h>
18 #include <sys/reboot.h>
19
20 #include <klay/filesystem.h>
21 #include <klay/dbus/connection.h>
22 #include <klay/audit/logger.h>
23
24 #include "engine/dmcrypt-engine.h"
25 #include "key-manager/key-manager.h"
26
27 #include "rmi/internal-encryption.h"
28
29 #define INTERNAL_STORAGE_PATH   "/opt/usr"
30
31 namespace ode {
32
33 namespace {
34
35 KeyManager keyManager(INTERNAL_STORAGE_PATH);
36 DMCryptEngine engine("/dev/mmcblk0p25", INTERNAL_STORAGE_PATH);
37
38 std::vector<std::string> dependedSystemdServices = {
39         "resourced.service",
40         "msg-server.service",
41         "mtp-responder.service",
42 };
43
44 void stopDependedSystemdServices()
45 {
46         std::vector<std::string> servicesToStop(dependedSystemdServices);
47         dbus::Connection& systemDBus = dbus::Connection::getSystem();
48         dbus::VariantIterator iter;
49
50         systemDBus.methodcall("org.freedesktop.systemd1",
51                                                         "/org/freedesktop/systemd1",
52                                                         "org.freedesktop.systemd1.Manager",
53                                                         "ListUnits",
54                                                         -1, "(a(ssssssouso))", "")
55                                                                 .get("(a(ssssssouso))", &iter);
56
57         while(1) {
58                 unsigned int dataUint;
59                 char *dataStr[9];
60                 int ret;
61
62                 ret = iter.get("(ssssssouso)", dataStr, dataStr + 1, dataStr + 2,
63                                                                                 dataStr + 3, dataStr + 4, dataStr + 5,
64                                                                                 dataStr + 6, &dataUint, dataStr + 7,
65                                                                                 dataStr + 8);
66
67                 if (!ret) {
68                         break;
69                 }
70
71                 std::string service(dataStr[0]);
72                 if (service.compare(0, 5, "user@") == 0) {
73                         servicesToStop.push_back(service);
74                 }
75         }
76
77
78         //TODO : get other services that are using INTERNAL_STORAGE_PATH
79
80         for (const std::string& service : servicesToStop) {
81                 INFO("Stop service - " + service);
82                 systemDBus.methodcall("org.freedesktop.systemd1",
83                                                                 "/org/freedesktop/systemd1",
84                                                                 "org.freedesktop.systemd1.Manager",
85                                                                 "StopUnit",
86                                                                 -1, "", "(ss)", service.c_str(), "flush");
87         }
88 }
89
90 }
91
92 InternalEncryption::InternalEncryption(ODEControlContext& ctx) :
93         context(ctx)
94 {
95         context.registerParametricMethod(this, "", (int)(InternalEncryption::mount)(std::string));
96         context.registerNonparametricMethod(this, "", (int)(InternalEncryption::umount));
97         context.registerParametricMethod(this, "", (int)(InternalEncryption::encrypt)(std::string));
98         context.registerParametricMethod(this, "", (int)(InternalEncryption::decrypt)(std::string));
99         context.registerParametricMethod(this, "", (int)(InternalEncryption::changePassword)(std::string, std::string));
100         context.registerNonparametricMethod(this, "", (int)(InternalEncryption::getState));
101 }
102
103 InternalEncryption::~InternalEncryption()
104 {
105 }
106
107 int InternalEncryption::mount(const std::string& password)
108 {
109         bool isVerified = false;
110         KeyManager::data pwData(password.begin(), password.end());
111
112         try {
113                 isVerified = keyManager.verifyPassword(pwData);
114         } catch (runtime::Exception& e) {}
115
116         if (!isVerified) {
117                 return -1;
118         }
119
120         engine.mount(keyManager.getDEK(pwData));
121         return 0;
122 }
123
124 int InternalEncryption::umount()
125 {
126         INFO("Close all processes using internal storage...");
127         stopDependedSystemdServices();
128         INFO("Umount internal storage...");
129         engine.umount();
130
131         return 0;
132 }
133
134 int InternalEncryption::encrypt(const std::string& password)
135 {
136         KeyManager::data pwData(password.begin(), password.end());
137
138         if (keyManager.isInitialized()) {
139                 bool isVerified = false;
140                 try {
141                         isVerified = keyManager.verifyPassword(pwData);
142                 } catch (runtime::Exception& e) {}
143
144                 if (!isVerified) {
145                         return -2;
146                 }
147         } else {
148                 keyManager.initPassword(pwData);
149         }
150
151         KeyManager::data DEK = keyManager.getDEK(pwData);
152         auto encryptWorker = [DEK, this]() {
153                 INFO("Close all processes using internal storage...");
154                 stopDependedSystemdServices();
155                 INFO("Umount internal storage...");
156                 while (::umount(INTERNAL_STORAGE_PATH) == -1) {
157                         if (errno != EBUSY) {
158                                 break;
159                         }
160                 }
161                 INFO("Encryption started...");
162                 engine.encrypt(DEK);
163                 INFO("Sync disk...");
164                 sync();
165                 INFO("Encryption completed");
166                 ::reboot(RB_AUTOBOOT);
167         };
168
169         std::thread asyncWork(encryptWorker);
170         asyncWork.detach();
171
172         return 0;
173 }
174
175 int InternalEncryption::decrypt(const std::string& password)
176 {
177         bool isVerified = false;
178         KeyManager::data pwData(password.begin(), password.end());
179
180         try {
181                 isVerified = keyManager.verifyPassword(pwData);
182         } catch (runtime::Exception& e) {}
183
184         if (!isVerified) {
185                 return -1;
186         }
187
188         KeyManager::data DEK = keyManager.getDEK(pwData);
189         auto decryptWorker = [DEK, this]() {
190                 INFO("Close all processes using internal storage...");
191                 stopDependedSystemdServices();
192                 INFO("Umount internal storage...");
193                 try {
194                         engine.umount();
195                 } catch (runtime::Exception& e) {}
196                 INFO("Decryption started...");
197                 engine.decrypt(DEK);
198                 INFO("Sync disk...");
199                 sync();
200                 INFO("Decryption completed");
201                 ::reboot(RB_AUTOBOOT);
202         };
203
204         std::thread asyncWork(decryptWorker);
205         asyncWork.detach();
206
207         keyManager.clearPassword();
208
209         return 0;
210 }
211
212 int InternalEncryption::changePassword(const std::string& oldPassword,
213                                                                                 const std::string& newPassword)
214 {
215         KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end());
216         KeyManager::data newPwData(newPassword.begin(), oldPassword.end());
217
218         bool isVerified = false;
219         try     {
220                 isVerified = keyManager.verifyPassword(newPwData);
221         } catch (runtime::Exception& e) {}
222
223         if (!isVerified) {
224                 return -1;
225         }
226
227         keyManager.changePassword(oldPwData, newPwData);
228         return 0;
229 }
230
231 int InternalEncryption::getState()
232 {
233         //TODO
234         return 0;
235 }
236
237 } // namespace ode