* See the License for the specific language governing permissions and
* limitations under the License
*/
+#include <fstream>
+#include <sstream>
+
+#include <signal.h>
+#include <unistd.h>
+#include <sys/mount.h>
+
+#include <vconf.h>
+#include <tzplatform_config.h>
+
+#include <klay/file-user.h>
#include <klay/filesystem.h>
#include <klay/audit/logger.h>
+#include "launchpad.h"
+#include "app-bundle.h"
#include "engine/ecryptfs-engine.h"
-#include "key-manager/keystore.h"
-#include "key-manager/key-generator.h"
+#include "key-manager/key-manager.h"
+#include <klay/dbus/variant.h>
+#include <klay/dbus/connection.h>
#include "rmi/external-encryption.h"
+#include "progress-bar.h"
+#include "progress-vconf-backend.h"
+
+#define EXTERNAL_STORAGE_PATH "/opt/media/SDCardA1"
+#define DEFAULT_USER "owner"
+#define EXTERNAL_STATE_VCONF_KEY VCONFKEY_SDE_CRYPTO_STATE
+#define EXTERNAL_OPTION_ONLY_NEW_FILE_VCONF_KEY VCONFKEY_SDE_ENCRYPT_NEWFILE
+#define EXTERNAL_OPTION_EXCEPT_FOR_MEDIA_FILE_VCONF_KEY VCONFKEY_SDE_EXCLUDE_MEDIAFILE
namespace ode {
-ExternalEncryption::ExternalEncryption(ODEControlContext& ctx) :
+namespace {
+
+VConfBackend vconfBackend(VCONFKEY_SDE_ENCRYPT_PROGRESS);
+ProgressBar progressBar(std::bind(&VConfBackend::update, &vconfBackend, std::placeholders::_1));
+
+EcryptfsEngine engine(EXTERNAL_STORAGE_PATH, EXTERNAL_STORAGE_PATH, progressBar);
+
+void killDependedApplications()
+{
+ for (pid_t pid : runtime::FileUser::getList(EXTERNAL_STORAGE_PATH, true)) {
+ INFO("Close process - " + std::to_string(pid));
+ ::kill(pid, SIGKILL);
+ }
+}
+
+void externalCallback(dbus::Variant parameters)
+{
+ int intparams[6];
+ char* strparams[7];
+
+ parameters.get("(issssssisibii)",
+ &intparams[0], // block type: 0 - scsi, 1 : mmc
+ &strparams[0], // devnode
+ &strparams[1], // syspath
+ &strparams[2], // usage
+ &strparams[3], // fs type
+ &strparams[4], // fs version
+ &strparams[5], // fs uuid enc
+ &intparams[1], // readonly: 0 - rw, 1 - ro
+ &strparams[6], // mount point
+ &intparams[2], // state: 0 - unmount, 1 - mount
+ &intparams[3], // primary: 0 - flase, 1 - true
+ &intparams[4], // flags: 1 - unmounted 2 - broken filesystem 4 - no filesystem 8 - not supported 16 - readonly
+ &intparams[5]); // strage id
+
+ if(intparams[2] == 0) {
+ INFO("Unmounted");
+ } else {
+ INFO("Mounted");
+ char *value = ::vconf_get_str(EXTERNAL_STATE_VCONF_KEY);
+ if (value != NULL) {
+ std::string valueStr(value);
+ free(value);
+ if (valueStr == "encrypted") {
+ try {
+ INFO("Launch SD card password popup");
+ AppBundle bundle;
+ bundle.add("viewtype", "SD_CARD_PASSWORD");
+
+ Launchpad launchpad(::tzplatform_getuid(TZ_SYS_DEFAULT_USER));
+ launchpad.launch("org.tizen.ode", bundle);
+ } catch (runtime::Exception &e) {
+ ERROR("Failed to launch SD card password popup");
+ }
+ }
+ }
+ }
+}
+
+void externalAddEventReceiver()
+{
+ dbus::Connection &systemDBus = dbus::Connection::getSystem();
+
+ systemDBus.subscribeSignal("",
+ "/Org/Tizen/System/Storage/Block/Manager",
+ "org.tizen.system.storage.BlockManager",
+ "DeviceChanged",
+ externalCallback);
+}
+
+unsigned int getOptions()
+{
+ unsigned int result = 0;
+ int value;
+
+ value = 0;
+ ::vconf_get_bool(EXTERNAL_OPTION_EXCEPT_FOR_MEDIA_FILE_VCONF_KEY, &value);
+ if (value) {
+ result |= ExternalEncryption::Option::OnlyNewFile;
+ }
+
+ value = 0;
+ ::vconf_get_bool(EXTERNAL_OPTION_ONLY_NEW_FILE_VCONF_KEY, &value);
+ if (value) {
+ result |= ExternalEncryption::Option::ExceptForMediaFile;
+ }
+
+ return result;
+}
+
+void setOptions(unsigned int options)
+{
+ bool value;
+
+ if (options & ExternalEncryption::Option::OnlyNewFile) {
+ value = true;
+ } else {
+ value = false;
+ }
+ ::vconf_set_bool(EXTERNAL_OPTION_EXCEPT_FOR_MEDIA_FILE_VCONF_KEY, value);
+
+ if (options & ExternalEncryption::Option::ExceptForMediaFile) {
+ value = true;
+ } else {
+ value = false;
+ }
+ ::vconf_set_bool(EXTERNAL_OPTION_ONLY_NEW_FILE_VCONF_KEY, value);
+}
+
+} // namsepace
+
+ExternalEncryption::ExternalEncryption(ODEControlContext &ctx) :
context(ctx)
{
context.registerParametricMethod(this, "", (int)(ExternalEncryption::mount)(std::string));
context.registerNonparametricMethod(this, "", (int)(ExternalEncryption::umount));
- context.registerParametricMethod(this, "", (int)(ExternalEncryption::encrypt)(std::string));
+ context.registerParametricMethod(this, "", (int)(ExternalEncryption::encrypt)(std::string, unsigned int));
context.registerParametricMethod(this, "", (int)(ExternalEncryption::decrypt)(std::string));
+ context.registerNonparametricMethod(this, "", (int)(ExternalEncryption::isPasswordInitialized));
+ context.registerParametricMethod(this, "", (int)(ExternalEncryption::initPassword)(std::string));
+ context.registerParametricMethod(this, "", (int)(ExternalEncryption::cleanPassword)(std::string));
context.registerParametricMethod(this, "", (int)(ExternalEncryption::changePassword)(std::string, std::string));
+ context.registerParametricMethod(this, "", (int)(ExternalEncryption::verifyPassword)(std::string));
context.registerNonparametricMethod(this, "", (int)(ExternalEncryption::getState));
-}
+ context.registerNonparametricMethod(this, "", (unsigned int)(ExternalEncryption::getSupportedOptions));
+ externalAddEventReceiver();
+}
ExternalEncryption::~ExternalEncryption()
{
}
-int ExternalEncryption::mount(const std::string& password)
+int ExternalEncryption::mount(const std::string &password)
{
- //TODO
+ if (getState() != State::Encrypted) {
+ return -1;
+ }
+
+ KeyManager::data data(password.begin(), password.end());
+ KeyManager keyManager(engine.getKeyMeta());
+
+ if (!keyManager.verifyPassword(data)) {
+ return -2;
+ }
+
+ engine.mount(keyManager.getMasterKey(data), getOptions());
return 0;
}
int ExternalEncryption::umount()
{
- //TODO
+ if (getState() != State::Encrypted) {
+ return -1;
+ }
+
+ INFO("Close all applications using external storage...");
+ killDependedApplications();
+ INFO("Umount external storage...");
+ engine.umount();
+
return 0;
}
-int ExternalEncryption::encrypt(const std::string& password)
+int ExternalEncryption::encrypt(const std::string &password, unsigned int options)
{
- //TODO
+ if (getState() != State::Unencrypted) {
+ return -1;
+ }
+
+ KeyManager::data pwData(password.begin(), password.end());
+ KeyManager keyManager(engine.getKeyMeta());
+
+ if (!keyManager.verifyPassword(pwData)) {
+ return -2;
+ }
+
+ KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
+ auto encryptWorker = [&MasterKey, options, this]() {
+ try {
+ INFO("Close all applications using external storage...");
+ killDependedApplications();
+ INFO("Encryption started...");
+ ::vconf_set_str(EXTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
+ engine.encrypt(MasterKey, options);
+ setOptions(options & getSupportedOptions());
+ INFO("Sync disk...");
+ sync();
+ INFO("Encryption completed");
+ ::vconf_set_str(EXTERNAL_STATE_VCONF_KEY, "encrypted");
+ } catch (runtime::Exception &e) {
+ ERROR("Encryption failed - " + std::string(e.what()));
+ }
+ };
+
+ std::thread asyncWork(encryptWorker);
+ asyncWork.detach();
+
+ return 0;
+}
+
+int ExternalEncryption::decrypt(const std::string &password)
+{
+ if (getState() != State::Encrypted) {
+ return -1;
+ }
+
+ KeyManager::data pwData(password.begin(), password.end());
+ KeyManager keyManager(engine.getKeyMeta());
+
+ if (!keyManager.verifyPassword(pwData)) {
+ return -2;
+ }
+
+ KeyManager::data MasterKey = keyManager.getMasterKey(pwData);
+ auto decryptWorker = [MasterKey, this]() {
+ try {
+ INFO("Close all applications using external storage...");
+ killDependedApplications();
+ INFO("Umount external storage...");
+ while (1) {
+ try {
+ engine.umount();
+ break;
+ } catch (runtime::Exception &e) {
+ killDependedApplications();
+ }
+ }
+
+ INFO("Decryption started...");
+ ::vconf_set_str(EXTERNAL_STATE_VCONF_KEY, "error_partially_encrypted");
+ engine.decrypt(MasterKey, getOptions());
+ INFO("Sync disk...");
+ sync();
+ INFO("Decryption completed");
+ ::vconf_set_str(EXTERNAL_STATE_VCONF_KEY, "unencrypted");
+ } catch (runtime::Exception &e) {
+ ERROR("Decryption failed - " + std::string(e.what()));
+ }
+ };
+
+ std::thread asyncWork(decryptWorker);
+ asyncWork.detach();
+
return 0;
}
-int ExternalEncryption::decrypt(const std::string& password)
+int ExternalEncryption::isPasswordInitialized()
{
- //TODO
+ if (engine.isKeyMetaSet()) {
+ return 1;
+ }
return 0;
}
-int ExternalEncryption::changePassword(const std::string& oldPassword,
- const std::string& newPassword)
+int ExternalEncryption::initPassword(const std::string& password)
{
- //TODO
+ KeyManager::data pwData(password.begin(), password.end());
+ KeyManager keyManager;
+
+ keyManager.initPassword(pwData);
+ engine.setKeyMeta(keyManager.serialize());
+ return 0;
+}
+
+int ExternalEncryption::cleanPassword(const std::string& password)
+{
+ KeyManager::data pwData(password.begin(), password.end());
+ KeyManager keyManager(engine.getKeyMeta());
+
+ if (!keyManager.verifyPassword(pwData)) {
+ return -2;
+ }
+
+ engine.clearKeyMeta();
+ return 0;
+}
+
+int ExternalEncryption::changePassword(const std::string &oldPassword,
+ const std::string &newPassword)
+{
+ KeyManager::data oldPwData(oldPassword.begin(), oldPassword.end());
+ KeyManager::data newPwData(newPassword.begin(), newPassword.end());
+ KeyManager keyManager(engine.getKeyMeta());
+
+ if (!keyManager.verifyPassword(oldPwData)) {
+ return -2;
+ }
+
+ keyManager.changePassword(oldPwData, newPwData);
+ engine.setKeyMeta(keyManager.serialize());
+
+ return 0;
+}
+
+int ExternalEncryption::verifyPassword(const std::string& password)
+{
+ KeyManager::data pwData(password.begin(), password.end());
+ KeyManager keyManager(engine.getKeyMeta());
+
+ if (keyManager.verifyPassword(pwData)) {
+ return 1;
+ }
return 0;
}
int ExternalEncryption::getState()
{
- //TODO
+ char *value = ::vconf_get_str(EXTERNAL_STATE_VCONF_KEY);
+ if (value == NULL) {
+ throw runtime::Exception("Failed to get vconf value");
+ }
+
+ std::string valueStr(value);
+ free(value);
+
+ if (valueStr == "encrypted") {
+ return State::Encrypted;
+ } else if (valueStr == "unencrypted") {
+ return State::Unencrypted;
+ } else {
+ return State::Corrupted;
+ }
+
return 0;
}
+unsigned int ExternalEncryption::getSupportedOptions()
+{
+ return engine.getSupportedOptions();
+}
+
} // namespace ode