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
23 #include <sys/mount.h>
24 #include <sys/reboot.h>
30 #include <tzplatform_config.h>
31 #include <klay/process.h>
32 #include <klay/file-user.h>
33 #include <klay/filesystem.h>
34 #include <klay/dbus/connection.h>
38 #include "progress-bar.h"
39 #include "engine/encryption/dmcrypt-engine.h"
40 #include "key-manager/key-manager.h"
42 #include "rmi/internal-encryption.h"
48 typedef DMCryptEngine INTERNAL_ENGINE;
50 const char *INTERNAL_DEV_PATH = "/dev/disk/by-partlabel";
51 const char *INTERNAL_DEV_NAME = "USER";
52 const char *INTERNAL_PATH = "/opt/usr";
54 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
56 // TODO: see recovery()
57 const std::string PROG_FACTORY_RESET = "/usr/bin/dbus-send";
58 const std::vector<std::string> wipeCommand = {
63 "--dest=com.samsung.factoryreset",
64 "/com/samsung/factoryreset",
65 "com.samsung.factoryreset.start.setting"
68 std::unique_ptr<INTERNAL_ENGINE> engine;
69 KeyManager::data mountKey;
71 std::string findDevPath()
73 std::string source = INTERNAL_DEV_PATH + std::string("/") + INTERNAL_DEV_NAME;
75 runtime::DirectoryIterator iter(INTERNAL_DEV_PATH), end;
78 const std::string& path = (*iter).getPath();
79 std::string name = path.substr(path.rfind('/') + 1);
81 upper.reserve(name.size());
83 upper += std::toupper(c);
85 if (upper.compare(0, strlen(INTERNAL_DEV_NAME), INTERNAL_DEV_NAME) == 0) {
91 } catch (runtime::Exception &e) {}
93 char *dev = ::realpath(source.c_str(), NULL);
95 throw runtime::Exception("Failed to find device path.");
98 std::string devPath(dev);
104 void stopKnownSystemdServices() {
105 std::vector<std::string> knownSystemdServices;
106 dbus::Connection& systemDBus = dbus::Connection::getSystem();
107 dbus::VariantIterator iter;
109 systemDBus.methodcall("org.freedesktop.systemd1",
110 "/org/freedesktop/systemd1",
111 "org.freedesktop.systemd1.Manager",
113 -1, "(a(ssssssouso))", "")
114 .get("(a(ssssssouso))", &iter);
117 unsigned int dataUint;
121 ret = iter.get("(ssssssouso)", dataStr, dataStr + 1, dataStr + 2,
122 dataStr + 3, dataStr + 4, dataStr + 5,
123 dataStr + 6, &dataUint, dataStr + 7,
130 std::string service(dataStr[0]);
131 if (service.compare(0, 5, "user@") == 0 ||
132 service == "tlm.service" ||
133 service == "resourced.service") {
134 knownSystemdServices.push_back(service);
138 for (const std::string& service : knownSystemdServices) {
139 INFO(SINK, "Stop service - " + service);
140 systemDBus.methodcall("org.freedesktop.systemd1",
141 "/org/freedesktop/systemd1",
142 "org.freedesktop.systemd1.Manager",
144 -1, "", "(ss)", service.c_str(), "flush");
150 void stopDependedSystemdServices()
152 dbus::Connection& systemDBus = dbus::Connection::getSystem();
153 std::set<std::string> servicesToStop;
155 for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) {
158 systemDBus.methodcall("org.freedesktop.systemd1",
159 "/org/freedesktop/systemd1",
160 "org.freedesktop.systemd1.Manager",
162 -1, "(o)", "(u)", (unsigned int)pid)
163 .get("(o)", &service);
164 servicesToStop.insert(service);
165 } catch (runtime::Exception &e) {
166 INFO(SINK, "Close process - " + std::to_string(pid));
167 ::kill(pid, SIGKILL);
171 for (const std::string& service : servicesToStop) {
172 INFO(SINK, "Close service - " + service);
173 systemDBus.methodcall("org.freedesktop.systemd1",
175 "org.freedesktop.systemd1.Unit",
177 -1, "", "(s)", "flush");
181 void showProgressUI(const std::string type) {
182 ::tzplatform_set_user(::tzplatform_getuid(TZ_SYS_DEFAULT_USER));
183 std::string defaultUserHome(::tzplatform_getenv(TZ_USER_HOME));
184 ::tzplatform_reset_user();
187 runtime::File shareDirectory("/opt/home/root/share");
188 if (!shareDirectory.exists()) {
189 shareDirectory.makeDirectory(true);
192 runtime::File elmConfigDir(shareDirectory.getPath() + "/.elementary");
193 if (!elmConfigDir.exists()) {
194 runtime::File defaultElmConfigDir(defaultUserHome + "/share/.elementary");
195 defaultElmConfigDir.copyTo(shareDirectory.getPath());
197 } catch (runtime::Exception &e) {
198 ERROR(SINK, "Failed to set up elm configuration");
201 std::vector<std::string> args = {
202 "ode", "progress", type, "Internal"
205 runtime::Process proc("/usr/bin/ode", args);
209 unsigned int getOptions()
211 unsigned int result = 0;
215 ::vconf_get_bool(VCONFKEY_ODE_FAST_ENCRYPTION, &value);
217 result |= InternalEncryption::Option::IncludeUnusedRegion;
223 void setOptions(unsigned int options)
227 if (options & InternalEncryption::Option::IncludeUnusedRegion) {
232 ::vconf_set_bool(VCONFKEY_ODE_FAST_ENCRYPTION, value);
237 InternalEncryption::InternalEncryption(ODEControlContext& ctx) :
240 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::setMountPassword)(std::string));
241 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::mount)());
242 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::umount)());
243 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::encrypt)(std::string, unsigned int));
244 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::decrypt)(std::string));
245 context.expose(this, "", (int)(InternalEncryption::isPasswordInitialized)());
246 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::initPassword)(std::string));
247 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::cleanPassword)(std::string));
248 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::changePassword)(std::string, std::string));
249 context.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryption::verifyPassword)(std::string));
250 context.expose(this, "", (int)(InternalEncryption::getState)());
251 context.expose(this, "", (unsigned int)(InternalEncryption::getSupportedOptions)());
253 context.createNotification("InternalEncryption::mount");
255 std::string source = findDevPath();
257 engine.reset(new INTERNAL_ENGINE(
258 source, INTERNAL_PATH,
259 ProgressBar([](int v) {
260 ::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS,
261 std::to_string(v).c_str());
266 InternalEncryption::~InternalEncryption()
270 int InternalEncryption::setMountPassword(const std::string& password)
272 KeyManager::data pwData(password.begin(), password.end());
273 KeyManager keyManager(engine->getKeyMeta());
274 if (!keyManager.verifyPassword(pwData)) {
278 ode::mountKey = keyManager.getMasterKey(pwData);
283 int InternalEncryption::mount()
285 if (getState() != State::Encrypted) {
289 if (engine->isMounted()) {
290 INFO(SINK, "Already mounted");
295 INFO(SINK, "Mount internal storage...");
296 engine->mount(mountKey, getOptions());
299 context.notify("InternalEncryption::mount");
301 runtime::File("/tmp/.lazy_mount").create(O_WRONLY);
302 runtime::File("/tmp/.unlock_mnt").create(O_WRONLY);
303 } catch (runtime::Exception &e) {
304 ERROR(SINK, "Mount failed - " + std::string(e.what()));
311 int InternalEncryption::umount()
313 if (getState() != State::Encrypted) {
317 if (!engine->isMounted()) {
318 INFO(SINK, "Already umounted");
323 INFO(SINK, "Close all processes using internal storage...");
324 stopDependedSystemdServices();
325 INFO(SINK, "Umount internal storage...");
327 } catch (runtime::Exception &e) {
328 ERROR(SINK, "Umount failed - " + std::string(e.what()));
335 int InternalEncryption::encrypt(const std::string& password, unsigned int options)
337 if (getState() != State::Unencrypted) {
341 KeyManager::data pwData(password.begin(), password.end());
342 KeyManager keyManager(engine->getKeyMeta());
344 if (!keyManager.verifyPassword(pwData)) {
348 KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
349 auto encryptWorker = [MasterKey, options, this]() {
351 std::string source = engine->getSource();
352 std::string mntPath = findMntPath(source);
354 if (!mntPath.empty()) {
355 INFO(SINK, "Close all known systemd services that might be using internal storage...");
356 stopKnownSystemdServices();
357 INFO(SINK, "Close all processes using internal storage...");
358 stopDependedSystemdServices();
361 while (!mntPath.empty()) {
362 INFO(SINK, "Umount internal storage...");
363 while (::umount(mntPath.c_str()) == -1) {
364 if (errno != EBUSY) {
365 throw runtime::Exception("Umount error - " + std::to_string(errno));
367 stopDependedSystemdServices();
369 mntPath = findMntPath(source);
372 showProgressUI("Encrypting");
374 INFO(SINK, "Encryption started...");
375 engine->encrypt(MasterKey, options);
376 setOptions(options & getSupportedOptions());
378 INFO(SINK, "Encryption completed");
379 ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "encrypted");
380 context.notify("InternalEncryption::mount");
382 INFO(SINK, "Syncing disk and rebooting...");
384 ::reboot(RB_AUTOBOOT);
385 } catch (runtime::Exception &e) {
386 ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_encrypted");
387 ERROR(SINK, "Encryption failed - " + std::string(e.what()));
391 std::thread asyncWork(encryptWorker);
397 int InternalEncryption::decrypt(const std::string& password)
399 if (getState() != State::Encrypted) {
403 KeyManager::data pwData(password.begin(), password.end());
404 KeyManager keyManager(engine->getKeyMeta());
406 if (!keyManager.verifyPassword(pwData)) {
410 KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
411 auto decryptWorker = [MasterKey, this]() {
413 if (engine->isMounted()) {
414 INFO(SINK, "Close all known systemd services that might be using internal storage...");
415 stopKnownSystemdServices();
416 INFO(SINK, "Close all processes using internal storage...");
417 stopDependedSystemdServices();
419 INFO(SINK, "Umount internal storage...");
424 } catch (runtime::Exception& e) {
425 stopDependedSystemdServices();
430 showProgressUI("Decrypting");
432 INFO(SINK, "Decryption started...");
433 engine->decrypt(MasterKey, getOptions());
435 INFO(SINK, "Decryption completed");
436 ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "unencrypted");
438 INFO(SINK, "Syncing disk and rebooting...");
440 ::reboot(RB_AUTOBOOT);
441 } catch (runtime::Exception &e) {
442 ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_encrypted");
443 ERROR(SINK, "Decryption failed - " + std::string(e.what()));
447 std::thread asyncWork(decryptWorker);
453 int InternalEncryption::recovery()
455 if (getState() != State::Unencrypted) {
460 runtime::Process proc(PROG_FACTORY_RESET, wipeCommand);
461 if (proc.execute() == -1) {
462 ERROR(SINK, "Failed to launch factory-reset");
469 int InternalEncryption::isPasswordInitialized()
471 if (engine->isKeyMetaSet()) {
477 int InternalEncryption::initPassword(const std::string& password)
479 KeyManager::data pwData(password.begin(), password.end());
480 KeyManager keyManager;
482 keyManager.initPassword(pwData);
483 engine->setKeyMeta(keyManager.serialize());
487 int InternalEncryption::cleanPassword(const std::string& password)
489 KeyManager::data pwData(password.begin(), password.end());
490 KeyManager keyManager(engine->getKeyMeta());
492 if (!keyManager.verifyPassword(pwData)) {
496 engine->clearKeyMeta();
500 int InternalEncryption::changePassword(const std::string& oldPassword,
501 const std::string& newPassword)
503 KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end());
504 KeyManager::data newPwData(newPassword.begin(), newPassword.end());
505 KeyManager keyManager(engine->getKeyMeta());
507 if (!keyManager.verifyPassword(oldPwData)) {
511 keyManager.changePassword(oldPwData, newPwData);
512 engine->setKeyMeta(keyManager.serialize());
517 int InternalEncryption::verifyPassword(const std::string& password)
519 KeyManager::data pwData(password.begin(), password.end());
520 KeyManager keyManager(engine->getKeyMeta());
522 if (keyManager.verifyPassword(pwData)) {
528 int InternalEncryption::getState()
530 char *value = ::vconf_get_str(VCONFKEY_ODE_CRYPTO_STATE);
532 throw runtime::Exception("Failed to get vconf value");
535 std::string valueStr(value);
538 if (valueStr == "encrypted") {
539 return State::Encrypted;
540 } else if (valueStr == "unencrypted") {
541 return State::Unencrypted;
543 return State::Corrupted;
549 unsigned int InternalEncryption::getSupportedOptions()
551 return engine->getSupportedOptions();