Fix static analysis issue
[platform/core/security/ode.git] / server / internal-encryption.cpp
index 7e4ce24..58edac5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015-2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015-2023 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -58,6 +58,7 @@ namespace ode {
 namespace {
 
 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
+const mode_t MODE_0640 = S_IRUSR | S_IWUSR | S_IRGRP;
 const std::string ODE_OBJECT_PATH = "/Org/Tizen/OnDeviceEncryption";
 const std::string ODE_INTERFACE_EVENT = "org.tizen.OnDeviceEncryption.Event";
 const std::string ODE_SIGNAL_NAME = "unmount";
@@ -224,7 +225,7 @@ void stopSystemdUnits()
                }
        }
 
-       for (auto unit : preprocessUnits) {
+       for (auto &unit : preprocessUnits) {
                stopUnit(unit);
        }
 
@@ -365,7 +366,7 @@ void killProcesses(std::vector<const char*> &args)
                while ((::getline(&line, &len, fp.get())) != -1) {
                        std::string log(line);
                        log.erase(std::find_if(log.rbegin(), log.rend(),
-                                               std::ptr_fun<int, int>(std::isgraph)).base(), log.end());
+                                               [](unsigned char c){ return std::isgraph(c); }).base(), log.end());
                        WARN(SINK, log);
                }
        } catch (std::exception &e) {
@@ -434,6 +435,8 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv,
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::mount)(std::vector<unsigned char>, unsigned int));
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::umount)());
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::isMounted)());
+       server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::prepareEncryption)(unsigned int));
+       server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::prepareDecryption)());
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::encrypt)(std::string, unsigned int));
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::decrypt)(std::string));
        server.expose(this, "", (int)(InternalEncryptionServer::isPasswordInitialized)());
@@ -450,7 +453,7 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv,
 
        std::string source = findDevPath();
 
