2 * Copyright (c) 2015 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
20 #include <sys/mount.h>
21 #include <sys/reboot.h>
24 #include <klay/process.h>
25 #include <klay/file-user.h>
26 #include <klay/filesystem.h>
27 #include <klay/dbus/connection.h>
28 #include <klay/audit/logger.h>
30 #include "engine/dmcrypt-engine.h"
31 #include "key-manager/key-manager.h"
33 #include "rmi/internal-encryption.h"
35 #define INTERNAL_STORAGE_PATH "/opt/usr"
36 #define INTERNAL_STATE_VCONF_KEY VCONFKEY_ODE_CRYPTO_STATE
37 #define INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY VCONFKEY_ODE_FAST_ENCRYPTION
39 #define PRIVILEGE_PLATFORM "http://tizen.org/privilege/internal/default/platform"
45 VConfBackend vconfBackend(VCONFKEY_ODE_ENCRYPT_PROGRESS);
46 ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1));
48 DMCryptEngine engine("/dev/mmcblk0p25", INTERNAL_STORAGE_PATH, progressBar);
50 void stopDependedSystemdServices()
52 dbus::Connection& systemDBus = dbus::Connection::getSystem();
53 std::set<std::string> servicesToStop;
55 for (pid_t pid : runtime::FileUser::getList(INTERNAL_STORAGE_PATH, true)) {
58 systemDBus.methodcall("org.freedesktop.systemd1",
59 "/org/freedesktop/systemd1",
60 "org.freedesktop.systemd1.Manager",
62 -1, "(o)", "(u)", (unsigned int)pid)
63 .get("(o)", &service);
64 servicesToStop.insert(service);
65 } catch (runtime::Exception &e) {
66 INFO("Close process - " + std::to_string(pid));
71 for (const std::string& service : servicesToStop) {
72 INFO("Close service - " + service);
73 systemDBus.methodcall("org.freedesktop.systemd1",
75 "org.freedesktop.systemd1.Unit",
77 -1, "", "(s)", "flush");
81 void showProgressUI(const std::string type) {
82 std::vector<std::string> args = {
83 "ode", "progress", type, "Internal"
86 runtime::Process proc("/usr/bin/ode", args);
90 unsigned int getOptions()
92 unsigned int result = 0;
96 ::vconf_get_bool(INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY, &value);
98 result |= InternalEncryption::Option::IncludeUnusedRegion;
104 void setOptions(unsigned int options)
108 if (options & InternalEncryption::Option::IncludeUnusedRegion) {
113 ::vconf_set_bool(INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY, value);
118 InternalEncryption::InternalEncryption(ODEControlContext& ctx) :
121 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::mount)(std::string));
122 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::umount)());
123 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::encrypt)(std::string, unsigned int));
124 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::decrypt)(std::string));
125 context.expose(this, "", (int)(InternalEncryption::isPasswordInitialized)());
126 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::initPassword)(std::string));
127 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::cleanPassword)(std::string));
128 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::changePassword)(std::string, std::string));
129 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::verifyPassword)(std::string));
130 context.expose(this, "", (int)(InternalEncryption::getState)());
131 context.expose(this, "", (unsigned int)(InternalEncryption::getSupportedOptions)());
134 InternalEncryption::~InternalEncryption()
138 int InternalEncryption::mount(const std::string& password)
140 if (getState() != State::Encrypted) {
144 KeyManager::data pwData(password.begin(), password.end());
145 KeyManager keyManager(engine.getKeyMeta());
147 if (!keyManager.verifyPassword(pwData)) {
151 engine.mount(keyManager.getMasterKey(pwData), getOptions());
155 int InternalEncryption::umount()
157 if (getState() != State::Encrypted) {
161 INFO("Close all processes using internal storage...");
162 stopDependedSystemdServices();
163 INFO("Umount internal storage...");
169 int InternalEncryption::encrypt(const std::string& password, unsigned int options)
171 if (getState() != State::Unencrypted) {
175 KeyManager::data pwData(password.begin(), password.end());
176 KeyManager keyManager(engine.getKeyMeta());
178 if (!keyManager.verifyPassword(pwData)) {
182 KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
183 auto encryptWorker = [MasterKey, options, this]() {
185 showProgressUI("Encrypting");
187 INFO("Close all processes using internal storage...");
188 stopDependedSystemdServices();
189 INFO("Umount internal storage...");
190 while (::umount(INTERNAL_STORAGE_PATH) == -1) {
191 if (errno != EBUSY) {
192 throw runtime::Exception("Umount error - " + std::to_string(errno));
194 stopDependedSystemdServices();
197 INFO("Encryption started...");
198 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
199 engine.encrypt(MasterKey, options);
200 setOptions(options & getSupportedOptions());
201 INFO("Sync disk...");
203 INFO("Encryption completed");
205 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "encrypted");
206 } catch (runtime::Exception &e) {
207 ERROR("Encryption failed - " + std::string(e.what()));
209 ::reboot(RB_AUTOBOOT);
212 std::thread asyncWork(encryptWorker);
218 int InternalEncryption::decrypt(const std::string& password)
220 if (getState() != State::Encrypted) {
224 KeyManager::data pwData(password.begin(), password.end());
225 KeyManager keyManager(engine.getKeyMeta());
227 if (!keyManager.verifyPassword(pwData)) {
231 KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
232 auto decryptWorker = [MasterKey, this]() {
234 showProgressUI("Decrypting");
236 INFO("Close all processes using internal storage...");
237 stopDependedSystemdServices();
238 INFO("Umount internal storage...");
243 } catch (runtime::Exception& e) {
244 stopDependedSystemdServices();
248 INFO("Decryption started...");
249 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
250 engine.decrypt(MasterKey, getOptions());
251 INFO("Sync disk...");
253 INFO("Decryption completed");
255 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "unencrypted");
256 } catch (runtime::Exception &e) {
257 ERROR("Decryption failed - " + std::string(e.what()));
259 ::reboot(RB_AUTOBOOT);
262 std::thread asyncWork(decryptWorker);
268 int InternalEncryption::isPasswordInitialized()
270 if (engine.isKeyMetaSet()) {
276 int InternalEncryption::initPassword(const std::string& password)
278 KeyManager::data pwData(password.begin(), password.end());
279 KeyManager keyManager;
281 keyManager.initPassword(pwData);
282 engine.setKeyMeta(keyManager.serialize());
286 int InternalEncryption::cleanPassword(const std::string& password)
288 KeyManager::data pwData(password.begin(), password.end());
289 KeyManager keyManager(engine.getKeyMeta());
291 if (!keyManager.verifyPassword(pwData)) {
295 engine.clearKeyMeta();
299 int InternalEncryption::changePassword(const std::string& oldPassword,
300 const std::string& newPassword)
302 KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end());
303 KeyManager::data newPwData(newPassword.begin(), newPassword.end());
304 KeyManager keyManager(engine.getKeyMeta());
306 if (!keyManager.verifyPassword(oldPwData)) {
310 keyManager.changePassword(oldPwData, newPwData);
311 engine.setKeyMeta(keyManager.serialize());
316 int InternalEncryption::verifyPassword(const std::string& password)
318 KeyManager::data pwData(password.begin(), password.end());
319 KeyManager keyManager(engine.getKeyMeta());
321 if (keyManager.verifyPassword(pwData)) {
327 int InternalEncryption::getState()
329 char *value = ::vconf_get_str(INTERNAL_STATE_VCONF_KEY);
331 throw runtime::Exception("Failed to get vconf value");
334 std::string valueStr(value);
337 if (valueStr == "encrypted") {
338 return State::Encrypted;
339 } else if (valueStr == "unencrypted") {
340 return State::Unencrypted;
342 return State::Corrupted;
348 unsigned int InternalEncryption::getSupportedOptions()
350 return engine.getSupportedOptions();