fe1ca8
From 768b91ef6f68661462494bed800505064eb97bc8 Mon Sep 17 00:00:00 2001
fe1ca8
From: Milan Broz <gmazyland@gmail.com>
fe1ca8
Date: Wed, 11 Jul 2018 12:34:39 +0200
fe1ca8
Subject: [PATCH 1/6] libblkid: Check for a secondary LUKS2 header.
fe1ca8
fe1ca8
This patch adds search for a secondary LUKS2 header,
fe1ca8
if the primary one is corrupted.
fe1ca8
fe1ca8
This patch is primarily needed for wipefs that should wipe
fe1ca8
both signatures (otherwise LUKS2 header recovery can use
fe1ca8
secondary header and revert wipefs action).
fe1ca8
fe1ca8
Signed-off-by: Milan Broz <gmazyland@gmail.com>
fe1ca8
Upstream: http://github.com/karelzak/util-linux/commit/8bee1a220db8effbe5a75ba9bc68840e019ea89a
fe1ca8
Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1595882
fe1ca8
---
fe1ca8
 libblkid/src/superblocks/luks.c | 60 ++++++++++++++++++++++++++++++++---------
fe1ca8
 1 file changed, 47 insertions(+), 13 deletions(-)
fe1ca8
fe1ca8
diff --git a/libblkid/src/superblocks/luks.c b/libblkid/src/superblocks/luks.c
fe1ca8
index bc3d7f558..67d7cfcc5 100644
fe1ca8
--- a/libblkid/src/superblocks/luks.c
fe1ca8
+++ b/libblkid/src/superblocks/luks.c
fe1ca8
@@ -1,5 +1,6 @@
fe1ca8
 /*
fe1ca8
  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
fe1ca8
+ * Copyright (C) 2018 Milan Broz <gmazyland@gmail.com>
fe1ca8
  *
fe1ca8
  * Inspired by libvolume_id by
fe1ca8
  *     Kay Sievers <kay.sievers@vrfy.org>
fe1ca8
@@ -29,6 +30,15 @@
fe1ca8
 #define LUKS2_CHECKSUM_ALG_L		32
fe1ca8
 #define LUKS2_CHECKSUM_L		64
fe1ca8
 
fe1ca8
+#define LUKS_MAGIC	"LUKS\xba\xbe"
fe1ca8
+#define LUKS_MAGIC_2	"SKUL\xba\xbe"
fe1ca8
+
fe1ca8
+/* Offsets for secondary header (for scan if primary header is corrupted). */
fe1ca8
+#define LUKS2_HDR2_OFFSETS { 0x04000, 0x008000, 0x010000, 0x020000, \
fe1ca8
+                             0x40000, 0x080000, 0x100000, 0x200000, 0x400000 }
fe1ca8
+
fe1ca8
+static const uint64_t secondary_offsets[] = LUKS2_HDR2_OFFSETS;
fe1ca8
+
fe1ca8
 struct luks_phdr {
fe1ca8
 	uint8_t		magic[LUKS_MAGIC_L];
fe1ca8
 	uint16_t	version;
fe1ca8
@@ -59,18 +69,16 @@ struct luks2_phdr {
fe1ca8
 	/* Padding to 4k, then JSON area */
fe1ca8
 } __attribute__ ((packed));
fe1ca8
 
fe1ca8
-static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag)
fe1ca8
+static int luks_attributes(blkid_probe pr, struct luks2_phdr *header, uint64_t offset)
fe1ca8
 {
fe1ca8
-	struct luks_phdr *header_v1;
fe1ca8
-	struct luks2_phdr *header;
fe1ca8
 	int version;
fe1ca8
+	struct luks_phdr *header_v1;
fe1ca8
 
fe1ca8
-	header = blkid_probe_get_sb(pr, mag, struct luks2_phdr);
fe1ca8
-	if (header == NULL)
fe1ca8
-		return errno ? -errno : 1;
fe1ca8
+	if (blkid_probe_set_magic(pr, offset, LUKS_MAGIC_L, (unsigned char *) &header->magic))
fe1ca8
+		return BLKID_PROBE_NONE;
fe1ca8
 
fe1ca8
 	version = be16_to_cpu(header->version);
fe1ca8
-	blkid_probe_sprintf_version(pr, "%u", be16_to_cpu(header->version));
fe1ca8
+	blkid_probe_sprintf_version(pr, "%u", version);
fe1ca8
 
fe1ca8
 	if (version == 1) {
fe1ca8
 		header_v1 = (struct luks_phdr *)header;
fe1ca8
@@ -84,7 +92,37 @@ static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag)
fe1ca8
 		blkid_probe_set_id_label(pr, "SUBSYSTEM",
fe1ca8
 			(unsigned char *) header->subsystem, LUKS2_LABEL_L);
fe1ca8
 	}
fe1ca8
-	return 0;
fe1ca8
+
fe1ca8
+	return BLKID_PROBE_OK;
fe1ca8
+}
fe1ca8
+
fe1ca8
+static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag __attribute__((__unused__)))
fe1ca8
+{
fe1ca8
+	struct luks2_phdr *header;
fe1ca8
+	size_t i;
fe1ca8
+
fe1ca8
+	header = (struct luks2_phdr *) blkid_probe_get_buffer(pr, 0, sizeof(struct luks2_phdr));
fe1ca8
+	if (!header)
fe1ca8
+		return errno ? -errno : BLKID_PROBE_NONE;
fe1ca8
+
fe1ca8
+	if (!memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L)) {
fe1ca8
+		/* LUKS primary header was found. */
fe1ca8
+		return luks_attributes(pr, header, 0);
fe1ca8
+	} else {
fe1ca8
+		/* No primary header, scan for known offsets of LUKS2 secondary header. */
fe1ca8
+		for (i = 0; i < ARRAY_SIZE(secondary_offsets); i++) {
fe1ca8
+			header = (struct luks2_phdr *) blkid_probe_get_buffer(pr,
fe1ca8
+				  secondary_offsets[i], sizeof(struct luks2_phdr));
fe1ca8
+
fe1ca8
+			if (!header)
fe1ca8
+				return errno ? -errno : BLKID_PROBE_NONE;
fe1ca8
+
fe1ca8
+			if (!memcmp(header->magic, LUKS_MAGIC_2, LUKS_MAGIC_L))
fe1ca8
+				return luks_attributes(pr, header, secondary_offsets[i]);
fe1ca8
+		}
fe1ca8
+	}
fe1ca8
+
fe1ca8
+	return BLKID_PROBE_NONE;
fe1ca8
 }
fe1ca8
 
fe1ca8
 const struct blkid_idinfo luks_idinfo =
fe1ca8
@@ -92,9 +130,5 @@ const struct blkid_idinfo luks_idinfo =
fe1ca8
 	.name		= "crypto_LUKS",
fe1ca8
 	.usage		= BLKID_USAGE_CRYPTO,
fe1ca8
 	.probefunc	= probe_luks,
fe1ca8
-	.magics		=
fe1ca8
-	{
fe1ca8
-		{ .magic = "LUKS\xba\xbe", .len = 6 },
fe1ca8
-		{ NULL }
fe1ca8
-	}
fe1ca8
+	.magics		= BLKID_NONE_MAGIC
fe1ca8
 };
fe1ca8
-- 
fe1ca8
2.14.4
fe1ca8