You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
966 lines
41 KiB
966 lines
41 KiB
From 37f1aff5f5f967d6a4440d176f3de877aab789ac Mon Sep 17 00:00:00 2001 |
|
From: Vojtech Trefny <vtrefny@redhat.com> |
|
Date: Mon, 20 Sep 2021 16:38:16 +0200 |
|
Subject: [PATCH 1/3] Add support for creating and activating integrity devices |
|
|
|
This adds support for create, open and close actions for standalone |
|
integrity devices using cryptsetup. |
|
--- |
|
configure.ac | 4 +- |
|
src/lib/plugin_apis/crypto.api | 157 +++++++++++++++++ |
|
src/plugins/crypto.c | 261 +++++++++++++++++++++++++++- |
|
src/plugins/crypto.h | 41 +++++ |
|
src/python/gi/overrides/BlockDev.py | 24 +++ |
|
tests/crypto_test.py | 97 ++++++++++- |
|
6 files changed, 576 insertions(+), 8 deletions(-) |
|
|
|
diff --git a/configure.ac b/configure.ac |
|
index abe1412..13830ae 100644 |
|
--- a/configure.ac |
|
+++ b/configure.ac |
|
@@ -210,7 +210,9 @@ AS_IF([test "x$with_crypto" != "xno"], |
|
AS_IF([$PKG_CONFIG --atleast-version=2.0.3 libcryptsetup], |
|
[AC_DEFINE([LIBCRYPTSETUP_2])], []) |
|
AS_IF([$PKG_CONFIG --atleast-version=2.3.0 libcryptsetup], |
|
- [AC_DEFINE([LIBCRYPTSETUP_BITLK])], []) |
|
+ [AC_DEFINE([LIBCRYPTSETUP_23])], []) |
|
+ AS_IF([$PKG_CONFIG --atleast-version=2.4.0 libcryptsetup], |
|
+ [AC_DEFINE([LIBCRYPTSETUP_24])], []) |
|
AS_IF([test "x$with_escrow" != "xno"], |
|
[LIBBLOCKDEV_PKG_CHECK_MODULES([NSS], [nss >= 3.18.0]) |
|
LIBBLOCKDEV_CHECK_HEADER([volume_key/libvolume_key.h], [$GLIB_CFLAGS $NSS_CFLAGS], [libvolume_key.h not available])], |
|
diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api |
|
index ef0217f..40e32c8 100644 |
|
--- a/src/lib/plugin_apis/crypto.api |
|
+++ b/src/lib/plugin_apis/crypto.api |
|
@@ -1,5 +1,6 @@ |
|
#include <glib.h> |
|
#include <blockdev/utils.h> |
|
+#include <libcryptsetup.h> |
|
|
|
#define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB |
|
|
|
@@ -245,6 +246,115 @@ GType bd_crypto_luks_extra_get_type () { |
|
return type; |
|
} |
|
|
|
+#define BD_CRYPTO_TYPE_INTEGRITY_EXTRA (bd_crypto_integrity_extra_get_type ()) |
|
+GType bd_crypto_integrity_extra_get_type(); |
|
+ |
|
+/** |
|
+ * BDCryptoIntegrityExtra: |
|
+ * @sector_size: integrity sector size |
|
+ * @journal_size: size of journal in bytes |
|
+ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit |
|
+ * @journal_commit_time: journal commit time (or bitmap flush time) in ms |
|
+ * @interleave_sectors: number of interleave sectors (power of two) |
|
+ * @tag_size: tag size per-sector in bytes |
|
+ * @buffer_sectors: number of sectors in one buffer |
|
+ */ |
|
+typedef struct BDCryptoIntegrityExtra { |
|
+ guint32 sector_size; |
|
+ guint64 journal_size; |
|
+ guint journal_watermark; |
|
+ guint journal_commit_time; |
|
+ guint32 interleave_sectors; |
|
+ guint32 tag_size; |
|
+ guint32 buffer_sectors; |
|
+} BDCryptoIntegrityExtra; |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_extra_copy: (skip) |
|
+ * @extra: (allow-none): %BDCryptoIntegrityExtra to copy |
|
+ * |
|
+ * Creates a new copy of @extra. |
|
+ */ |
|
+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { |
|
+ if (extra == NULL) |
|
+ return NULL; |
|
+ |
|
+ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); |
|
+ |
|
+ new_extra->sector_size = extra->sector_size; |
|
+ new_extra->journal_size = extra->journal_size; |
|
+ new_extra->journal_watermark = extra->journal_watermark; |
|
+ new_extra->journal_commit_time = extra->journal_commit_time; |
|
+ new_extra->interleave_sectors = extra->interleave_sectors; |
|
+ new_extra->tag_size = extra->tag_size; |
|
+ new_extra->buffer_sectors = extra->buffer_sectors; |
|
+ |
|
+ return new_extra; |
|
+} |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_extra_free: (skip) |
|
+ * @extra: (allow-none): %BDCryptoIntegrityExtra to free |
|
+ * |
|
+ * Frees @extra. |
|
+ */ |
|
+void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { |
|
+ if (extra == NULL) |
|
+ return; |
|
+ |
|
+ g_free (extra); |
|
+} |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_extra_new: (constructor) |
|
+ * @sector_size: integrity sector size, 0 for default (512) |
|
+ * @journal_size: size of journal in bytes |
|
+ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit |
|
+ * @journal_commit_time: journal commit time (or bitmap flush time) in ms |
|
+ * @interleave_sectors: number of interleave sectors (power of two) |
|
+ * @tag_size: tag size per-sector in bytes |
|
+ * @buffer_sectors: number of sectors in one buffer |
|
+ * |
|
+ * Returns: (transfer full): a new Integrity extra argument |
|
+ */ |
|
+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { |
|
+ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); |
|
+ ret->sector_size = sector_size; |
|
+ ret->journal_size = journal_size; |
|
+ ret->journal_watermark = journal_watermark; |
|
+ ret->journal_commit_time = journal_commit_time; |
|
+ ret->interleave_sectors = interleave_sectors; |
|
+ ret->tag_size = tag_size; |
|
+ ret->buffer_sectors = buffer_sectors; |
|
+ |
|
+ return ret; |
|
+} |
|
+ |
|
+GType bd_crypto_integrity_extra_get_type () { |
|
+ static GType type = 0; |
|
+ |
|
+ if (G_UNLIKELY(type == 0)) { |
|
+ type = g_boxed_type_register_static("BDCryptoIntegrityExtra", |
|
+ (GBoxedCopyFunc) bd_crypto_integrity_extra_copy, |
|
+ (GBoxedFreeFunc) bd_crypto_integrity_extra_free); |
|
+ } |
|
+ |
|
+ return type; |
|
+} |
|
+ |
|
+typedef enum { |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, |
|
+#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, |
|
+#endif |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, |
|
+#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, |
|
+#endif |
|
+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, |
|
+} BDCryptoIntegrityOpenFlags; |
|
+ |
|
#define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) |
|
GType bd_crypto_luks_info_get_type(); |
|
|
|
@@ -857,6 +967,53 @@ BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error) |
|
*/ |
|
BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); |
|
|
|
+/** |
|
+ * bd_crypto_integrity_format: |
|
+ * @device: a device to format as integrity |
|
+ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default |
|
+ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums |
|
+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed |
|
+ * @key_size: size the integrity key and @key_data |
|
+ * @extra: (allow-none): extra arguments for integrity format creation |
|
+ * @error: (out): place to store error (if any) |
|
+ * |
|
+ * Formats the given @device as integrity according to the other parameters given. |
|
+ * |
|
+ * Returns: whether the given @device was successfully formatted as integrity or not |
|
+ * (the @error) contains the error in such cases) |
|
+ * |
|
+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE |
|
+ */ |
|
+gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_open: |
|
+ * @device: integrity device to open |
|
+ * @name: name for the opened @device |
|
+ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default |
|
+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed |
|
+ * @key_size: size the integrity key and @key_data |
|
+ * @flags: flags for the integrity device activation |
|
+ * @extra: (allow-none): extra arguments for integrity open |
|
+ * @error: (out): place to store error (if any) |
|
+ * |
|
+ * Returns: whether the @device was successfully opened or not |
|
+ * |
|
+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE |
|
+ */ |
|
+gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_close: |
|
+ * @integrity_device: integrity device to close |
|
+ * @error: (out): place to store error (if any) |
|
+ * |
|
+ * Returns: whether the given @integrity_device was successfully closed or not |
|
+ * |
|
+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE |
|
+ */ |
|
+gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); |
|
+ |
|
/** |
|
* bd_crypto_device_seems_encrypted: |
|
* @device: the queried device |
|
diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c |
|
index 4fad9a8..b1b0700 100644 |
|
--- a/src/plugins/crypto.c |
|
+++ b/src/plugins/crypto.c |
|
@@ -50,6 +50,18 @@ |
|
|
|
#define SECTOR_SIZE 512 |
|
|
|
+#define DEFAULT_LUKS_KEYSIZE_BITS 256 |
|
+#define DEFAULT_LUKS_CIPHER "aes-xts-plain64" |
|
+ |
|
+#ifdef LIBCRYPTSETUP_23 |
|
+/* 0 for autodetect since 2.3.0 */ |
|
+#define DEFAULT_INTEGRITY_TAG_SIZE 0 |
|
+#else |
|
+/* we need some sane default for older versions, users should specify tag size when using |
|
+ other algorithms than the default crc32c */ |
|
+#define DEFAULT_INTEGRITY_TAG_SIZE 4 |
|
+#endif |
|
+ |
|
#define UNUSED __attribute__((unused)) |
|
|
|
/** |
|
@@ -146,6 +158,43 @@ BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar |
|
return ret; |
|
} |
|
|
|
+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors) { |
|
+ BDCryptoIntegrityExtra *ret = g_new0 (BDCryptoIntegrityExtra, 1); |
|
+ ret->sector_size = sector_size; |
|
+ ret->journal_size = journal_size; |
|
+ ret->journal_watermark = journal_watermark; |
|
+ ret->journal_commit_time = journal_commit_time; |
|
+ ret->interleave_sectors = interleave_sectors; |
|
+ ret->tag_size = tag_size; |
|
+ ret->buffer_sectors = buffer_sectors; |
|
+ |
|
+ return ret; |
|
+} |
|
+ |
|
+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra) { |
|
+ if (extra == NULL) |
|
+ return NULL; |
|
+ |
|
+ BDCryptoIntegrityExtra *new_extra = g_new0 (BDCryptoIntegrityExtra, 1); |
|
+ |
|
+ new_extra->sector_size = extra->sector_size; |
|
+ new_extra->journal_size = extra->journal_size; |
|
+ new_extra->journal_watermark = extra->journal_watermark; |
|
+ new_extra->journal_commit_time = extra->journal_commit_time; |
|
+ new_extra->interleave_sectors = extra->interleave_sectors; |
|
+ new_extra->tag_size = extra->tag_size; |
|
+ new_extra->buffer_sectors = extra->buffer_sectors; |
|
+ |
|
+ return new_extra; |
|
+} |
|
+ |
|
+void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra) { |
|
+ if (extra == NULL) |
|
+ return; |
|
+ |
|
+ g_free (extra); |
|
+} |
|
+ |
|
void bd_crypto_luks_info_free (BDCryptoLUKSInfo *info) { |
|
if (info == NULL) |
|
return; |
|
@@ -346,15 +395,15 @@ gboolean bd_crypto_is_tech_avail (BDCryptoTech tech, guint64 mode, GError **erro |
|
"Integrity technology requires libcryptsetup >= 2.0"); |
|
return FALSE; |
|
#endif |
|
- ret = mode & (BD_CRYPTO_TECH_MODE_QUERY); |
|
+ ret = mode & (BD_CRYPTO_TECH_MODE_CREATE|BD_CRYPTO_TECH_MODE_OPEN_CLOSE|BD_CRYPTO_TECH_MODE_QUERY); |
|
if (ret != mode) { |
|
g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, |
|
- "Only 'query' supported for Integrity"); |
|
+ "Only 'create', 'open' and 'query' supported for Integrity"); |
|
return FALSE; |
|
} else |
|
return TRUE; |
|
case BD_CRYPTO_TECH_BITLK: |
|
-#ifndef LIBCRYPTSETUP_BITLK |
|
+#ifndef LIBCRYPTSETUP_23 |
|
g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, |
|
"BITLK technology requires libcryptsetup >= 2.3.0"); |
|
return FALSE; |
|
@@ -2035,6 +2084,208 @@ BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **e |
|
} |
|
#endif |
|
|
|
+static int _wipe_progress (guint64 size, guint64 offset, void *usrptr) { |
|
+ /* "convert" the progress from 0-100 to 50-100 because wipe starts at 50 in bd_crypto_integrity_format */ |
|
+ gdouble progress = 50 + (((gdouble) offset / size) * 100) / 2; |
|
+ bd_utils_report_progress (*(guint64 *) usrptr, progress, "Integrity device wipe in progress"); |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_format: |
|
+ * @device: a device to format as integrity |
|
+ * @algorithm: integrity algorithm specification (e.g. "crc32c" or "sha256") |
|
+ * @wipe: whether to wipe the device after format; a device that is not initially wiped will contain invalid checksums |
|
+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed |
|
+ * @key_size: size the integrity key and @key_data |
|
+ * @extra: (allow-none): extra arguments for integrity format creation |
|
+ * @error: (out): place to store error (if any) |
|
+ * |
|
+ * Formats the given @device as integrity according to the other parameters given. |
|
+ * |
|
+ * Returns: whether the given @device was successfully formatted as integrity or not |
|
+ * (the @error) contains the error in such cases) |
|
+ * |
|
+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_CREATE |
|
+ */ |
|
+gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error) { |
|
+ struct crypt_device *cd = NULL; |
|
+ gint ret; |
|
+ guint64 progress_id = 0; |
|
+ gchar *msg = NULL; |
|
+ struct crypt_params_integrity params = ZERO_INIT; |
|
+ g_autofree gchar *tmp_name = NULL; |
|
+ g_autofree gchar *tmp_path = NULL; |
|
+ g_autofree gchar *dev_name = NULL; |
|
+ |
|
+ msg = g_strdup_printf ("Started formatting '%s' as integrity device", device); |
|
+ progress_id = bd_utils_report_started (msg); |
|
+ g_free (msg); |
|
+ |
|
+ ret = crypt_init (&cd, device); |
|
+ if (ret != 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
+ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ if (extra) { |
|
+ params.sector_size = extra->sector_size; |
|
+ params.journal_size = extra->journal_size; |
|
+ params.journal_watermark = extra->journal_watermark; |
|
+ params.journal_commit_time = extra->journal_commit_time; |
|
+ params.interleave_sectors = extra->interleave_sectors; |
|
+ params.tag_size = extra->tag_size; |
|
+ params.buffer_sectors = extra->buffer_sectors; |
|
+ } |
|
+ |
|
+ params.integrity_key_size = key_size; |
|
+ params.integrity = algorithm; |
|
+ params.tag_size = params.tag_size ? params.tag_size : DEFAULT_INTEGRITY_TAG_SIZE; |
|
+ |
|
+ ret = crypt_format (cd, CRYPT_INTEGRITY, NULL, NULL, NULL, NULL, 0, ¶ms); |
|
+ if (ret != 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_FORMAT_FAILED, |
|
+ "Failed to format device: %s", strerror_l (-ret, c_locale)); |
|
+ crypt_free (cd); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ if (wipe) { |
|
+ bd_utils_report_progress (progress_id, 50, "Format created"); |
|
+ |
|
+ dev_name = g_path_get_basename (device); |
|
+ tmp_name = g_strdup_printf ("bd-temp-integrity-%s-%d", dev_name, g_random_int ()); |
|
+ tmp_path = g_strdup_printf ("%s/%s", crypt_get_dir (), tmp_name); |
|
+ |
|
+ ret = crypt_activate_by_volume_key (cd, tmp_name, (const char *) key_data, key_size, |
|
+ CRYPT_ACTIVATE_PRIVATE | CRYPT_ACTIVATE_NO_JOURNAL); |
|
+ if (ret != 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
+ "Failed to activate the newly created integrity device for wiping: %s", |
|
+ strerror_l (-ret, c_locale)); |
|
+ crypt_free (cd); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ bd_utils_report_progress (progress_id, 50, "Starting to wipe the newly created integrity device"); |
|
+ ret = crypt_wipe (cd, tmp_path, CRYPT_WIPE_ZERO, 0, 0, 1048576, |
|
+ 0, &_wipe_progress, &progress_id); |
|
+ bd_utils_report_progress (progress_id, 100, "Wipe finished"); |
|
+ if (ret != 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
+ "Failed to wipe the newly created integrity device: %s", |
|
+ strerror_l (-ret, c_locale)); |
|
+ |
|
+ ret = crypt_deactivate (cd, tmp_name); |
|
+ if (ret != 0) |
|
+ g_warning ("Failed to deactivate temporary device %s", tmp_name); |
|
+ |
|
+ crypt_free (cd); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ ret = crypt_deactivate (cd, tmp_name); |
|
+ if (ret != 0) |
|
+ g_warning ("Failed to deactivate temporary device %s", tmp_name); |
|
+ |
|
+ } else |
|
+ bd_utils_report_finished (progress_id, "Completed"); |
|
+ |
|
+ crypt_free (cd); |
|
+ |
|
+ return TRUE; |
|
+} |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_open: |
|
+ * @device: integrity device to open |
|
+ * @name: name for the opened @device |
|
+ * @algorithm: (allow-none): integrity algorithm specification (e.g. "crc32c" or "sha256") or %NULL to use the default |
|
+ * @key_data: (allow-none) (array length=key_size): integrity key or %NULL if not needed |
|
+ * @key_size: size the integrity key and @key_data |
|
+ * @flags: flags for the integrity device activation |
|
+ * @extra: (allow-none): extra arguments for integrity open |
|
+ * @error: (out): place to store error (if any) |
|
+ * |
|
+ * Returns: whether the @device was successfully opened or not |
|
+ * |
|
+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE |
|
+ */ |
|
+gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error) { |
|
+ struct crypt_device *cd = NULL; |
|
+ gint ret = 0; |
|
+ guint64 progress_id = 0; |
|
+ gchar *msg = NULL; |
|
+ struct crypt_params_integrity params = ZERO_INIT; |
|
+ |
|
+ params.integrity = algorithm; |
|
+ params.integrity_key_size = key_size; |
|
+ |
|
+ if (extra) { |
|
+ params.sector_size = extra->sector_size; |
|
+ params.journal_size = extra->journal_size; |
|
+ params.journal_watermark = extra->journal_watermark; |
|
+ params.journal_commit_time = extra->journal_commit_time; |
|
+ params.interleave_sectors = extra->interleave_sectors; |
|
+ params.tag_size = extra->tag_size; |
|
+ params.buffer_sectors = extra->buffer_sectors; |
|
+ } |
|
+ |
|
+ msg = g_strdup_printf ("Started opening '%s' integrity device", device); |
|
+ progress_id = bd_utils_report_started (msg); |
|
+ g_free (msg); |
|
+ |
|
+ ret = crypt_init (&cd, device); |
|
+ if (ret != 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
+ "Failed to initialize device: %s", strerror_l (-ret, c_locale)); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ ret = crypt_load (cd, CRYPT_INTEGRITY, ¶ms); |
|
+ if (ret != 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
+ "Failed to load device's parameters: %s", strerror_l (-ret, c_locale)); |
|
+ crypt_free (cd); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); |
|
+ if (ret < 0) { |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
+ "Failed to activate device: %s", strerror_l (-ret, c_locale)); |
|
+ |
|
+ crypt_free (cd); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+ } |
|
+ |
|
+ crypt_free (cd); |
|
+ bd_utils_report_finished (progress_id, "Completed"); |
|
+ return TRUE; |
|
+} |
|
+ |
|
+/** |
|
+ * bd_crypto_integrity_close: |
|
+ * @integrity_device: integrity device to close |
|
+ * @error: (out): place to store error (if any) |
|
+ * |
|
+ * Returns: whether the given @integrity_device was successfully closed or not |
|
+ * |
|
+ * Tech category: %BD_CRYPTO_TECH_INTEGRITY-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE |
|
+ */ |
|
+gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error) { |
|
+ return _crypto_close (integrity_device, "integrity", error); |
|
+} |
|
+ |
|
/** |
|
* bd_crypto_device_seems_encrypted: |
|
* @device: the queried device |
|
@@ -2472,7 +2723,7 @@ gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, |
|
* |
|
* Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE |
|
*/ |
|
-#ifndef LIBCRYPTSETUP_BITLK |
|
+#ifndef LIBCRYPTSETUP_23 |
|
gboolean bd_crypto_bitlk_open (const gchar *device UNUSED, const gchar *name UNUSED, const guint8* pass_data UNUSED, gsize data_len UNUSED, gboolean read_only UNUSED, GError **error) { |
|
/* this will return FALSE and set error, because BITLK technology is not available */ |
|
return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); |
|
@@ -2542,7 +2793,7 @@ gboolean bd_crypto_bitlk_open (const gchar *device, const gchar *name, const gui |
|
* |
|
* Tech category: %BD_CRYPTO_TECH_BITLK-%BD_CRYPTO_TECH_MODE_OPEN_CLOSE |
|
*/ |
|
-#ifndef LIBCRYPTSETUP_BITLK |
|
+#ifndef LIBCRYPTSETUP_23 |
|
gboolean bd_crypto_bitlk_close (const gchar *bitlk_device UNUSED, GError **error) { |
|
/* this will return FALSE and set error, because BITLK technology is not available */ |
|
return bd_crypto_is_tech_avail (BD_CRYPTO_TECH_BITLK, BD_CRYPTO_TECH_MODE_OPEN_CLOSE, error); |
|
diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h |
|
index a38724d..166e558 100644 |
|
--- a/src/plugins/crypto.h |
|
+++ b/src/plugins/crypto.h |
|
@@ -116,6 +116,43 @@ void bd_crypto_luks_extra_free (BDCryptoLUKSExtra *extra); |
|
BDCryptoLUKSExtra* bd_crypto_luks_extra_copy (BDCryptoLUKSExtra *extra); |
|
BDCryptoLUKSExtra* bd_crypto_luks_extra_new (guint64 data_alignment, const gchar *data_device, const gchar *integrity, guint64 sector_size, const gchar *label, const gchar *subsystem, BDCryptoLUKSPBKDF *pbkdf); |
|
|
|
+/** |
|
+ * BDCryptoIntegrityExtra: |
|
+ * @sector_size: integrity sector size |
|
+ * @journal_size: size of journal in bytes |
|
+ * @journal_watermark: journal flush watermark in percents; in bitmap mode sectors-per-bit |
|
+ * @journal_commit_time: journal commit time (or bitmap flush time) in ms |
|
+ * @interleave_sectors: number of interleave sectors (power of two) |
|
+ * @tag_size: tag size per-sector in bytes |
|
+ * @buffer_sectors: number of sectors in one buffer |
|
+ */ |
|
+typedef struct BDCryptoIntegrityExtra { |
|
+ guint32 sector_size; |
|
+ guint64 journal_size; |
|
+ guint journal_watermark; |
|
+ guint journal_commit_time; |
|
+ guint32 interleave_sectors; |
|
+ guint32 tag_size; |
|
+ guint32 buffer_sectors; |
|
+} BDCryptoIntegrityExtra; |
|
+ |
|
+void bd_crypto_integrity_extra_free (BDCryptoIntegrityExtra *extra); |
|
+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra *extra); |
|
+BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); |
|
+ |
|
+typedef enum { |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, |
|
+#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, |
|
+#endif |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, |
|
+#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, |
|
+#endif |
|
+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, |
|
+} BDCryptoIntegrityOpenFlags; |
|
+ |
|
/** |
|
* BDCryptoLUKSInfo: |
|
* @version: LUKS version |
|
@@ -209,6 +246,10 @@ gboolean bd_crypto_luks_header_restore (const gchar *device, const gchar *backup |
|
BDCryptoLUKSInfo* bd_crypto_luks_info (const gchar *luks_device, GError **error); |
|
BDCryptoIntegrityInfo* bd_crypto_integrity_info (const gchar *device, GError **error); |
|
|
|
+gboolean bd_crypto_integrity_format (const gchar *device, const gchar *algorithm, gboolean wipe, const guint8* key_data, gsize key_size, BDCryptoIntegrityExtra *extra, GError **error); |
|
+gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const gchar *algorithm, const guint8* key_data, gsize key_size, BDCryptoIntegrityOpenFlags flags, BDCryptoIntegrityExtra *extra, GError **error); |
|
+gboolean bd_crypto_integrity_close (const gchar *integrity_device, GError **error); |
|
+ |
|
gboolean bd_crypto_device_seems_encrypted (const gchar *device, GError **error); |
|
gboolean bd_crypto_tc_open (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, gboolean read_only, GError **error); |
|
gboolean bd_crypto_tc_open_full (const gchar *device, const gchar *name, const guint8* pass_data, gsize data_len, const gchar **keyfiles, gboolean hidden, gboolean system, gboolean veracrypt, guint32 veracrypt_pim, gboolean read_only, GError **error); |
|
diff --git a/src/python/gi/overrides/BlockDev.py b/src/python/gi/overrides/BlockDev.py |
|
index 715a262..71bcd31 100644 |
|
--- a/src/python/gi/overrides/BlockDev.py |
|
+++ b/src/python/gi/overrides/BlockDev.py |
|
@@ -276,6 +276,30 @@ def crypto_bitlk_open(device, name, passphrase, read_only=False): |
|
__all__.append("crypto_bitlk_open") |
|
|
|
|
|
+class CryptoIntegrityExtra(BlockDev.CryptoIntegrityExtra): |
|
+ def __new__(cls, sector_size=0, journal_size=0, journal_watermark=0, journal_commit_time=0, interleave_sectors=0, tag_size=0, buffer_sectors=0): |
|
+ ret = BlockDev.CryptoIntegrityExtra.new(sector_size, journal_size, journal_watermark, journal_commit_time, interleave_sectors, tag_size, buffer_sectors) |
|
+ ret.__class__ = cls |
|
+ return ret |
|
+ def __init__(self, *args, **kwargs): # pylint: disable=unused-argument |
|
+ super(CryptoIntegrityExtra, self).__init__() #pylint: disable=bad-super-call |
|
+CryptoIntegrityExtra = override(CryptoIntegrityExtra) |
|
+__all__.append("CryptoIntegrityExtra") |
|
+ |
|
+ |
|
+_crypto_integrity_format = BlockDev.crypto_integrity_format |
|
+@override(BlockDev.crypto_integrity_format) |
|
+def crypto_integrity_format(device, algorithm=None, wipe=True, key_data=None, extra=None): |
|
+ return _crypto_integrity_format(device, algorithm, wipe, key_data, extra) |
|
+__all__.append("crypto_integrity_format") |
|
+ |
|
+_crypto_integrity_open = BlockDev.crypto_integrity_open |
|
+@override(BlockDev.crypto_integrity_open) |
|
+def crypto_integrity_open(device, name, algorithm, key_data=None, flags=0, extra=None): |
|
+ return _crypto_integrity_open(device, name, algorithm, key_data, flags, extra) |
|
+__all__.append("crypto_integrity_open") |
|
+ |
|
+ |
|
_dm_create_linear = BlockDev.dm_create_linear |
|
@override(BlockDev.dm_create_linear) |
|
def dm_create_linear(map_name, device, length, uuid=None): |
|
diff --git a/tests/crypto_test.py b/tests/crypto_test.py |
|
index 0aecc03..1c6832e 100644 |
|
--- a/tests/crypto_test.py |
|
+++ b/tests/crypto_test.py |
|
@@ -2,6 +2,7 @@ import unittest |
|
import os |
|
import tempfile |
|
import overrides_hack |
|
+import secrets |
|
import shutil |
|
import subprocess |
|
import six |
|
@@ -42,6 +43,8 @@ class CryptoTestCase(unittest.TestCase): |
|
|
|
requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) |
|
|
|
+ _dm_name = "libblockdevTestLUKS" |
|
+ |
|
@classmethod |
|
def setUpClass(cls): |
|
unittest.TestCase.setUpClass() |
|
@@ -72,7 +75,7 @@ class CryptoTestCase(unittest.TestCase): |
|
|
|
def _clean_up(self): |
|
try: |
|
- BlockDev.crypto_luks_close("libblockdevTestLUKS") |
|
+ BlockDev.crypto_luks_close(self._dm_name) |
|
except: |
|
pass |
|
|
|
@@ -964,7 +967,8 @@ class CryptoTestInfo(CryptoTestCase): |
|
succ = BlockDev.crypto_luks_close("libblockdevTestLUKS") |
|
self.assertTrue(succ) |
|
|
|
-class CryptoTestIntegrity(CryptoTestCase): |
|
+ |
|
+class CryptoTestLUKS2Integrity(CryptoTestCase): |
|
@tag_test(TestTags.SLOW) |
|
@unittest.skipUnless(HAVE_LUKS2, "LUKS 2 not supported") |
|
def test_luks2_integrity(self): |
|
@@ -1151,3 +1155,92 @@ class CryptoTestBitlk(CryptoTestCase): |
|
succ = BlockDev.crypto_bitlk_close("libblockdevTestBitlk") |
|
self.assertTrue(succ) |
|
self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestBitlk")) |
|
+ |
|
+ |
|
+class CryptoTestIntegrity(CryptoTestCase): |
|
+ |
|
+ _dm_name = "libblockdevTestIntegrity" |
|
+ |
|
+ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") |
|
+ def test_integrity(self): |
|
+ # basic format+open+close test |
|
+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", False) |
|
+ self.assertTrue(succ) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") |
|
+ self.assertTrue(succ) |
|
+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ info = BlockDev.crypto_integrity_info(self._dm_name) |
|
+ self.assertEqual(info.algorithm, "sha256") |
|
+ |
|
+ succ = BlockDev.crypto_integrity_close(self._dm_name) |
|
+ self.assertTrue(succ) |
|
+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ # same now with a keyed algorithm |
|
+ key = list(secrets.token_bytes(64)) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "hmac(sha256)", False, key) |
|
+ self.assertTrue(succ) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "hmac(sha256)", key) |
|
+ self.assertTrue(succ) |
|
+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ info = BlockDev.crypto_integrity_info(self._dm_name) |
|
+ self.assertEqual(info.algorithm, "hmac(sha256)") |
|
+ |
|
+ succ = BlockDev.crypto_integrity_close(self._dm_name) |
|
+ self.assertTrue(succ) |
|
+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ # same with some custom parameters |
|
+ extra = BlockDev.CryptoIntegrityExtra(sector_size=4096, interleave_sectors=65536) |
|
+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "crc32c", wipe=False, extra=extra) |
|
+ self.assertTrue(succ) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c") |
|
+ self.assertTrue(succ) |
|
+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ info = BlockDev.crypto_integrity_info(self._dm_name) |
|
+ self.assertEqual(info.algorithm, "crc32c") |
|
+ self.assertEqual(info.sector_size, 4096) |
|
+ self.assertEqual(info.interleave_sectors, 65536) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_close(self._dm_name) |
|
+ self.assertTrue(succ) |
|
+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ @tag_test(TestTags.SLOW) |
|
+ @unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") |
|
+ def test_integrity_wipe(self): |
|
+ # also check that wipe progress reporting works |
|
+ progress_log = [] |
|
+ |
|
+ def _my_progress_func(_task, _status, completion, msg): |
|
+ progress_log.append((completion, msg)) |
|
+ |
|
+ succ = BlockDev.utils_init_prog_reporting(_my_progress_func) |
|
+ self.assertTrue(succ) |
|
+ self.addCleanup(BlockDev.utils_init_prog_reporting, None) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_format(self.loop_dev, "sha256", True) |
|
+ self.assertTrue(succ) |
|
+ |
|
+ # at least one message "Integrity device wipe in progress" should be logged |
|
+ self.assertTrue(any(prog[1] == "Integrity device wipe in progress" for prog in progress_log)) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "sha256") |
|
+ self.assertTrue(succ) |
|
+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ # check the devices was wiped and the checksums recalculated |
|
+ # (mkfs reads some blocks first so without checksums it would fail) |
|
+ ret, _out, err = run_command("mkfs.ext2 /dev/mapper/%s " % self._dm_name) |
|
+ self.assertEqual(ret, 0, msg="Failed to create ext2 filesystem on integrity: %s" % err) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_close(self._dm_name) |
|
+ self.assertTrue(succ) |
|
+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 4dcb7a42a2cb33f7a63021d72889c9a9688adfd3 Mon Sep 17 00:00:00 2001 |
|
From: Vojtech Trefny <vtrefny@redhat.com> |
|
Date: Thu, 30 Sep 2021 16:01:40 +0200 |
|
Subject: [PATCH 2/3] Create smaller test images for integrity tests |
|
|
|
We are going to overwrite the entire device in test_integrity_wipe |
|
so we need to make sure the sparse actually fits to /tmp which |
|
can be smaller than 1 GiB. |
|
--- |
|
tests/crypto_test.py | 6 ++++-- |
|
1 file changed, 4 insertions(+), 2 deletions(-) |
|
|
|
diff --git a/tests/crypto_test.py b/tests/crypto_test.py |
|
index 1c6832e..b7ec251 100644 |
|
--- a/tests/crypto_test.py |
|
+++ b/tests/crypto_test.py |
|
@@ -44,6 +44,7 @@ class CryptoTestCase(unittest.TestCase): |
|
requested_plugins = BlockDev.plugin_specs_from_names(("crypto", "loop")) |
|
|
|
_dm_name = "libblockdevTestLUKS" |
|
+ _sparse_size = 1024**3 |
|
|
|
@classmethod |
|
def setUpClass(cls): |
|
@@ -57,8 +58,8 @@ class CryptoTestCase(unittest.TestCase): |
|
|
|
def setUp(self): |
|
self.addCleanup(self._clean_up) |
|
- self.dev_file = create_sparse_tempfile("crypto_test", 1024**3) |
|
- self.dev_file2 = create_sparse_tempfile("crypto_test2", 1024**3) |
|
+ self.dev_file = create_sparse_tempfile("crypto_test", self._sparse_size) |
|
+ self.dev_file2 = create_sparse_tempfile("crypto_test2", self._sparse_size) |
|
try: |
|
self.loop_dev = create_lio_device(self.dev_file) |
|
except RuntimeError as e: |
|
@@ -1160,6 +1161,7 @@ class CryptoTestBitlk(CryptoTestCase): |
|
class CryptoTestIntegrity(CryptoTestCase): |
|
|
|
_dm_name = "libblockdevTestIntegrity" |
|
+ _sparse_size = 100 * 1024**2 |
|
|
|
@unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") |
|
def test_integrity(self): |
|
-- |
|
2.31.1 |
|
|
|
|
|
From 3b82f9085c0df2e58b673716cdefd747495738e2 Mon Sep 17 00:00:00 2001 |
|
From: Vojtech Trefny <vtrefny@redhat.com> |
|
Date: Wed, 20 Oct 2021 10:27:41 +0200 |
|
Subject: [PATCH 3/3] crypto: Do not use libcryptsetup flags directly in |
|
crypto.h |
|
|
|
We can "translate" our flags in the implementation instead to |
|
avoid including libcryptsetup.h in our header and API files. |
|
--- |
|
src/lib/plugin_apis/crypto.api | 17 ++++++----------- |
|
src/plugins/crypto.c | 34 +++++++++++++++++++++++++++++++++- |
|
src/plugins/crypto.h | 16 ++++++---------- |
|
tests/crypto_test.py | 14 ++++++++++++++ |
|
4 files changed, 59 insertions(+), 22 deletions(-) |
|
|
|
diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api |
|
index 40e32c8..cf87979 100644 |
|
--- a/src/lib/plugin_apis/crypto.api |
|
+++ b/src/lib/plugin_apis/crypto.api |
|
@@ -1,6 +1,5 @@ |
|
#include <glib.h> |
|
#include <blockdev/utils.h> |
|
-#include <libcryptsetup.h> |
|
|
|
#define BD_CRYPTO_LUKS_METADATA_SIZE G_GUINT64_CONSTANT (2097152ULL) // 2 MiB |
|
|
|
@@ -343,16 +342,12 @@ GType bd_crypto_integrity_extra_get_type () { |
|
} |
|
|
|
typedef enum { |
|
- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, |
|
- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, |
|
-#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP |
|
- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, |
|
-#endif |
|
- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, |
|
-#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET |
|
- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, |
|
-#endif |
|
- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, |
|
} BDCryptoIntegrityOpenFlags; |
|
|
|
#define BD_CRYPTO_TYPE_LUKS_INFO (bd_crypto_luks_info_get_type ()) |
|
diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c |
|
index b1b0700..8a4d64a 100644 |
|
--- a/src/plugins/crypto.c |
|
+++ b/src/plugins/crypto.c |
|
@@ -2223,6 +2223,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const |
|
guint64 progress_id = 0; |
|
gchar *msg = NULL; |
|
struct crypt_params_integrity params = ZERO_INIT; |
|
+ guint32 activate_flags = 0; |
|
|
|
params.integrity = algorithm; |
|
params.integrity_key_size = key_size; |
|
@@ -2237,6 +2238,37 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const |
|
params.buffer_sectors = extra->buffer_sectors; |
|
} |
|
|
|
+ |
|
+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL) |
|
+ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL; |
|
+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECOVERY) |
|
+ activate_flags |= CRYPT_ACTIVATE_RECOVERY; |
|
+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE) |
|
+ activate_flags |= CRYPT_ACTIVATE_RECALCULATE; |
|
+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS) |
|
+ activate_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS; |
|
+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP) { |
|
+#ifndef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, |
|
+ "Cannot activate %s with bitmap, installed version of cryptsetup doesn't support this option.", device); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+#else |
|
+ activate_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP; |
|
+#endif |
|
+ } |
|
+ |
|
+ if (flags & BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET) { |
|
+#ifndef CRYPT_ACTIVATE_RECALCULATE_RESET |
|
+ g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_TECH_UNAVAIL, |
|
+ "Cannot reset integrity recalculation while activating %s, installed version of cryptsetup doesn't support this option.", device); |
|
+ bd_utils_report_finished (progress_id, (*error)->message); |
|
+ return FALSE; |
|
+#else |
|
+ activate_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET; |
|
+#endif |
|
+ } |
|
+ |
|
msg = g_strdup_printf ("Started opening '%s' integrity device", device); |
|
progress_id = bd_utils_report_started (msg); |
|
g_free (msg); |
|
@@ -2258,7 +2290,7 @@ gboolean bd_crypto_integrity_open (const gchar *device, const gchar *name, const |
|
return FALSE; |
|
} |
|
|
|
- ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, flags); |
|
+ ret = crypt_activate_by_volume_key (cd, name, (const char *) key_data, key_size, activate_flags); |
|
if (ret < 0) { |
|
g_set_error (error, BD_CRYPTO_ERROR, BD_CRYPTO_ERROR_DEVICE, |
|
"Failed to activate device: %s", strerror_l (-ret, c_locale)); |
|
diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h |
|
index 166e558..b5f133c 100644 |
|
--- a/src/plugins/crypto.h |
|
+++ b/src/plugins/crypto.h |
|
@@ -141,16 +141,12 @@ BDCryptoIntegrityExtra* bd_crypto_integrity_extra_copy (BDCryptoIntegrityExtra * |
|
BDCryptoIntegrityExtra* bd_crypto_integrity_extra_new (guint64 sector_size, guint64 journal_size, guint journal_watermark, guint journal_commit_time, guint64 interleave_sectors, guint64 tag_size, guint64 buffer_sectors); |
|
|
|
typedef enum { |
|
- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = CRYPT_ACTIVATE_NO_JOURNAL, |
|
- BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = CRYPT_ACTIVATE_RECOVERY, |
|
-#ifdef CRYPT_ACTIVATE_NO_JOURNAL_BITMAP |
|
- BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = CRYPT_ACTIVATE_NO_JOURNAL_BITMAP, |
|
-#endif |
|
- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = CRYPT_ACTIVATE_RECALCULATE, |
|
-#ifdef CRYPT_ACTIVATE_RECALCULATE_RESET |
|
- BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = CRYPT_ACTIVATE_RECALCULATE_RESET, |
|
-#endif |
|
- BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = CRYPT_ACTIVATE_ALLOW_DISCARDS, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL = 1 << 0, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECOVERY = 1 << 1, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_NO_JOURNAL_BITMAP = 1 << 2, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE = 1 << 3, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_RECALCULATE_RESET = 1 << 4, |
|
+ BD_CRYPTO_INTEGRITY_OPEN_ALLOW_DISCARDS = 1 << 5, |
|
} BDCryptoIntegrityOpenFlags; |
|
|
|
/** |
|
diff --git a/tests/crypto_test.py b/tests/crypto_test.py |
|
index b7ec251..673d8b8 100644 |
|
--- a/tests/crypto_test.py |
|
+++ b/tests/crypto_test.py |
|
@@ -1215,6 +1215,20 @@ class CryptoTestIntegrity(CryptoTestCase): |
|
self.assertTrue(succ) |
|
self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
|
|
+ # open with flags |
|
+ succ = BlockDev.crypto_integrity_open(self.loop_dev, self._dm_name, "crc32c", |
|
+ flags=BlockDev.CryptoIntegrityOpenFlags.ALLOW_DISCARDS) |
|
+ self.assertTrue(succ) |
|
+ self.assertTrue(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
+ # check that discard is enabled for the mapped device |
|
+ _ret, out, _err = run_command("dmsetup table %s" % self._dm_name) |
|
+ self.assertIn("allow_discards", out) |
|
+ |
|
+ succ = BlockDev.crypto_integrity_close(self._dm_name) |
|
+ self.assertTrue(succ) |
|
+ self.assertFalse(os.path.exists("/dev/mapper/%s" % self._dm_name)) |
|
+ |
|
@tag_test(TestTags.SLOW) |
|
@unittest.skipUnless(HAVE_LUKS2, "Integrity not supported") |
|
def test_integrity_wipe(self): |
|
-- |
|
2.31.1 |
|
|
|
|