-       if (getState() == State::Encrypted) {
+       if (getStateInternal() == State::Encrypted) {
                //"error_partially_encrypted"
                if (!FileFooter::exist(source) && !UpgradeSupport::checkUpgradeFlag()) {
                        // Trigger key migration process
@@ -458,13 +461,9 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv,
                }
        }
 
-       engine.reset(new INTERNAL_ENGINE(
-               source, INTERNAL_PATH,
-               ProgressBar([](int v) {
-                       ::vconf_set_str(VCONFKEY_ODE_ENCRYPT_PROGRESS,
-                                                       std::to_string(v).c_str());
-               })
-       ));
+       engine.reset(new INTERNAL_ENGINE(source,
+                                        INTERNAL_PATH,
+                                        ProgressBar(VCONFKEY_ODE_ENCRYPT_PROGRESS)));
 
        try {
                dbus::Connection &systemDBus = dbus::Connection::getSystem();
@@ -494,6 +493,8 @@ int InternalEncryptionServer::migrateMasterKey(const std::string& dev, const std
 
 int InternalEncryptionServer::setMountPassword(const std::string& password)
 {
+       RequestLifetime rl(server);
+
        const std::string& dev = engine->getSource();
 
        // check if upgrade flag exists
@@ -511,6 +512,8 @@ int InternalEncryptionServer::setMountPassword(const std::string& password)
 
 int InternalEncryptionServer::mount(const std::vector<unsigned char> &mk, unsigned int options)
 {
+       RequestLifetime rl(server);
+
        if (mountKey.empty() && mk.empty()) {
                ERROR(SINK, "You need to set master key first.");
                return error::NoData;
@@ -519,7 +522,7 @@ int InternalEncryptionServer::mount(const std::vector<unsigned char> &mk, unsign
        BinaryData key = mk.empty() ? mountKey : mk;
        mountKey.clear();
 
-       if (getState() != State::Encrypted) {
+       if (getStateInternal() != State::Encrypted) {
                ERROR(SINK, "Cannot mount, SD partition's state incorrect.");
                return error::NoSuchDevice;
        }
@@ -547,6 +550,8 @@ int InternalEncryptionServer::mount(const std::vector<unsigned char> &mk, unsign
 
 int InternalEncryptionServer::isMounted()
 {
+       RequestLifetime rl(server);
+
        int ret = 0;
        try {
                ret = engine->isMounted() ? 1 : 0;
@@ -559,7 +564,9 @@ int InternalEncryptionServer::isMounted()
 
 int InternalEncryptionServer::umount()
 {
-       if (getState() != State::Encrypted) {
+       RequestLifetime rl(server);
+
+       if (getStateInternal() != State::Encrypted) {
                ERROR(SINK, "Cannot umount, partition's state incorrect.");
                return error::NoSuchDevice;
        }
@@ -583,9 +590,62 @@ int InternalEncryptionServer::umount()
        return error::None;
 }
 
+int InternalEncryptionServer::prepareEncryption(unsigned int options)
+{
+       RequestLifetime rl(server);
+
+       if (getStateInternal() != State::Unencrypted) {
+               ERROR(SINK, "Cannot encrypt, partition's state incorrect.");
+               return error::NoSuchDevice;
+       }
+
+       try {
+               runtime::File file("/opt/etc/.odeprogress");
+               file.create(MODE_0640);
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, "Failed to create the flag file: " + std::string(e.what()));
+               return error::Unknown;
+       }
+
+       setOptions(options & engine->getSupportedOptions());
+
+       ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "prepared_encryption");
+       ::sync();
+       ::reboot(RB_AUTOBOOT);
+
+       return error::None;
+}
+
+int InternalEncryptionServer::prepareDecryption()
+{
+       RequestLifetime rl(server);
+
+       if (getStateInternal() != State::Encrypted) {
+               ERROR(SINK, "Cannot decrypt, partition's state incorrect.");
+               return error::NoSuchDevice;
+       }
+
+       try {
+               runtime::File file("/opt/etc/.odeprogress");
+               file.create(MODE_0640);
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, "Failed to create the flag file: " + std::string(e.what()));
+               return error::Unknown;
+       }
+
+       ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "prepared_decryption");
+       ::sync();
+       ::reboot(RB_AUTOBOOT);
+
+       return error::None;
+}
+
 int InternalEncryptionServer::encrypt(const std::string& password, unsigned int options)
 {
-       if (getState() != State::Unencrypted) {
+       RequestLifetime rl(server);
+
+       int state = getStateInternal();
+       if (state != State::Unencrypted && state != State::PreparedEncryption) {
                ERROR(SINK, "Cannot encrypt, partition's state incorrect.");
                return error::NoSuchDevice;
        }
@@ -595,7 +655,7 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
        if (ret != error::None)
                return ret;
 
-       auto encryptWorker = [masterKey, options, this]() {
+       auto encryptWorker = [masterKey, options, this](RequestLifetime&& rl) {
                try {
                        if (::device_power_request_lock(POWER_LOCK_DISPLAY, 0) != 0)
                                ERROR(SINK, "Failed to request to lock display");
@@ -604,23 +664,26 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
                        ::sleep(1);
 
                        runtime::File file("/opt/etc/.odeprogress");
-                       file.create(0640);
-
-                       std::string source = engine->getSource();
-                       auto mntPaths = findMountPointsByDevice(source);
-
-                       if (!mntPaths.empty()) {
-                               INFO(SINK, "Closing all processes using internal storage.");
-                               stopSystemdUnits();
-
-                               INFO(SINK, "Unmounting internal storage.");
-                               unmountInternalStorage(source);
+                       if (getStateInternal() == State::Unencrypted) {
+                               /* For backward compatibility */
+                               file.create(MODE_0640);
+                               std::string source = engine->getSource();
+                               auto mntPaths = findMountPointsByDevice(source);
+
+                               if (!mntPaths.empty()) {
+                                       INFO(SINK, "Closing all processes using internal storage.");
+                                       stopSystemdUnits();
+
+                                       INFO(SINK, "Unmounting internal storage.");
+                                       unmountInternalStorage(source);
+                               }
+                               setOptions(options & engine->getSupportedOptions());
                        }
 
                        INFO(SINK, "Encryption started.");
                        ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_encrypted");
                        try {
-                               engine->encrypt(masterKey, options);
+                               engine->encrypt(masterKey, getOptions());
                        } catch (runtime::Exception &e) {
                                ERROR(SINK, e.what());
                                if (!engine->isStarted()) {
@@ -630,7 +693,6 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
                                ::sync();
                                ::reboot(RB_AUTOBOOT);
                        }
-                       setOptions(options & getSupportedOptions());
 
                        INFO(SINK, "Encryption completed.");
                        ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "encrypted");
@@ -646,7 +708,7 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
                }
        };
 
-       std::thread asyncWork(encryptWorker);
+       std::thread asyncWork(encryptWorker, std::move(rl));
        asyncWork.detach();
 
        return error::None;
@@ -654,7 +716,10 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
 
 int InternalEncryptionServer::decrypt(const std::string& password)
 {
-       if (getState() != State::Encrypted) {
+       RequestLifetime rl(server);
+
+       int state = getStateInternal();
+       if (state != State::Encrypted && state != State::PreparedDecryption) {
                ERROR(SINK, "Cannot decrypt, partition's state incorrect.");
                return error::NoSuchDevice;
        }
@@ -673,7 +738,7 @@ int InternalEncryptionServer::decrypt(const std::string& password)
        if (ret != error::None)
                return ret;
 
-       auto decryptWorker = [masterKey, this]() {
+       auto decryptWorker = [masterKey, this](RequestLifetime&& rl) {
                try {
                        if (::device_power_request_lock(POWER_LOCK_DISPLAY, 0) != 0)
                                ERROR(SINK, "Failed to request to lock display");
@@ -682,15 +747,18 @@ int InternalEncryptionServer::decrypt(const std::string& password)
                        ::sleep(1);
 
                        runtime::File file("/opt/etc/.odeprogress");
-                       file.create(0640);
+                       if (getStateInternal() == State::Encrypted) {
+                               /* For backward compatibility */
+                               file.create(MODE_0640);
 
-                       if (engine->isMounted()) {
-                               INFO(SINK, "Closing all processes using internal storage.");
-                               stopSystemdUnits();
+                               if (engine->isMounted()) {
+                                       INFO(SINK, "Closing all processes using internal storage.");
+                                       stopSystemdUnits();
 
-                               INFO(SINK, "Umounting internal storage.");
-                               unmountInternalStorage("/dev/mapper/userdata");
-                               engine->umount();
+                                       INFO(SINK, "Unmounting internal storage.");
+                                       unmountInternalStorage("/dev/mapper/userdata");
+                                       engine->umount();
+                               }
                        }
 
                        INFO(SINK, "Decryption started.");
@@ -720,7 +788,7 @@ int InternalEncryptionServer::decrypt(const std::string& password)
                }
        };
 
-       std::thread asyncWork(decryptWorker);
+       std::thread asyncWork(decryptWorker, std::move(rl));
        asyncWork.detach();
 
        return error::None;
@@ -728,13 +796,25 @@ int InternalEncryptionServer::decrypt(const std::string& password)
 
 int InternalEncryptionServer::recovery()
 {
-       int state = getState();
+       RequestLifetime rl(server);
+
+       int state = getStateInternal();
 
        if (state == State::Unencrypted)
                return error::NoSuchDevice;
+       if (state == State::PreparedEncryption) {
+               ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "unencrypted");
+               ::sync();
+               return error::None;
+       }
+       if (state == State::PreparedDecryption) {
+               ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "encrypted");
+               ::sync();
+               return error::None;
+       }
 
        runtime::File file("/opt/.factoryreset");
-       file.create(0640);
+       file.create(MODE_0640);
 
        ::sync();
        try {
@@ -778,6 +858,27 @@ int InternalEncryptionServer::verifyPassword(const std::string& password)
 
 int InternalEncryptionServer::getState()
 {
+       RequestLifetime rl(server);
+
+       return getStateInternal();
+}
+
+unsigned int InternalEncryptionServer::getSupportedOptions()
+{
+       RequestLifetime rl(server);
+
+       return engine->getSupportedOptions();
+}
+
+std::string InternalEncryptionServer::getDevicePath() const
+{
+       RequestLifetime rl(server);
+
+       return engine->getSource();
+}
+
+int InternalEncryptionServer::getStateInternal() const
+{
        char *value = ::vconf_get_str(VCONFKEY_ODE_CRYPTO_STATE);
        if (value == NULL) {
                throw runtime::Exception("Failed to get vconf value.");
@@ -790,20 +891,14 @@ int InternalEncryptionServer::getState()
                return State::Encrypted;
        else if (valueStr == "unencrypted")
                return State::Unencrypted;
+       else if (valueStr == "prepared_encryption")
+               return State::PreparedEncryption;
+       else if (valueStr == "prepared_decryption")
+               return State::PreparedDecryption;
        else if (valueStr == "error_partially_encrypted" || valueStr == "error_partially_decrypted")
                return State::Corrupted;
 
        return State::NotSupported;
 }
 
-unsigned int InternalEncryptionServer::getSupportedOptions()
-{
-       return engine->getSupportedOptions();
-}
-
-std::string InternalEncryptionServer::getDevicePath() const
-{
-       return engine->getSource();
-}
-
 } // namespace ode