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>
31 #include "progress-bar.h"
32 #include "engine/encryption/dmcrypt-engine.h"
33 #include "key-manager/key-manager.h"
35 #include "rmi/internal-encryption.h"
37 #define INTERNAL_ENGINE DMCryptEngine
38 #define INTERNAL_DEV "/dev/mmcblk0p25"
39 #define INTERNAL_PATH "/opt/usr"
40 #define INTERNAL_STATE_VCONF_KEY VCONFKEY_ODE_CRYPTO_STATE
41 #define INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY VCONFKEY_ODE_FAST_ENCRYPTION
43 #define PRIVILEGE_PLATFORM "http://tizen.org/privilege/internal/default/platform"
49 std::unique_ptr<INTERNAL_ENGINE> engine;
51 void stopDependedSystemdServices()
53 dbus::Connection& systemDBus = dbus::Connection::getSystem();
54 std::set<std::string> servicesToStop;
56 for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) {
59 systemDBus.methodcall("org.freedesktop.systemd1",
60 "/org/freedesktop/systemd1",
61 "org.freedesktop.systemd1.Manager",
63 -1, "(o)", "(u)", (unsigned int)pid)
64 .get("(o)", &service);
65 servicesToStop.insert(service);
66 } catch (runtime::Exception &e) {
67 INFO("Close process - " + std::to_string(pid));
72 for (const std::string& service : servicesToStop) {
73 INFO("Close service - " + service);
74 systemDBus.methodcall("org.freedesktop.systemd1",
76 "org.freedesktop.systemd1.Unit",
78 -1, "", "(s)", "flush");
82 void showProgressUI(const std::string type) {
83 std::vector<std::string> args = {
84 "ode", "progress", type, "Internal"
87 runtime::Process proc("/usr/bin/ode", args);
91 unsigned int getOptions()
93 unsigned int result = 0;
97 ::vconf_get_bool(INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY, &value);
99 result |= InternalEncryption::Option::IncludeUnusedRegion;
105 void setOptions(unsigned int options)
109 if (options & InternalEncryption::Option::IncludeUnusedRegion) {
114 ::vconf_set_bool(INTERNAL_OPTION_ONLY_USED_REGION_VCONF_KEY, value);
119 InternalEncryption::InternalEncryption(ODEControlContext& ctx) :
122 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::mount)(std::string));
123 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::umount)());
124 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::encrypt)(std::string, unsigned int));
125 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::decrypt)(std::string));
126 context.expose(this, "", (int)(InternalEncryption::isPasswordInitialized)());
127 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::initPassword)(std::string));
128 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::cleanPassword)(std::string));
129 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::changePassword)(std::string, std::string));
130 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::verifyPassword)(std::string));
131 context.expose(this, "", (int)(InternalEncryption::getState)());
132 context.expose(this, "", (unsigned int)(InternalEncryption::getSupportedOptions)());
134 engine.reset(new INTERNAL_ENGINE(
135 INTERNAL_DEV, INTERNAL_PATH,
136 ProgressBar([](int v) {
137 ::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS,
138 std::to_string(v).c_str());
143 InternalEncryption::~InternalEncryption()
147 int InternalEncryption::mount(const std::string& password)
149 if (getState() != State::Encrypted) {
153 KeyManager::data pwData(password.begin(), password.end());
154 KeyManager keyManager(engine->getKeyMeta());
156 if (!keyManager.verifyPassword(pwData)) {
160 engine->mount(keyManager.getMasterKey(pwData), getOptions());
164 int InternalEncryption::umount()
166 if (getState() != State::Encrypted) {
170 INFO("Close all processes using internal storage...");
171 stopDependedSystemdServices();
172 INFO("Umount internal storage...");
178 int InternalEncryption::encrypt(const std::string& password, unsigned int options)
180 if (getState() != State::Unencrypted) {
184 KeyManager::data pwData(password.begin(), password.end());
185 KeyManager keyManager(engine->getKeyMeta());
187 if (!keyManager.verifyPassword(pwData)) {
191 KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
192 auto encryptWorker = [MasterKey, options, this]() {
194 showProgressUI("Encrypting");
196 INFO("Close all processes using internal storage...");
197 stopDependedSystemdServices();
198 INFO("Umount internal storage...");
199 while (::umount(INTERNAL_PATH) == -1) {
200 if (errno != EBUSY) {
201 throw runtime::Exception("Umount error - " + std::to_string(errno));
203 stopDependedSystemdServices();
206 INFO("Encryption started...");
207 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
208 engine->encrypt(MasterKey, options);
209 setOptions(options & getSupportedOptions());
210 INFO("Sync disk...");
212 INFO("Encryption completed");
214 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "encrypted");
215 } catch (runtime::Exception &e) {
216 ERROR("Encryption failed - " + std::string(e.what()));
218 ::reboot(RB_AUTOBOOT);
221 std::thread asyncWork(encryptWorker);
227 int InternalEncryption::decrypt(const std::string& password)
229 if (getState() != State::Encrypted) {
233 KeyManager::data pwData(password.begin(), password.end());
234 KeyManager keyManager(engine->getKeyMeta());
236 if (!keyManager.verifyPassword(pwData)) {
240 KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
241 auto decryptWorker = [MasterKey, this]() {
243 showProgressUI("Decrypting");
245 INFO("Close all processes using internal storage...");
246 stopDependedSystemdServices();
247 INFO("Umount internal storage...");
252 } catch (runtime::Exception& e) {
253 stopDependedSystemdServices();
257 INFO("Decryption started...");
258 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
259 engine->decrypt(MasterKey, getOptions());
260 INFO("Sync disk...");
262 INFO("Decryption completed");
264 ::vconf_set_str(INTERNAL_STATE_VCONF_KEY, "unencrypted");
265 } catch (runtime::Exception &e) {
266 ERROR("Decryption failed - " + std::string(e.what()));
268 ::reboot(RB_AUTOBOOT);
271 std::thread asyncWork(decryptWorker);
277 int InternalEncryption::isPasswordInitialized()
279 if (engine->isKeyMetaSet()) {
285 int InternalEncryption::initPassword(const std::string& password)
287 KeyManager::data pwData(password.begin(), password.end());
288 KeyManager keyManager;
290 keyManager.initPassword(pwData);
291 engine->setKeyMeta(keyManager.serialize());
295 int InternalEncryption::cleanPassword(const std::string& password)
297 KeyManager::data pwData(password.begin(), password.end());
298 KeyManager keyManager(engine->getKeyMeta());
300 if (!keyManager.verifyPassword(pwData)) {
304 engine->clearKeyMeta();
308 int InternalEncryption::changePassword(const std::string& oldPassword,
309 const std::string& newPassword)
311 KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end());
312 KeyManager::data newPwData(newPassword.begin(), newPassword.end());
313 KeyManager keyManager(engine->getKeyMeta());
315 if (!keyManager.verifyPassword(oldPwData)) {
319 keyManager.changePassword(oldPwData, newPwData);
320 engine->setKeyMeta(keyManager.serialize());
325 int InternalEncryption::verifyPassword(const std::string& password)
327 KeyManager::data pwData(password.begin(), password.end());
328 KeyManager keyManager(engine->getKeyMeta());
330 if (keyManager.verifyPassword(pwData)) {
336 int InternalEncryption::getState()
338 char *value = ::vconf_get_str(INTERNAL_STATE_VCONF_KEY);
340 throw runtime::Exception("Failed to get vconf value");
343 std::string valueStr(value);
346 if (valueStr == "encrypted") {
347 return State::Encrypted;
348 } else if (valueStr == "unencrypted") {
349 return State::Unencrypted;
351 return State::Corrupted;
357 unsigned int InternalEncryption::getSupportedOptions()
359 return engine->getSupportedOptions();