[PATCH] hald+LUKS v2

W. Michael Petullo mike at flyn.org
Wed Feb 16 14:57:33 PST 2005


Attached you should find a more complete patch to add LUKS[1] support
to hald.  This should eventually provide an easy means to mount encrypted
filesystems.  Currently, hald only detects that a disk contains a LUKS
header and sets some relevant parameters.

The previous patch only enabled hald to recognize a partition encrypted
using LUKS.  This patch adds the detection of a dm-crypt device and the
proper identification of its filesystem.  This is based on the work
David Z. did for a previous version of hald.  This special code is
required because the kernel does not quite consider a dm-crypt device
as a first-class citizen in sysfs.

Here is a rough example of the using this code with a USB disk:

1.  Format the usb disk to contain an encrypted filesystem using LUKS.

2.  Attach the disk to the computer running hald.

3.  Hald should identify the disk as a LUKS disk.  One may confirm this
with "lshal | grep LUKS."

4.  Use the sesame-setup tool I am working on to create a dm-crypt
plaintext device node for the device: "sesame-setup /dev/sda1."

5.  Hald should identify the plaintext device node.  One may confirm
this with "lshal | grep dm."

Step 4 will be performed automatically in a GNOME session once
gnome-volume-manager is modified to recognize these volumes and prompt
for a passphrase.

Thanks.

[1] http://clemens.endorphin.org/LUKS

-- 
Mike

:wq
-------------- next part --------------
diff -u --recursive --new-file hal-cvs-vanilla/ChangeLog hal-cvs/ChangeLog
--- hal-cvs-vanilla/ChangeLog	2005-02-10 11:45:11.000000000 -0600
+++ hal-cvs/ChangeLog	2005-02-16 16:55:45.000000000 -0600
@@ -1,3 +1,17 @@
+2005-02-16  W. Michael Petullo  <mike at flyn.org>
+
+	* hald/linux2/blockdev.c:
+	hald/linux2/probing/probe-volume.c:
+	volume_id/luks.c:
+	volume_id/luks.h:
+	volume_id/util.c:
+	volume_id/util.h:
+	volume_id/volume_id.c:
+	volume_id/volume_id.h:
+	volume_id/Makefile.am: Add support for volumes encrypted using
+	LUKS.
+
+
 2005-02-10  David Zeuthen  <davidz at redhat.com>
 
 	* configure.in: From Richard Hughes <richard at hughsie.com> I've
diff -u --recursive --new-file hal-cvs-vanilla/hald/linux2/blockdev.c hal-cvs/hald/linux2/blockdev.c
--- hal-cvs-vanilla/hald/linux2/blockdev.c	2005-02-10 11:03:57.000000000 -0600
+++ hal-cvs/hald/linux2/blockdev.c	2005-02-16 16:19:24.000000000 -0600
@@ -41,6 +41,7 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <unistd.h>
+#include <linux/kdev_t.h>
 
 #include <limits.h>
 #include <errno.h>
@@ -272,10 +273,97 @@
 		goto out;
 	}
 
