Skip to content

Commit

Permalink
Core: Add support for LUKS encryption.
Browse files Browse the repository at this point in the history
  • Loading branch information
xyakimo1 committed Dec 17, 2024
1 parent ced0a05 commit a91e049
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 0 deletions.
13 changes: 13 additions & 0 deletions data/org.freedesktop.UDisks2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2360,6 +2360,19 @@
<arg name="options" direction="in" type="a{sv}"/>
</method>

<!--
Encrypt:
@passphrase: Future passphrase of the LUKS2 device.
@options: Options. TODO
@since: 2.11.0
Encrypts a block device to the LUKS2 format.
-->
<method name="Encrypt">
<arg name="passphrase" direction="in" type="s"/>
<arg name="options" direction="in" type="a{sv}"/>
</method>

</interface>

<!-- ********************************************************************** -->
Expand Down
29 changes: 29 additions & 0 deletions src/tests/dbus-tests/test_50_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,35 @@ def test_rescan(self):

disk.Rescan(self.no_options, dbus_interface=self.iface_prefix + '.Block')

def test_encrypt(self):
disk = self.vdevs[0]
device = self.get_device(disk)
self.assertIsNotNone(device)

d = dbus.Dictionary(signature='sv')
d['passphrase'] = "shouldnotseeme"
d['key-size'] = dbus.UInt32(256)
d['cipher'] = "aes"
d['cipher-mode'] = "cbc-essiv:sha256"
d['resilience'] = "datashift" # required, otherwise won't work
d['hash'] = "sha256"
d['max-hotzone-size'] = dbus.UInt64(0)
d['sector-size'] = dbus.UInt32(512)
d['new-volume_key'] = True

device.Encrypt(self.LUKS_PASSPHRASE, d, dbus_interface=self.iface_prefix + '.Block')

# verify that device now has the .Encrypted interface
device = self.get_device(disk)
self.assertHasIface(device, "org.freedesktop.UDisks2.Encrypted")

# verify that the newly encrypted device can be unlocked
luks_obj = device.Unlock("shouldnotseeme", self.no_options,
dbus_interface=self.iface_prefix + '.Encrypted')
self.assertIsNotNone(luks_obj)
ret, _ = self.run_command("ls /dev/mapper/luks*")
self.assertEqual(ret, 0)


class UdisksBlockRemovableTest(udiskstestcase.UdisksTestCase):
'''Extra block device tests over a scsi_debug removable device'''
Expand Down
124 changes: 124 additions & 0 deletions src/udiskslinuxblock.c
Original file line number Diff line number Diff line change
Expand Up @@ -4308,6 +4308,129 @@ handle_restore_encrypted_header (UDisksBlock *encrypted,

/* ---------------------------------------------------------------------------------------------------- */

/* runs in thread dedicated to handling method call */
static gboolean
handle_encrypt (UDisksBlock *block,
GDBusMethodInvocation *invocation,
const gchar *passphrase,
GVariant *options)
{
UDisksObject *object = NULL;
UDisksDaemon *daemon;
UDisksState *state = NULL;
uid_t caller_uid;
GError *error = NULL;
UDisksBaseJob *job = NULL;

const gchar *device;
BDCryptoKeyslotContext *context = NULL;
guint32 key_size;
gchar *cipher;
gchar *cipher_mode;
gchar *resilience;
gchar *hash;
guint64 max_hotzone_size;
guint32 sector_size;
gboolean new_volume_key;
gboolean offline = TRUE;
// gchar *pbkdf_type;
// BDCryptoLUKSPBKDF *pbkdf = NULL;
BDCryptoLUKSReencryptParams *params = NULL;

object = udisks_daemon_util_dup_object (block, &error);
if (object == NULL)
{
g_dbus_method_invocation_return_gerror (invocation, error);
goto out;
}

daemon = udisks_linux_block_object_get_daemon (UDISKS_LINUX_BLOCK_OBJECT (object));
state = udisks_daemon_get_state (daemon);

udisks_linux_block_object_lock_for_cleanup (UDISKS_LINUX_BLOCK_OBJECT (object));
udisks_state_check_block (state, udisks_linux_block_object_get_device_number (UDISKS_LINUX_BLOCK_OBJECT (object)));

if (!udisks_daemon_util_get_caller_uid_sync (daemon, invocation, NULL /* GCancellable */, &caller_uid, &error))
{
g_dbus_method_invocation_return_gerror (invocation, error);
goto out;
}

job = udisks_daemon_launch_simple_job (daemon,
UDISKS_OBJECT (object),
"block-encrypt",
caller_uid,
NULL);
if (job == NULL)
{
g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
"Failed to create a job object");
goto out;
}

udisks_linux_block_encrypted_lock (block);
// do stuff here
device = udisks_block_get_device (block);

context = bd_crypto_keyslot_context_new_passphrase ((const guint8 *) passphrase,
strlen(passphrase),
&error);
if (!context)
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
"Error encrypting block device %s (ctx): %s",
device,
error->message);
udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), FALSE, error->message);
udisks_linux_block_encrypted_unlock (block);
goto out;
}

