[gnome-disk-utility] Add TrueCrypt/VeraCrypt support
- From: Kai Lüke <kailueke src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] Add TrueCrypt/VeraCrypt support
- Date: Fri, 25 May 2018 07:10:50 +0000 (UTC)
commit 30422ec7cc0e86e9255aedaffe697d33a045d9d8
Author: segfault <segfault riseup net>
Date: Tue Oct 10 02:33:15 2017 +0200
Add TrueCrypt/VeraCrypt support
This is a combination of 4 commits:
- Disable "Encryption Options" for non-LUKS devices
- Disable "Change Passphrase" for non-LUKS devices
- Rename volume-content-luks to volume-content-crypto
- Add TCRYPT option widgets to the unlock dialog
This extends the unlock dialog by widgets which allow specifying the
parameters supported by TrueCrypt and VeraCrypt volumes. This includes:
- Whether the volume to be unlocked is hidden.
- Whether the volume to be unlocked is a system partition.
Note: TrueCrypt and VeraCrypt only support encrypting Windows system
partitions [1], so the label for this option is "Windows system".
- Whether to use a PIM [2].
- Whether to use one or multiple keyfiles. In the beginning there is
only one button to choose a single keyfile. When a keyfile is chosen,
another button appears below to allow selecting another keyfile, and
so on.
Since TCRYPT volumes cannot be reliably detected as such, a label is
displayed at the top of the unlock dialog to indicate to the user that
this volume might not actually be encrypted.
[1] https://www.veracrypt.fr/en/System%20Encryption.html
[2] https://www.veracrypt.fr/en/Header%20Key%20Derivation.html
src/disks/gduunlockdialog.c | 179 +++++++++++++++++++++++++++++++++--
src/disks/gduwindow.c | 8 +-
src/disks/ui/unlock-device-dialog.ui | 144 +++++++++++++++++++++++++++-
3 files changed, 316 insertions(+), 15 deletions(-)
---
diff --git a/src/disks/gduunlockdialog.c b/src/disks/gduunlockdialog.c
index bbb34b5e..71af48e7 100644
--- a/src/disks/gduunlockdialog.c
+++ b/src/disks/gduunlockdialog.c
@@ -11,6 +11,8 @@
#include <glib/gi18n.h>
#include <libsecret/secret.h>
+#include <stdlib.h>
+#include <errno.h>
#include "gduapplication.h"
#include "gduwindow.h"
@@ -35,16 +37,28 @@ typedef struct
UDisksObject *object;
UDisksBlock *block;
UDisksEncrypted *encrypted;
+ gchar* type;
GduWindow *window;
GtkBuilder *builder;
GtkWidget *dialog;
+ GtkWidget *unlock_button;
GtkWidget *infobar_vbox;
- GtkWidget *entry;
+ GtkWidget *passphrase_entry;
GtkWidget *show_passphrase_check_button;
+ GtkWidget *tcrypt_hidden_check_button;
+ GtkWidget *tcrypt_system_check_button;
+ GtkWidget *pim_entry;
+
+ GList *tcrypt_keyfile_button_list;
gchar *passphrase;
+ GVariant *keyfiles;
+ guint num_keyfiles;
+ guint pim;
+ gboolean hidden_volume;
+ gboolean system_volume;
} DialogData;
static void
@@ -62,10 +76,57 @@ dialog_data_free (DialogData *data)
if (data->builder != NULL)
g_object_unref (data->builder);
+ if (g_strcmp0 (data->type, "crypto_TCRYPT") == 0 || g_strcmp0 (data->type, "crypto_unknown") == 0)
+ // The elements are already freed by the builder / parent widget
+ g_list_free (data->tcrypt_keyfile_button_list);
+
+ g_free (data->type);
g_free (data->passphrase);
g_free (data);
}
+static void
+update_unlock_button_sensitivity (GObject *object,
+ gpointer user_data)
+{
+ DialogData *data = user_data;
+ gboolean password_entered = gtk_entry_get_text_length (GTK_ENTRY (data->passphrase_entry)) > 0;
+ gboolean keyfile_chosen = (data->tcrypt_keyfile_button_list != NULL &&
+ g_list_length (data->tcrypt_keyfile_button_list) > 1);
+
+ gtk_widget_set_sensitive (data->unlock_button, password_entered || keyfile_chosen);
+}
+
+static void
+on_tcrypt_keyfile_set (GObject *object,
+ gpointer user_data)
+{
+ DialogData *data = user_data;
+ GtkWidget *button;
+ GtkWidget *sibling;
+ GtkGrid *grid;
+ GList *list;
+
+ grid = GTK_GRID (gtk_builder_get_object (data->builder, "unlock-device-grid"));
+
+ button = gtk_file_chooser_button_new (_("Select a Keyfile"), GTK_FILE_CHOOSER_ACTION_OPEN);
+
+ sibling = NULL;
+ for (list = data->tcrypt_keyfile_button_list; list != NULL; list = list->next)
+ sibling = (GTK_WIDGET (list->data));
+
+ gtk_grid_attach_next_to (grid, button, sibling, GTK_POS_BOTTOM, 1, 1);
+ gtk_widget_show (button);
+
+ data->tcrypt_keyfile_button_list = g_list_append (data->tcrypt_keyfile_button_list, button);
+ g_signal_connect (button, "file-set", G_CALLBACK (on_tcrypt_keyfile_set), data);
+
+ // Don't call this function again for this instance
+ g_signal_handlers_disconnect_by_func (object, on_tcrypt_keyfile_set, user_data);
+
+ update_unlock_button_sensitivity (object, user_data);
+}
+
/* ---------------------------------------------------------------------------------------------------- */
static void
@@ -83,7 +144,7 @@ unlock_cb (UDisksEncrypted *encrypted,
&error))
{
gdu_utils_show_error (GTK_WINDOW (data->window),
- _("Error unlocking encrypted device"),
+ _("Error unlocking device"),
error);
g_error_free (error);
}
@@ -93,9 +154,20 @@ unlock_cb (UDisksEncrypted *encrypted,
static void
do_unlock (DialogData *data)
{
+ GVariantBuilder options_builder;
+ g_variant_builder_init (&options_builder, G_VARIANT_TYPE_VARDICT);
+ if (data->hidden_volume)
+ g_variant_builder_add (&options_builder, "{sv}", "hidden", g_variant_new_boolean (TRUE));
+ if (data->system_volume)
+ g_variant_builder_add (&options_builder, "{sv}", "system", g_variant_new_boolean (TRUE));
+ if (data->pim != 0)
+ g_variant_builder_add (&options_builder, "{sv}", "pim", g_variant_new_uint32 (data->pim));
+ if (data->num_keyfiles != 0)
+ g_variant_builder_add (&options_builder, "{sv}", "keyfiles", data->keyfiles);
+
udisks_encrypted_call_unlock (data->encrypted,
data->passphrase,
- g_variant_new ("a{sv}", NULL), /* options */
+ g_variant_builder_end (&options_builder),
NULL, /* cancellable */
(GAsyncReadyCallback) unlock_cb,
data);
@@ -105,15 +177,61 @@ static void
show_dialog (DialogData *data)
{
gint response;
+ gchar *err;
+ GError *error;
+ GVariantBuilder *keyfiles_builder;
+ GList *list;
+ const char* filename;
+ const char* text_pim;
+ guint64 tmp_pim;
gtk_widget_show_all (data->dialog);
- gtk_widget_grab_focus (data->entry);
+ gtk_widget_grab_focus (data->passphrase_entry);
response = gtk_dialog_run (GTK_DIALOG (data->dialog));
if (response == GTK_RESPONSE_OK)
{
gtk_widget_hide (data->dialog);
- data->passphrase = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->entry)));
+ data->passphrase = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->passphrase_entry)));
+
+ if (g_strcmp0 (data->type, "crypto_TCRYPT") == 0 || g_strcmp0 (data->type, "crypto_unknown") == 0)
+ {
+ data->hidden_volume = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(data->tcrypt_hidden_check_button));
+ data->system_volume = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(data->tcrypt_system_check_button));
+
+ // Add keyfiles
+ data->num_keyfiles = 0;
+ keyfiles_builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
+ for (list = data->tcrypt_keyfile_button_list; list != NULL; list = list->next)
+ {
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (list->data));
+ if (filename == NULL)
+ continue;
+ g_variant_builder_add (keyfiles_builder, "s", filename);
+ data->num_keyfiles += 1;
+ }
+ data->keyfiles = g_variant_new ("as", keyfiles_builder);
+ g_variant_builder_unref (keyfiles_builder);
+
+ text_pim = gtk_entry_get_text (GTK_ENTRY (data->pim_entry));
+ if (text_pim && strlen (text_pim) > 0)
+ {
+ errno = 0;
+ tmp_pim = strtoul ( text_pim, &err, 10);
+ if (*err || errno || tmp_pim <= 0 || tmp_pim > G_MAXUINT32)
+ {
+ error = g_error_new (G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+ _("Invalid PIM"));
+ gdu_utils_show_error (GTK_WINDOW(data->window),
+ _("Error unlocking device"),
+ error);
+ g_error_free (error);
+ dialog_data_free (data);
+ return;
+ }
+ data->pim = tmp_pim;
+ }
+ }
do_unlock (data);
}
else
@@ -143,7 +261,7 @@ luks_find_passphrase_cb (GObject *source,
_("The encryption passphrase was retrieved from the keyring"),
NULL);
gtk_box_pack_start (GTK_BOX (data->infobar_vbox), infobar, TRUE, TRUE, 0);
- gtk_entry_set_text (GTK_ENTRY (data->entry), passphrase);
+ gtk_entry_set_text (GTK_ENTRY (data->passphrase_entry), passphrase);
}
else
{
@@ -166,24 +284,65 @@ gdu_unlock_dialog_show (GduWindow *window,
data->block = udisks_object_peek_block (object);
data->encrypted = udisks_object_peek_encrypted (object);
data->window = g_object_ref (window);
-
+ data->type = udisks_block_dup_id_type (data->block);
data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
"unlock-device-dialog.ui",
"unlock-device-dialog",
&data->builder));
+ data->unlock_button = GTK_WIDGET (gtk_builder_get_object (data->builder, "unlock-device-unlock-button"));
data->infobar_vbox = GTK_WIDGET (gtk_builder_get_object (data->builder, "infobar-vbox"));
- data->entry = GTK_WIDGET (gtk_builder_get_object (data->builder, "unlock-device-passphrase-entry"));
+ data->passphrase_entry = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-passphrase-entry"));
data->show_passphrase_check_button = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-show-passphrase-check-button"));
+ // Add TCRYPT options if the device is (possibly) a TCRYPT volume
+ if (g_strcmp0 (data->type, "crypto_TCRYPT") == 0 || g_strcmp0 (data->type, "crypto_unknown") == 0)
+ {
+ GtkWidget *volume_type_label = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-volume-type-label"));
+ GtkWidget *keyfiles_label = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-keyfiles-label"));
+ GtkWidget *pim_label = GTK_WIDGET (gtk_builder_get_object (data->builder, "unlock-device-pim-label"));
+ GtkWidget *button = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-tcrypt-keyfile-chooser-button"));
+
+ gtk_window_set_title (GTK_WINDOW (data->dialog), _("Set options to unlock"));
+
+ data->tcrypt_hidden_check_button = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-tcrypt-hidden-check-button"));
+ data->tcrypt_system_check_button = GTK_WIDGET (gtk_builder_get_object (data->builder,
"unlock-device-tcrypt-system-check-button"));
+ data->pim_entry = GTK_WIDGET (gtk_builder_get_object (data->builder, "unlock-device-pim-entry"));
+ data->tcrypt_keyfile_button_list = NULL;
+ data->tcrypt_keyfile_button_list = g_list_append (data->tcrypt_keyfile_button_list, button);
+
+ gtk_widget_set_visible (volume_type_label, TRUE);
+ gtk_widget_set_visible (pim_label, TRUE);
+ gtk_widget_set_visible (keyfiles_label, TRUE);
+ gtk_widget_set_visible (button, TRUE);
+ gtk_widget_set_visible (data->tcrypt_hidden_check_button, TRUE);
+ gtk_widget_set_visible (data->tcrypt_system_check_button, TRUE);
+ gtk_widget_set_visible (data->pim_entry, TRUE);
+
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->tcrypt_hidden_check_button), FALSE);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->tcrypt_system_check_button), FALSE);
+ gtk_entry_set_text (GTK_ENTRY (data->pim_entry), "");
+
+ g_signal_connect (button, "file-set", G_CALLBACK (on_tcrypt_keyfile_set), data);
+
+ if (g_strcmp0 (data->type, "crypto_unknown") == 0)
+ {
+ GtkWidget *unknown_crypto_label;
+ unknown_crypto_label = GTK_WIDGET (gtk_builder_get_object (data->builder, "unknown-crypto-label"));
+ gtk_widget_set_visible (unknown_crypto_label, TRUE);
+ gtk_widget_set_no_show_all (unknown_crypto_label, FALSE);
+ }
+ }
+
gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (data->window));
gtk_dialog_set_default_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->show_passphrase_check_button), FALSE);
- gtk_entry_set_text (GTK_ENTRY (data->entry), "");
+ gtk_entry_set_text (GTK_ENTRY (data->passphrase_entry), "");
+ g_signal_connect (data->passphrase_entry, "changed", G_CALLBACK (update_unlock_button_sensitivity), data);
g_object_bind_property (data->show_passphrase_check_button,
"active",
- data->entry,
+ data->passphrase_entry,
"visibility",
G_BINDING_SYNC_CREATE);
diff --git a/src/disks/gduwindow.c b/src/disks/gduwindow.c
index e8aa6c52..5fe8df8c 100644
--- a/src/disks/gduwindow.c
+++ b/src/disks/gduwindow.c
@@ -2788,14 +2788,18 @@ update_device_page_for_block (GduWindow *window,
{
show_flags->volume_buttons |= SHOW_FLAGS_VOLUME_BUTTONS_ENCRYPTED_LOCK;
/* Translators: Shown as in-use part of 'Contents' if the encrypted device is unlocked */
- in_use_markup = g_strdup (C_("volume-content-luks", "Unlocked"));
+ in_use_markup = g_strdup (C_("volume-content-crypto", "Unlocked"));
}
else
{
show_flags->volume_buttons |= SHOW_FLAGS_VOLUME_BUTTONS_ENCRYPTED_UNLOCK;
/* Translators: Shown as in-use part of 'Contents' if the encrypted device is unlocked */
- in_use_markup = g_strdup (C_("volume-content-luks", "Locked"));
+ in_use_markup = g_strdup (C_("volume-content-crypto", "Locked"));
}
+ }
+
+ if (g_strcmp0 (udisks_block_get_id_type (block), "crypto_LUKS") == 0)
+ {
show_flags->volume_menu |= SHOW_FLAGS_VOLUME_MENU_CONFIGURE_CRYPTTAB;
show_flags->volume_menu |= SHOW_FLAGS_VOLUME_MENU_CHANGE_PASSPHRASE;
}
diff --git a/src/disks/ui/unlock-device-dialog.ui b/src/disks/ui/unlock-device-dialog.ui
index 937ca14b..288086fc 100644
--- a/src/disks/ui/unlock-device-dialog.ui
+++ b/src/disks/ui/unlock-device-dialog.ui
@@ -2,6 +2,7 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkDialog" id="unlock-device-dialog">
+ <property name="width_request">400</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="title" translatable="yes">Enter passphrase to unlock</property>
@@ -14,6 +15,8 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
+ <property name="margin_left">20</property>
+ <property name="margin_right">20</property>
<child>
<object class="GtkBox" id="infobar-vbox">
<property name="visible">True</property>
@@ -30,7 +33,24 @@
</packing>
</child>
<child>
- <object class="GtkGrid" id="grid1">
+ <object class="GtkLabel" id="unknown-crypto-label">
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_bottom">5</property>
+ <property name="label" translatable="yes">This volume might be a VeraCrypt volume as it contains
random data.</property>
+ <property name="wrap">True</property>
+ <property name="width_chars">30</property>
+ <property name="max_width_chars">30</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="unlock-device-grid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">6</property>
@@ -56,6 +76,7 @@
</child>
<child>
<object class="GtkEntry" id="unlock-device-passphrase-entry">
+ <property name="placeholder-text" translatable="yes">If specified</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
@@ -88,6 +109,122 @@
<property name="height">1</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="unlock-device-volume-type-label">
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Volume type</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">1</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="unlock-device-volume-type-box">
+ <property name="spacing">10</property>
+ <property name="margin_top">3</property>
+ <property name="margin_bottom">3</property>
+ <child>
+ <object class="GtkCheckButton" id="unlock-device-tcrypt-hidden-check-button">
+ <property name="label" translatable="yes">_Hidden</property>
+ <property name="tooltip_markup" translatable="yes">Instead of unlocking this volume,
attempt to unlock a secondary volume hidden inside.</property>
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="unlock-device-tcrypt-system-check-button">
+ <property name="label" translatable="yes">Windows _system</property>
+ <property name="tooltip_markup" translatable="yes">Unlock an encrypted Windows system
partition or drive.</property>
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="unlock-device-pim-label">
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">PI_M</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">unlock-device-pim-entry</property>
+ <property name="xalign">1</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="unlock-device-pim-entry">
+ <property name="placeholder-text" translatable="yes">If specified</property>
+ <property name="tooltip_markup" translatable="yes">If set, the VeraCrypt PIM (Personal
Iterations Multiplier) numeric value to use for this volume.</property>
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="unlock-device-keyfiles-label">
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Keyfiles</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">1</property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFileChooserButton" id="unlock-device-tcrypt-keyfile-chooser-button">
+ <property name="title" translatable="yes">Select a Keyfile</property>
+ <property name="visible">False</property>
+ <property name="no_show_all">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
<child>
<placeholder/>
</child>
@@ -117,9 +254,10 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="button6">
+ <object class="GtkButton" id="unlock-device-unlock-button">
<property name="label" translatable="yes">_Unlock</property>
<property name="visible">True</property>
+ <property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="receives_default">True</property>
@@ -143,7 +281,7 @@
</child>
<action-widgets>
<action-widget response="-6">button5</action-widget>
- <action-widget response="-5">button6</action-widget>
+ <action-widget response="-5">unlock-device-unlock-button</action-widget>
</action-widgets>
</object>
</interface>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]