-	if (parent == NULL)
+	d = hal_device_new ();
+
+	if (parent == NULL) {
+		unsigned int major;
+		unsigned int minor;
+		const char *last_elem;
+
+		major = 253; /* FIXME: replace by devmapper constant */
+
+		last_elem = hal_util_get_last_element (device_file);
+		if (sscanf (last_elem, "dm-%d", &minor) == 1) {
+			GDir *dir;
+
+
+			HAL_INFO (("path=%s is a device mapper dev, major/minor=%d/%d", device_file, major, minor));
+
+			/* Ugly hack to see if we're a LUKS crypto device; should
+			 * be replaced by some ioctl or libdevmapper stuff by where
+			 * we can ask about the name for /dev/dm-0; as e.g. given by
+			 * 'dmsetup info'
+			 *
+			 * Our assumption is that sesame-setup have invoked
+			 * dmsetup; e.g. the naming convention is 
+			 *
+			 *    sesame_crypto_<luks_uuid>
+			 *
+			 * where <luks_uuid> is the UUID encoded in the luks
+			 * metadata.
+			 */
+
+			/* Ugly sleep of 0.5s here as well to allow dmsetup to do the mknod */
+			usleep (1000 * 1000 * 5 / 10);
+			
+			if ((dir = g_dir_open ("/dev/mapper", 0, NULL)) != NULL) {
+				const gchar *f;
+				char devpath[256];
+				struct stat statbuf;
+				
+				while ((f = g_dir_read_name (dir)) != NULL) {
+					char sesame_prefix[] = "sesame_crypto_";
+					const char *luks_uuid;
+					
+					HAL_INFO (("looking at /dev/mapper/%s", f));
+					
+					g_snprintf (devpath, sizeof (devpath), "/dev/mapper/%s", f);
+					if (stat (devpath, &statbuf) == 0) {
+						if (S_ISBLK (statbuf.st_mode) && 
+						    MAJOR(statbuf.st_rdev) == major && 
+						    MINOR(statbuf.st_rdev) == minor &&
+						    strncmp (f, sesame_prefix, sizeof (sesame_prefix) - 1) == 0) {
+							HalDevice *backing_volume;
+							
+							luks_uuid = f + sizeof (sesame_prefix) - 1;
+							HAL_INFO (("found %s; luks_uuid='%s'!", 
+								   devpath, luks_uuid));
+							
+							backing_volume = hal_device_store_match_key_value_string (
+								hald_get_gdl (), 
+								"volume.uuid", 
+								/* FIXME: was "volume.crypto_sesame.uuid", */
+								luks_uuid);
+							if (backing_volume != NULL) {
+								const char *backing_volume_stordev_udi;
+								HAL_INFO (("backing_volume udi='%s'!", backing_volume->udi));
+								backing_volume_stordev_udi = hal_device_property_get_string (backing_volume, "block.storage_device");
+								if (backing_volume_stordev_udi != NULL) {
+									HAL_INFO (("backing_volume_stordev_udi='%s'!", backing_volume_stordev_udi));
+									parent = hal_device_store_find (hald_get_gdl (), backing_volume_stordev_udi);
+									if (parent != NULL) {
+										HAL_INFO (("parent='%s'!", parent->udi));
+										is_partition = TRUE;
+										hal_device_property_set_string (d, "volume.crypto_sesame.clear.backing_volume", backing_volume->udi);
+										goto got_parent;
+									}
+								}
+							}
+							
+						}
+					}
+				}
+				g_dir_close (dir);
+			}
+		}
+
+		hal_device_store_remove (hald_get_tdl (), d);
+		d = NULL;
 		goto error;
+	}
+
+got_parent:
 
-	d = hal_device_new ();
 	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	hal_device_property_set_string (d, "info.parent", parent->udi);
@@ -394,7 +482,6 @@
 		parent_bus = hal_device_property_get_string (parent, "info.bus");
 		HAL_INFO (("parent_bus is %s", parent_bus));
 
