diff --git a/src/lib/plugin_apis/crypto.api b/src/lib/plugin_apis/crypto.api index d790894c..1150a617 100644 --- a/src/lib/plugin_apis/crypto.api +++ b/src/lib/plugin_apis/crypto.api @@ -489,6 +489,7 @@ GType bd_crypto_bitlk_info_get_type(); * @uuid: UUID of the BITLK device * @backing_device: name of the underlying block device * @sector_size: size (in bytes) of encryption sector + * @has_clearkey: whether the device has a valid clear key protector */ typedef struct BDCryptoBITLKInfo { gchar *cipher; @@ -496,6 +497,7 @@ typedef struct BDCryptoBITLKInfo { gchar *uuid; gchar *backing_device; guint32 sector_size; + gboolean has_clearkey; } BDCryptoBITLKInfo; /** @@ -532,6 +534,7 @@ BDCryptoBITLKInfo* bd_crypto_bitlk_info_copy (BDCryptoBITLKInfo *info) { new_info->uuid = g_strdup (info->uuid); new_info->backing_device = g_strdup (info->backing_device); new_info->sector_size = info->sector_size; + new_info->has_clearkey = info->has_clearkey; return new_info; } @@ -1381,7 +1384,7 @@ gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, * bd_crypto_bitlk_open: * @device: the device to open * @name: name for the BITLK device - * @context: key slot context (passphrase/keyfile/token...) for this BITLK device + * @context: (nullable): key slot context (passphrase/keyfile/token...) for this BITLK device or %NULL for clear key * @read_only: whether to open as read-only or not (meaning read-write) * @error: (out) (optional): place to store error (if any) * @@ -1397,7 +1400,7 @@ gboolean bd_crypto_bitlk_open (const gchar *device, const gchar *name, BDCryptoK * bd_crypto_bitlk_open_flags: * @device: the device to open * @name: name for the BITLK device - * @context: key slot context (passphrase/keyfile/token...) for this BITLK device + * @context: (nullable): key slot context (passphrase/keyfile/token...) for this BITLK device or %NULL for clear key * @flags: activation flags for the BITLK device * @error: (out) (optional): place to store error (if any) * diff --git a/src/plugins/crypto.c b/src/plugins/crypto.c index e801e30a..dc54cc27 100644 --- a/src/plugins/crypto.c +++ b/src/plugins/crypto.c @@ -254,6 +254,7 @@ BDCryptoBITLKInfo* bd_crypto_bitlk_info_copy (BDCryptoBITLKInfo *info) { new_info->uuid = g_strdup (info->uuid); new_info->backing_device = g_strdup (info->backing_device); new_info->sector_size = info->sector_size; + new_info->has_clearkey = info->has_clearkey; return new_info; } @@ -2730,6 +2731,7 @@ BDCryptoBITLKInfo* bd_crypto_bitlk_info (const gchar *device, GError **error) { info->backing_device = g_strdup (crypt_get_device_name (cd)); ret = crypt_get_sector_size (cd); info->sector_size = ret > 0 ? ret : 0; + info->has_clearkey = (crypt_activate_by_passphrase (cd, NULL, CRYPT_ANY_SLOT, NULL, 0, 0) >= 0); crypt_free (cd); @@ -3638,7 +3640,7 @@ gboolean bd_crypto_escrow_device (const gchar *device, const gchar *passphrase, * bd_crypto_bitlk_open_flags: * @device: the device to open * @name: name for the BITLK device - * @context: key slot context (passphrase/keyfile/token...) for this BITLK device + * @context: (nullable): key slot context (passphrase/keyfile/token...) for this BITLK device or %NULL for clear key * @flags: activation flags for the BITLK device * @error: (out) (optional): place to store error (if any) * @@ -3689,7 +3691,9 @@ gboolean bd_crypto_bitlk_open_flags (const gchar *device, const gchar *name, BDC if (flags & BD_CRYPTO_OPEN_READONLY) crypt_flags |= CRYPT_ACTIVATE_READONLY; - if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) { + if (!context) { + ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT, NULL, 0, crypt_flags); + } else if (context->type == BD_CRYPTO_KEYSLOT_CONTEXT_TYPE_PASSPHRASE) { ret = crypt_activate_by_passphrase (cd, name, CRYPT_ANY_SLOT, (const char *) context->u.passphrase.pass_data, context->u.passphrase.data_len, @@ -3739,7 +3743,7 @@ gboolean bd_crypto_bitlk_open_flags (const gchar *device, const gchar *name, BDC * bd_crypto_bitlk_open: * @device: the device to open * @name: name for the BITLK device - * @context: key slot context (passphrase/keyfile/token...) for this BITLK device + * @context: (nullable): key slot context (passphrase/keyfile/token...) for this BITLK device or %NULL for clear key * @read_only: whether to open as read-only or not (meaning read-write) * @error: (out) (optional): place to store error (if any) * diff --git a/src/plugins/crypto.h b/src/plugins/crypto.h index 892866a1..3ff42d04 100644 --- a/src/plugins/crypto.h +++ b/src/plugins/crypto.h @@ -214,6 +214,7 @@ BDCryptoLUKSInfo* bd_crypto_luks_info_copy (BDCryptoLUKSInfo *info); * @uuid: UUID of the BITLK device * @backing_device: name of the underlying block device * @sector_size: size (in bytes) of encryption sector + * @has_clearkey: whether the device has a valid clear key protector */ typedef struct BDCryptoBITLKInfo { gchar *cipher; @@ -221,6 +222,7 @@ typedef struct BDCryptoBITLKInfo { gchar *uuid; gchar *backing_device; guint32 sector_size; + gboolean has_clearkey; } BDCryptoBITLKInfo; void bd_crypto_bitlk_info_free (BDCryptoBITLKInfo *info); diff --git a/tests/bitlk-images.tar.gz b/tests/bitlk-images.tar.gz index d0ecbb45..0f19b56a 100644 Binary files a/tests/bitlk-images.tar.gz and b/tests/bitlk-images.tar.gz differ diff --git a/tests/crypto_test.py b/tests/crypto_test.py index b33349a8..e7e052f4 100644 --- a/tests/crypto_test.py +++ b/tests/crypto_test.py @@ -1747,6 +1747,7 @@ def test_bitlk_info(self): self.assertEqual(info.cipher, "aes") self.assertEqual(info.mode, "xts-plain64") self.assertEqual(info.sector_size, 512) + self.assertFalse(info.has_clearkey) ctx = BlockDev.CryptoKeyslotContext(passphrase=self.passphrase) succ = BlockDev.crypto_bitlk_open(self.bitlk_dev, "libblockdevTestBitlk", ctx) @@ -1770,6 +1771,35 @@ def test_bitlk_info(self): self.assertTrue(succ) self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestBitlk")) + @unittest.skipUnless(HAVE_BITLK, "BITLK not supported") + def test_bitlk_clearkey(self): + """Verify that opening/closing a BitLocker device with Clear Key works""" + clearkey_img = "bitlk-aes-xts-128-clearkey-only.img" + succ, loop = BlockDev.loop_setup(os.path.join(self.tempdir, clearkey_img)) + if not succ: + raise RuntimeError("Failed to setup loop device for testing") + dev = "/dev/%s" % loop + try: + info = BlockDev.crypto_bitlk_info(dev) + self.assertIsNotNone(info) + self.assertTrue(info.has_clearkey) + self.assertEqual(info.uuid, "df73cb51-ff48-4033-8d56-a32cc2b1ab7a") + + # Open with NULL context (Clear Key) + succ = BlockDev.crypto_bitlk_open(dev, "libblockdevTestBitlkCK", None) + self.assertTrue(succ) + self.assertTrue(os.path.exists("/dev/mapper/libblockdevTestBitlkCK")) + + succ = BlockDev.crypto_bitlk_close("libblockdevTestBitlkCK") + self.assertTrue(succ) + self.assertFalse(os.path.exists("/dev/mapper/libblockdevTestBitlkCK")) + finally: + try: + BlockDev.crypto_bitlk_close("libblockdevTestBitlkCK") + except: + pass + BlockDev.loop_teardown(dev) + class CryptoTestFVAULT2(CryptoTestCase):