* See the License for the specific language governing permissions and
* limitations under the License
*/
+#include <unistd.h>
+#include <sys/mount.h>
+#include <sys/reboot.h>
+
#include <klay/filesystem.h>
+#include <klay/dbus/connection.h>
#include <klay/audit/logger.h>
#include "engine/dmcrypt-engine.h"
#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<std::string> dependedSystemdServices = {
+ "resourced.service",
+ "msg-server.service",
+ "mtp-responder.service",
+};
+
+void stopDependedSystemdServices()
+{
+ std::vector<std::string> 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)
{
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;
}