-		/* per-bus specific properties */
 		if (strcmp (parent_bus, "ide") == 0) {
 			char buf[256];
 			gchar *media;
diff -u --recursive --new-file hal-cvs-vanilla/hald/linux2/probing/probe-volume.c hal-cvs/hald/linux2/probing/probe-volume.c
--- hal-cvs-vanilla/hald/linux2/probing/probe-volume.c	2005-02-10 11:03:57.000000000 -0600
+++ hal-cvs/hald/linux2/probing/probe-volume.c	2005-02-15 10:30:56.000000000 -0600
@@ -74,6 +74,9 @@
 	case VOLUME_ID_RAID:
 		usage = "raid";
 		break;
+	case VOLUME_ID_CRYPTO:
+		usage = "crypto";
+		break;
 	case VOLUME_ID_UNUSED:
 		libhal_device_set_property_string (ctx, udi, "info.product", "Volume (unused)", &error);
 		usage = "unused";
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/luks.c hal-cvs/volume_id/luks.c
--- hal-cvs-vanilla/volume_id/luks.c	1969-12-31 18:00:00.000000000 -0600
+++ hal-cvs/volume_id/luks.c	2005-02-16 15:34:30.000000000 -0600
@@ -0,0 +1,114 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2005 W. Michael Petullo <mike at flyn.org>
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation; either
+ *	version 2.1 of the License, or (at your option) any later version.
+ *
+ *	This library is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *	Lesser General Public License for more details.
+ *
+ *	You should have received a copy of the GNU Lesser General Public
+ *	License along with this library; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <asm/types.h>
+
+#include "volume_id.h"
+#include "util.h"
+#include "logging.h"
+#include "luks.h"
+
+/* FIXME: this contains a lot of copy and pasted code.  One alternative
+ * would be to fork/exec cryptsetup isLuks and cryptsetup luksUUID.  Another
+ * would be to write a LUKS library */
+
+/* from cryptsetup-luks internal.h */
+#define SECTOR_SHIFT            9
+#define SECTOR_SIZE             (1 << SECTOR_SHIFT)
+
+/* from cryptsetup-luks luks.h */
+#define LUKS_CIPHERNAME_L 32
+#define LUKS_CIPHERMODE_L 32
+#define LUKS_HASHSPEC_L 32
+#define LUKS_DIGESTSIZE 20 /* since SHA1 */
+#define LUKS_SALTSIZE 32
+#define LUKS_NUMKEYS 8
+
+/* from cryptsetup-luks luks.h */
+const unsigned char LUKS_MAGIC[] = {'L','U','K','S', 0xba, 0xbe};
+#define LUKS_MAGIC_L 6
+
+/* from cryptsetup-luks luks.h */
+#define LUKS_PHDR_SIZE (sizeof(struct luks_phdr)/SECTOR_SIZE+1)
+
+/* from cryptsetup-luks luks.h */
+#define UUID_STRING_L 40
+
+int volume_id_probe_luks(struct volume_id *id, __u64 off)
+{
+	int i;
+
+	/* from cryptsetup-luks luks.h */
+	struct luks_phdr {
+		char            magic[LUKS_MAGIC_L];
+		uint16_t        version;
+		char            cipherName[LUKS_CIPHERNAME_L];
+		char            cipherMode[LUKS_CIPHERMODE_L];
+		char            hashSpec[LUKS_HASHSPEC_L];
+		uint32_t        payloadOffset;
+		uint32_t        keyBytes;
+		char            mkDigest[LUKS_DIGESTSIZE];
+		char            mkDigestSalt[LUKS_SALTSIZE];
+		uint32_t        mkDigestIterations;
+		char            uuid[UUID_STRING_L];
+
+		struct {
+			uint32_t active;
+
+			/* parameters used for password processing */
+			uint32_t passwordIterations;
+			char     passwordSalt[LUKS_SALTSIZE];
+
+			/* parameters used for AF store/load */
+			uint32_t keyMaterialOffset;
+			uint32_t stripes;
+		} keyblock[LUKS_NUMKEYS];
+	} *header;
+
+	header = (struct luks_phdr*) volume_id_get_buffer(id, off, LUKS_PHDR_SIZE);
+
+	if (header == NULL)
+		return -1;
+
+	if (memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L))
+		return -1;
+
+	volume_id_set_usage(id, VOLUME_ID_CRYPTO);
+	volume_id_set_uuid(id, header->uuid, UUID_DCE_UNPARSED);
+
+	id->type = "crypto_LUKS";
+
+	return 0;
+}
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/luks.h hal-cvs/volume_id/luks.h
--- hal-cvs-vanilla/volume_id/luks.h	1969-12-31 18:00:00.000000000 -0600
+++ hal-cvs/volume_id/luks.h	2005-02-14 21:30:31.000000000 -0600
@@ -0,0 +1,26 @@
+/*
+ * volume_id - reads filesystem label and uuid
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers at vrfy.org>
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation; either
+ *	version 2.1 of the License, or (at your option) any later version.
+ *
+ *	This library is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ *	Lesser General Public License for more details.
+ *
+ *	You should have received a copy of the GNU Lesser General Public
+ *	License along with this library; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VOLUME_ID_EXT_
+#define _VOLUME_ID_EXT_
+
+extern int volume_id_probe_luks(struct volume_id *id, __u64 off);
+
+#endif
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/Makefile.am hal-cvs/volume_id/Makefile.am
--- hal-cvs-vanilla/volume_id/Makefile.am	2005-02-07 15:24:16.000000000 -0600
+++ hal-cvs/volume_id/Makefile.am	2005-02-14 21:29:51.000000000 -0600
@@ -12,6 +12,7 @@
 	linux_raid.h		linux_raid.c		\
 	linux_swap.h		linux_swap.c		\
 	lvm.h			lvm.c			\
+	luks.h			luks.c			\
 	mac.h			mac.c			\
 	msdos.h			msdos.c			\
 	ntfs.h			ntfs.c			\
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/util.c hal-cvs/volume_id/util.c
--- hal-cvs-vanilla/volume_id/util.c	2005-02-07 15:24:16.000000000 -0600
+++ hal-cvs/volume_id/util.c	2005-02-16 15:42:27.000000000 -0600
@@ -53,6 +53,8 @@
 		return "raid";
 	case VOLUME_ID_DISKLABEL:
 		return "disklabel";
+	case VOLUME_ID_CRYPTO:
+		return "crypto";
 	case VOLUME_ID_UNPROBED:
 		return "unprobed";
 	case VOLUME_ID_UNUSED:
@@ -136,6 +138,10 @@
 		break;
 	case UUID_DCE:
 		count = 16;
+		break;
+	case UUID_DCE_UNPARSED:
+		count = 36;
+		break;
 	}
 	memcpy(id->uuid_raw, buf, count);
 
@@ -170,6 +176,10 @@
 			buf[8], buf[9],
 			buf[10], buf[11], buf[12], buf[13], buf[14],buf[15]);
 		break;
+	case UUID_DCE_UNPARSED:
+		memcpy(id->uuid, buf, count);
+		id->uuid[count] = 0x00;
+		break;
 	}
 }
 
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/util.h hal-cvs/volume_id/util.h
--- hal-cvs-vanilla/volume_id/util.h	2005-02-07 15:24:16.000000000 -0600
+++ hal-cvs/volume_id/util.h	2005-02-16 15:35:10.000000000 -0600
@@ -67,6 +67,7 @@
 #endif
 
 enum uuid_format {
+	UUID_DCE_UNPARSED,
 	UUID_DCE,
 	UUID_DOS,
 	UUID_NTFS,
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/volume_id.c hal-cvs/volume_id/volume_id.c
--- hal-cvs-vanilla/volume_id/volume_id.c	2005-02-07 15:24:16.000000000 -0600
+++ hal-cvs/volume_id/volume_id.c	2005-02-16 15:42:53.000000000 -0600
@@ -46,6 +46,7 @@
 #include "fat.h"
 #include "hfs.h"
 #include "jfs.h"
+#include "luks.h"
 #include "xfs.h"
 #include "ufs.h"
 #include "ntfs.h"
@@ -76,6 +77,10 @@
 	if (volume_id_probe_highpoint_ataraid(id, off) == 0)
 		goto exit;
 
+	/* LUKS encrypted volume */
+	if (volume_id_probe_luks(id, off) == 0)
+		goto exit;
+
 	/* signature in the first block, only small buffer needed */
 	if (volume_id_probe_vfat(id, off) == 0)
 		goto exit;
diff -u --recursive --new-file hal-cvs-vanilla/volume_id/volume_id.h hal-cvs/volume_id/volume_id.h
--- hal-cvs-vanilla/volume_id/volume_id.h	2005-02-07 15:24:16.000000000 -0600
+++ hal-cvs/volume_id/volume_id.h	2005-02-15 21:29:24.000000000 -0600
@@ -38,6 +38,7 @@
 	VOLUME_ID_PARTITIONTABLE,
 	VOLUME_ID_RAID,
 	VOLUME_ID_DISKLABEL,
+	VOLUME_ID_CRYPTO,
 };
 
 struct volume_id_partition {
-------------- next part --------------
_______________________________________________
hal mailing list
hal at lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/hal


More information about the Hal mailing list