2 * Copyright (c) 2015 - 2019 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
17 #include <sys/mount.h>
28 #include <tzplatform_config.h>
29 #include <klay/file-user.h>
30 #include <klay/filesystem.h>
34 #include "progress-bar.h"
35 #include "rmi/common.h"
36 #include "file-footer.h"
38 #include "external-encryption.h"
45 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
46 const char *SDCARD_UI_ACTIVATOR_PATH = "/run/ode-booting-with-encrypted-sdcard";
50 INFO(SINK, "Launching SD card password popup.");
52 runtime::File act(SDCARD_UI_ACTIVATOR_PATH);
54 act.create(O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // 644
55 } catch (const runtime::Exception& e) {
56 ERROR(SINK, "Opening sdcard UI activator (" << SDCARD_UI_ACTIVATOR_PATH << ") failed: " <<
64 char *cryptoState = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
65 if (cryptoState == NULL)
68 bool encrypted = (strcmp(cryptoState, "encrypted") == 0);
74 * Introspection data for the exported object
77 * dbus-send --system --type=method_call --print-reply --dest=org.tizen.ode
78 * /org/tizen/ode/ExternalEncryption org.freedesktop.DBus.Introspectable.Introspect
80 const gchar introspectionXml[] =
82 " <interface name='org.tizen.ode.ExternalEncryption'>"
83 " <method name='UpdateCardStatus'>"
84 " <arg type='s' name='mountpoint' direction='in'/>"
85 " <arg type='i' name='status' direction='in'/>"
90 void dbusMethodCall(GDBusConnection *,
93 const gchar *interface,
96 GDBusMethodInvocation *invocation,
99 DEBUG(SINK, "dbusMethodCall sender: " << sender << ", object: " << object << ", interface: " <<
100 interface << ", method: " << method);
102 static_cast<ExternalEncryptionServer*>(user_data)->dbusMethodCall(method, params, invocation);
105 unsigned int getOptions()
107 unsigned int result = 0;
111 ::vconf_get_bool(VCONFKEY_SDE_EXCLUDE_MEDIAFILE, &value);
113 result |= ExternalEncryption::Option::OnlyNewFile;
117 ::vconf_get_bool(VCONFKEY_SDE_ENCRYPT_NEWFILE, &value);
119 result |= ExternalEncryption::Option::ExceptForMediaFile;
125 void setOptions(unsigned int options)
129 if (options & ExternalEncryption::Option::OnlyNewFile) {
134 ::vconf_set_bool(VCONFKEY_SDE_EXCLUDE_MEDIAFILE, value);
136 if (options & ExternalEncryption::Option::ExceptForMediaFile) {
141 ::vconf_set_bool(VCONFKEY_SDE_ENCRYPT_NEWFILE, value);
146 ExternalEncryptionServer::ExternalEncryptionServer(ServerContext &srv,
151 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::setMountPassword)(std::string));
152 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::mount)());
153 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::umount)());
154 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::encrypt)(std::string, unsigned int));
155 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::decrypt)(std::string));
156 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::recovery)());
157 server.expose(this, "", (int)(ExternalEncryptionServer::isPasswordInitialized)());
158 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::initPassword)(std::string));
159 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::cleanPassword)(std::string));
160 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::changePassword)(std::string, std::string));
161 server.expose(this, PRIVILEGE_PLATFORM, (int)(ExternalEncryptionServer::verifyPassword)(std::string));
162 server.expose(this, "", (int)(ExternalEncryptionServer::getState)());
163 server.expose(this, "", (unsigned int)(ExternalEncryptionServer::getSupportedOptions)());
164 server.expose(this, "", (std::string)(ExternalEncryptionServer::getDevicePath)());
166 server.createNotification("ExternalEncryptionServer::mount");
170 ExternalEncryptionServer::~ExternalEncryptionServer()
174 int ExternalEncryptionServer::setMountPassword(const std::string& password)
176 RequestLifetime rl(server);
178 return keyServer.get(getEngine().getSource(), password, mountKey);
181 int ExternalEncryptionServer::mount()
183 RequestLifetime rl(server);
185 if (mountKey.empty()) {
186 ERROR(SINK, "You need to call set_mount_password() first.");
187 return error::NoData;
190 BinaryData key = mountKey;
193 if (getStateInternal() != State::Encrypted) {
194 ERROR(SINK, "Cannot mount, SD card's state incorrect.");
195 return error::NoSuchDevice;
198 auto& engine = getEngine();
199 if (engine.isMounted()) {
200 INFO(SINK, "SD card already mounted.");
204 INFO(SINK, "Mounting external storage.");
206 engine.mount(key, getOptions());
207 } catch (runtime::Exception &e) {
208 ERROR(SINK, "Failed to mount: " + std::string(e.what()));
209 return error::Unknown;
212 server.notify("ExternalEncryptionServer::mount");
217 int ExternalEncryptionServer::umount()
219 RequestLifetime rl(server);
221 if (getStateInternal() != State::Encrypted) {
222 ERROR(SINK, "Cannot umount, SD card's state incorrect.");
223 return error::NoSuchDevice;
226 auto& engine = getEngine();
227 if (!engine.isMounted()) {
228 INFO(SINK, "SD card already umounted.");
232 INFO(SINK, "Closing all applications using external storage.");
233 killDependentApplications(engine.getDestination());
235 INFO(SINK, "Umounting external storage.");
238 } catch (runtime::Exception &e) {
239 ERROR(SINK, "Failed to umount: " + std::string(e.what()));
240 return error::Unknown;
246 int ExternalEncryptionServer::encrypt(const std::string &password, unsigned int options)
248 RequestLifetime rl(server);
250 if (getStateInternal() != State::Unencrypted) {
251 INFO(SINK, "Cannot encrypt, SD card's state incorrect.");
252 return error::NoSuchDevice;
255 BinaryData masterKey;
256 int ret = keyServer.get(getEngine().getSource(), password, masterKey);
257 if (ret != error::None)
260 auto encryptWorker = [masterKey, options, this](RequestLifetime&& rl) {
262 auto& engine = getEngine();
264 INFO(SINK, "Closing all applications using external storage.");
265 killDependentApplications(engine.getDestination());
267 INFO(SINK, "Encryption started.");
268 engine.encrypt(masterKey, options);
269 setOptions(options & engine.getSupportedOptions());
271 INFO(SINK, "Encryption completed.");
272 ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "encrypted");
273 server.notify("ExternalEncryptionServer::mount");
275 INFO(SINK, "Syncing disk.");
277 } catch (runtime::Exception &e) {
278 ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "error_partially_encrypted");
279 ERROR(SINK, "Encryption failed: " + std::string(e.what()));
283 std::thread asyncWork(encryptWorker, std::move(rl));
289 int ExternalEncryptionServer::decrypt(const std::string &password)
291 RequestLifetime rl(server);
293 if (getStateInternal() != State::Encrypted) {
294 ERROR(SINK, "Cannot decrypt, SD card's state incorrect.");
295 return error::NoSuchDevice;
298 BinaryData masterKey;
299 int ret = keyServer.get(getEngine().getSource(), password, masterKey);
300 if (ret != error::None)
303 auto decryptWorker = [masterKey, this](RequestLifetime&& rl) {
305 auto& engine = getEngine();
307 INFO(SINK, "Closing all applications using external storage.");
308 killDependentApplications(engine.getDestination());
310 INFO(SINK, "Umounting external storage.");
315 } catch (runtime::Exception &e) {
316 killDependentApplications(engine.getDestination());
320 INFO(SINK, "Decryption started.");
321 ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "error_partially_decrypted");
322 engine.decrypt(masterKey, getOptions());
324 INFO(SINK, "Decryption completed.");
325 ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "unencrypted");
327 INFO(SINK, "Syncing disk.");
329 } catch (runtime::Exception &e) {
330 ERROR(SINK, "Decryption failed: " + std::string(e.what()));
334 std::thread asyncWork(decryptWorker, std::move(rl));
340 int ExternalEncryptionServer::recovery()
342 RequestLifetime rl(server);
344 if (getStateInternal() == State::Unencrypted) {
345 return error::NoSuchDevice;
348 auto& engine = getEngine();
349 for (runtime::DirectoryIterator iter(engine.getSource()), end;
350 iter != end; ++iter) {
354 keyServer.removePassword(engine.getSource());
355 ::vconf_set_str(VCONFKEY_SDE_CRYPTO_STATE, "unencrypted");
360 int ExternalEncryptionServer::isPasswordInitialized()
362 return keyServer.isInitialized(getEngine().getSource());
365 int ExternalEncryptionServer::initPassword(const std::string& password)
367 return keyServer.init(getEngine().getSource(), password, Key::DEFAULT_256BIT);
370 int ExternalEncryptionServer::cleanPassword(const std::string& password)
372 return keyServer.remove(getEngine().getSource(), password);
375 int ExternalEncryptionServer::changePassword(const std::string &oldPassword,
376 const std::string &newPassword)
378 return keyServer.changePassword(getEngine().getSource(), oldPassword, newPassword);
381 int ExternalEncryptionServer::verifyPassword(const std::string& password)
383 return keyServer.verifyPassword(getEngine().getSource(), password);
386 int ExternalEncryptionServer::getState()
388 RequestLifetime rl(server);
390 return getStateInternal();
393 unsigned int ExternalEncryptionServer::getSupportedOptions()
395 RequestLifetime rl(server);
397 return getEngine().getSupportedOptions();
400 std::string ExternalEncryptionServer::getDevicePath() const
402 RequestLifetime rl(server);
404 return getEngine().getSource();
407 void ExternalEncryptionServer::dbusRegisterObject(GDBusConnection *connection)
410 GDBusNodeInfo *dbusIntrospectionData = g_dbus_node_info_new_for_xml(introspectionXml, &err);
411 if (dbusIntrospectionData == NULL) {
412 ERROR(SINK, "Dbus introspection data creation failed: " << err->message);
416 const GDBusInterfaceVTable interfaceVtable =
425 * dbus-send --system --type=method_call --print-reply --dest=org.tizen.ode
426 * /org/tizen/ode/ExternalEncryption org.tizen.ode.ExternalEncryption.UpdateCardStatus
427 * string:"/media/SDCardA1" int32:1
429 guint registrationId = g_dbus_connection_register_object(connection,
430 "/org/tizen/ode/ExternalEncryption",
431 dbusIntrospectionData->interfaces[0],
436 if (registrationId == 0)
437 ERROR(SINK, "Dbus object registration failed: " << err->message);
439 g_dbus_node_info_unref(dbusIntrospectionData);
442 void ExternalEncryptionServer::dbusMethodCall(const gchar *,
444 GDBusMethodInvocation *invocation)
446 RequestLifetime rl(server);
448 const gchar *mountPoint;
451 g_variant_get(params, "(&si)", &mountPoint, &cardStatus);
453 switch (cardStatus) {
455 DEBUG(SINK, "Card unmounted " << mountPoint);
457 int ret = ::vconf_unset(VCONFKEY_SDE_MOUNT_POINT);
459 ERROR(SINK, "vconf_set_str() failed with " << ret);
465 DEBUG(SINK, "Card mounted " << mountPoint);
467 int ret = ::vconf_set_str(VCONFKEY_SDE_MOUNT_POINT, mountPoint);
469 ERROR(SINK, "vconf_set_str() failed with " << ret);
470 else if (isEncrypted())
475 ERROR(SINK, "Unsupported card status: " << cardStatus);
476 g_dbus_method_invocation_return_error(invocation,
478 G_DBUS_ERROR_INVALID_ARGS,
479 "Unsupported card status");
482 g_dbus_method_invocation_return_value(invocation, NULL);
485 int ExternalEncryptionServer::getStateInternal() const
487 char *value = ::vconf_get_str(VCONFKEY_SDE_CRYPTO_STATE);
489 throw runtime::Exception("Failed to get vconf value.");
492 std::string valueStr(value);
495 if (valueStr == "encrypted")
496 return State::Encrypted;
497 else if (valueStr == "unencrypted")
498 return State::Unencrypted;
499 else if (valueStr == "error_partially_encrypted" || valueStr == "error_partially_decrypted")
500 return State::Corrupted;
502 return State::NotSupported;
505 EXTERNAL_ENGINE& ExternalEncryptionServer::getEngine() const
508 char *tmp = ::vconf_get_str(VCONFKEY_SDE_MOUNT_POINT);
511 ERROR(SINK, "Sd card not mounted");
512 throw runtime::Exception("Sd card not mounted");
515 std::string mountPoint(tmp);
518 char *realMountPoint = ::realpath(mountPoint.c_str(), NULL);
519 if (realMountPoint == NULL) {
520 ERROR(SINK, "Failed to resolve mountpoint.");
521 throw runtime::Exception("Failed to resolve mountpoint.");
523 mountPoint.assign(realMountPoint);
524 free(realMountPoint);
526 engine.reset(new EXTERNAL_ENGINE(mountPoint,
528 ProgressBar(VCONFKEY_SDE_ENCRYPT_PROGRESS)));