From 97d073da4f6a2f81712b7b9750412c9dc783e03b Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Fri, 18 Nov 2016 15:12:22 +0900 Subject: [PATCH] Add internal encryption with key-manager and engine Signed-off-by: Sungbae Yoo Change-Id: Ibb21880e538e7a83a1b72cf0c5e8f4009fa4577c --- server/internal-encryption.cpp | 170 +++++++++++++++++++++++++++++++-- 1 file changed, 164 insertions(+), 6 deletions(-) diff --git a/server/internal-encryption.cpp b/server/internal-encryption.cpp index 6978dfc..59a9186 100644 --- a/server/internal-encryption.cpp +++ b/server/internal-encryption.cpp @@ -13,7 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License */ +#include +#include +#include + #include +#include #include #include "engine/dmcrypt-engine.h" @@ -21,8 +26,69 @@ #include "rmi/internal-encryption.h" +#define INTERNAL_STORAGE_PATH "/opt/usr" + namespace ode { +namespace { + +KeyManager keyManager(INTERNAL_STORAGE_PATH); +DMCryptEngine engine("/dev/mmcblk0p25", INTERNAL_STORAGE_PATH); + +std::vector dependedSystemdServices = { + "resourced.service", + "msg-server.service", + "mtp-responder.service", +}; + +void stopDependedSystemdServices() +{ + std::vector servicesToStop(dependedSystemdServices); + dbus::Connection& systemDBus = dbus::Connection::getSystem(); + dbus::VariantIterator iter; + + systemDBus.methodcall("org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "ListUnits", + -1, "(a(ssssssouso))", "") + .get("(a(ssssssouso))", &iter); + + while(1) { + unsigned int dataUint; + char *dataStr[9]; + int ret; + + ret = iter.get("(ssssssouso)", dataStr, dataStr + 1, dataStr + 2, + dataStr + 3, dataStr + 4, dataStr + 5, + dataStr + 6, &dataUint, dataStr + 7, + dataStr + 8); + + if (!ret) { + break; + } + + std::string service(dataStr[0]); + if (service.compare(0, 5, "user@") == 0) { + servicesToStop.push_back(service); + } + } + + + //TODO : get other services that are using INTERNAL_STORAGE_PATH + + for (const std::string& service : servicesToStop) { + INFO("Stop service - " + service); + systemDBus.methodcall("org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StopUnit", + -1, "", "(ss)", service.c_str(), "flush"); + } +} + +} + InternalEncryption::InternalEncryption(ODEControlContext& ctx) : context(ctx) { @@ -34,39 +100,131 @@ InternalEncryption::InternalEncryption(ODEControlContext& ctx) : context.registerNonparametricMethod(this, "", (int)(InternalEncryption::getState)); } - InternalEncryption::~InternalEncryption() { } int InternalEncryption::mount(const std::string& password) { - //TODO + bool isVerified = false; + KeyManager::data pwData(password.begin(), password.end()); + + try { + isVerified = keyManager.verifyPassword(pwData); + } catch (runtime::Exception& e) {} + + if (!isVerified) { + return -1; + } + + engine.mount(keyManager.getDEK(pwData)); return 0; } int InternalEncryption::umount() { - //TODO + INFO("Close all processes using internal storage..."); + stopDependedSystemdServices(); + INFO("Umount internal storage..."); + engine.umount(); + return 0; } int InternalEncryption::encrypt(const std::string& password) { - //TODO + KeyManager::data pwData(password.begin(), password.end()); + + if (keyManager.isInitialized()) { + bool isVerified = false; + try { + isVerified = keyManager.verifyPassword(pwData); + } catch (runtime::Exception& e) {} + + if (!isVerified) { + return -2; + } + } else { + keyManager.initPassword(pwData); + } + + KeyManager::data DEK = keyManager.getDEK(pwData); + auto encryptWorker = [DEK, this]() { + INFO("Close all processes using internal storage..."); + stopDependedSystemdServices(); + INFO("Umount internal storage..."); + while (::umount(INTERNAL_STORAGE_PATH) == -1) { + if (errno != EBUSY) { + break; + } + } + INFO("Encryption started..."); + engine.encrypt(DEK); + INFO("Sync disk..."); + sync(); + INFO("Encryption completed"); + ::reboot(RB_AUTOBOOT); + }; + + std::thread asyncWork(encryptWorker); + asyncWork.detach(); + return 0; } int InternalEncryption::decrypt(const std::string& password) { - //TODO + bool isVerified = false; + KeyManager::data pwData(password.begin(), password.end()); + + try { + isVerified = keyManager.verifyPassword(pwData); + } catch (runtime::Exception& e) {} + + if (!isVerified) { + return -1; + } + + KeyManager::data DEK = keyManager.getDEK(pwData); + auto decryptWorker = [DEK, this]() { + INFO("Close all processes using internal storage..."); + stopDependedSystemdServices(); + INFO("Umount internal storage..."); + try { + engine.umount(); + } catch (runtime::Exception& e) {} + INFO("Decryption started..."); + engine.decrypt(DEK); + INFO("Sync disk..."); + sync(); + INFO("Decryption completed"); + ::reboot(RB_AUTOBOOT); + }; + + std::thread asyncWork(decryptWorker); + asyncWork.detach(); + + keyManager.clearPassword(); + return 0; } int InternalEncryption::changePassword(const std::string& oldPassword, const std::string& newPassword) { - //TODO + KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end()); + KeyManager::data newPwData(newPassword.begin(), oldPassword.end()); + + bool isVerified = false; + try { + isVerified = keyManager.verifyPassword(newPwData); + } catch (runtime::Exception& e) {} + + if (!isVerified) { + return -1; + } + + keyManager.changePassword(oldPwData, newPwData); return 0; } -- 2.34.1