g_variant_lookup (options, "key-size", "u", &key_size);
g_variant_lookup (options, "cipher", "&s", &cipher);
g_variant_lookup (options, "cipher-mode", "&s", &cipher_mode);
g_variant_lookup (options, "resilience", "&s", &resilience);
g_variant_lookup (options, "hash", "&s", &hash);
g_variant_lookup (options, "max-hotzone-size", "u", &max_hotzone_size);
g_variant_lookup (options, "sector-size", "u", &sector_size);
g_variant_lookup (options, "new-volume_key", "b", &new_volume_key);
// `offline` is already determined

params = bd_crypto_luks_reencrypt_params_new (key_size, cipher, cipher_mode, resilience, hash, max_hotzone_size, sector_size, new_volume_key, offline, NULL);

if (! bd_crypto_luks_encrypt (device, params, context, NULL /* prog_func -- TODO */, &error))
{
g_dbus_method_invocation_return_error (invocation,
UDISKS_ERROR,
UDISKS_ERROR_FAILED,
"Error encrypting block device %s (enc): %s",
device,
error->message);
udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), FALSE, error->message);
udisks_linux_block_encrypted_unlock (block);
goto out;
}

//
udisks_linux_block_encrypted_unlock (block);

udisks_block_complete_encrypt (block, invocation);
udisks_simple_job_complete (UDISKS_SIMPLE_JOB (job), TRUE, NULL);

out:
if (object != NULL)
udisks_linux_block_object_release_cleanup_lock (UDISKS_LINUX_BLOCK_OBJECT (object));
if (state != NULL)
udisks_state_check (state);
g_clear_object (&object);
g_clear_error (&error);
return TRUE; /* returning TRUE means that we handled the method invocation */
}

/* ---------------------------------------------------------------------------------------------------- */

static void
block_iface_init (UDisksBlockIface *iface)
{
Expand All @@ -4322,4 +4445,5 @@ block_iface_init (UDisksBlockIface *iface)
iface->handle_open_device = handle_open_device;
iface->handle_rescan = handle_rescan;
iface->handle_restore_encrypted_header = handle_restore_encrypted_header;
iface->handle_encrypt = handle_encrypt;
}
1 change: 1 addition & 0 deletions udisks/udisksclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -2738,6 +2738,7 @@ udisks_client_get_job_description_from_operation (const gchar *operation)
g_hash_table_insert (hash, (gpointer) "encrypted-header-backup", (gpointer) C_("job", "Backing Up Header of an Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "encrypted-reencrypt", (gpointer) C_("job", "Reencrypting an Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "block-restore-encrypted-header", (gpointer) C_("job", "Restoring Header of an Encrypted Device"));
g_hash_table_insert (hash, (gpointer) "block-encrypt", (gpointer) C_("job", "Encrypting a Block Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-start", (gpointer) C_("job", "Starting Swap Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-stop", (gpointer) C_("job", "Stopping Swap Device"));
g_hash_table_insert (hash, (gpointer) "swapspace-modify", (gpointer) C_("job", "Modifying Swap Device"));
Expand Down

0 comments on commit a91e049

Please sign in to comment.