[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: New patches out for 2.2 and 2.4.



On Sun, Jan 07, 2001 at 11:52:53AM +0100, Dr. Ernst Molitor wrote:
> Dear Alexander, 
> 
> thank you very much for your work on kernel-int, which is most
> valuable.
> 
> With the 2.4.0.1 patch and the util-linux patch applied to
> util-linux...[or].tar.gz, I'm able to create and use new encrypted
> file systems via loop, but I seem unable to access those created under
> the latest 2.2.17 kernel-int patches. Trying to mount with, e.g.,
> 
> 	 mount -t ext2 -oloop,encryption=blowfish .crypto crypto
> 
> will lead to a passphrase dialog, then exit with an error message
> like 
> 
>    ioctl: LOOP_SET_STATUS ...
> 
> Trying one of the cipher names that appear in /proc/crypto/ciphers
> works fine for newly added ciphers, only, as far as I can see; 
> using the full name (that is, with -cbc or -ecb added), leads to
> error messages all the time ("cipher not supported"), regardless of
> how I try to escape the dash from being interpreted as an option 
> lead in by the shell...
> 
> I'd very much appreciate a hint on what my mistake could be...
> 

It's a bug in the util-linux patch.  For "old" ciphers (i.e. twofish,
blowfish and others that worked in previous versions of util-linux),
it will try to use the LOOP_SET_STATUS ioctl wrongly.

The attached patch should hopefully fix that by first trying the
new-style ioctl, and then falling back to the old-style ioctl if it
didn't work.

astor

-- 
Alexander Kjeldaas                Mail:  astor@fast.no
finger astor@master.kernel.org for OpenPGP key.
diff -urN util-linux-2.10o.int3/mount/lomount.c util-linux-2.10o.int2/mount/lomount.c
--- util-linux-2.10o.int3/mount/lomount.c	Sun Jan  7 03:32:14 2001
+++ util-linux-2.10o.int2/mount/lomount.c	Sun Jan  7 03:36:30 2001
@@ -44,6 +44,7 @@
 extern char *xstrdup (const char *s);	/* not: #include "sundries.h" */
 extern void error (const char *fmt, ...);	/* idem */
 
+
 struct cipher_info
 {
 	const char *name;
@@ -53,38 +54,13 @@
 	int key_schedule_size;
 };
 
-
-static int get_cipher_info(const char *name, struct cipher_info *res)
-{
-	char path[PATH_MAX];
-	char buf[2000];
-	FILE *f;
-	struct {
-		int *out;
-		const char *prefix;
-	} fields[] = {{&res->blocksize, "blocksize:"},
-		      {&res->keysize_mask, "keysize_mask:"},
-		      {&res->ivsize, "ivsize:"},
-		      {&res->key_schedule_size, "key_schedule_size:"}};
-	snprintf(path, sizeof(path), "/proc/crypto/cipher/%s", name);
-	f = fopen(path, "r");
-	while(f && fgets(buf, sizeof(buf), f)) {
-		int i;
-		for (i = 0; i < sizeof(fields)/sizeof(fields[0]); i++) {
-			int len = strlen(fields[i].prefix);
-			if (strncmp(buf, fields[i].prefix, len) == 0) {
-				*fields[i].out = strtoul(&buf[len+1], NULL, 0);
-				break;
-			}
-		}
-		
-	}
-	if (!f) 
-		return -1;
-	return 0;
-}
-
-
+static int set_loop_passwd(struct loop_info *_loopinfo, int pfd, int keysz,
+			   const char *encryption, int fd, int ffd);
+static int get_cipher_info(const char *name, struct cipher_info *res);
+static int name_to_id(const char *name);
+#ifdef MAIN
+static char *id_to_name(int id);
+#endif
 
 #ifdef LOOP_SET_FD
 struct crypt_type_struct {
@@ -103,29 +79,7 @@
 	{ -1, NULL,0   }
 };
 
-static int 
-crypt_type (const char *name) {
-	int i;
-
-	if (name) {
-		for (i = 0; crypt_type_tbl[i].id != -1; i++)
-			if (!strcasecmp (name, crypt_type_tbl[i].name))
-				return crypt_type_tbl[i].id;
-	}
-	return LO_CRYPT_CRYPTOAPI;
-}
-
 #ifdef MAIN
-static char *
-crypt_name (int id) {
-	int i;
-
-	for (i = 0; crypt_type_tbl[i].id != -1; i++)
-		if (id == crypt_type_tbl[i].id)
-			return crypt_type_tbl[i].name;
-	return "undefined";
-}
-
 static int
 show_loop (char *device) {
 	struct loop_info loopinfo;
@@ -147,7 +101,7 @@
 	printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
 		device, loopinfo.lo_device, loopinfo.lo_inode,
 		loopinfo.lo_name, loopinfo.lo_offset,
-		crypt_name (loopinfo.lo_encrypt_type));
+		id_to_name(loopinfo.lo_encrypt_type));
 	close (fd);
 
 	return 0;
@@ -213,12 +167,12 @@
 		error(_(
 		    "mount: Could not find any loop device, and, according to %s,\n"
 		    "       this kernel does not know about the loop device.\n"
-		    "       (If so, then recompile or `insmod loop.o'.)"),
+		    "       (If so, then recompile or `modprobe loop'.)"),
 		      PROC_DEVICES);
 	    else
 		error(_(
 		    "mount: Could not find any loop device. Maybe this kernel does not know\n"
-		    "       about the loop device (then recompile or `insmod loop.o'), or\n"
+		    "       about the loop device (then recompile or `modprobe loop'), or\n"
 		    "       maybe /dev/loop# has the wrong major number?"));
 	} else
 		error(_("mount: could not find any free loop device"));
@@ -270,12 +224,7 @@
 set_loop (const char *device, const char *file, int offset,
 	  const char *encryption, int pfd, int keysz, int *loopro) {
 	struct loop_info loopinfo;
-	int fd, ffd, mode, i;
-	int keylength;
-	char *pass;
-	char keybits[2*HASHLENGTH]; 
-	char passwdbuff[PASSWDBUFFLEN];
-	struct cipher_info info;
+	int fd, ffd, mode, tried_old;
 
 	mode = (*loopro ? O_RDONLY : O_RDWR);
 	if ((ffd = open (file, mode)) < 0) {
@@ -293,14 +242,10 @@
 	*loopro = (mode == O_RDONLY);
 
 	memset (&loopinfo, 0, sizeof (loopinfo));
-	strncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
+	snprintf(loopinfo.lo_name, sizeof(loopinfo.lo_name),
+		 "%s-cbc", encryption);
 	loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
-	if (encryption && (loopinfo.lo_encrypt_type = crypt_type (encryption))
-	    < 0) {
-		fprintf (stderr, _("Unsupported encryption type %s\n"),
-			 encryption);
-		return 1;
-	}
+	loopinfo.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
 	loopinfo.lo_offset = offset;
 
 #ifdef MCL_FUTURE  
@@ -315,29 +260,75 @@
 		exit(1);
 	}
 #endif
+	
+	if (ioctl (fd, LOOP_SET_FD, ffd) < 0) {
+		perror ("ioctl: LOOP_SET_FD");
+		return 1;
+	}
 
-	switch (loopinfo.lo_encrypt_type) {
+	tried_old = 0;
+again:
+	set_loop_passwd(&loopinfo, pfd, keysz, encryption, fd, ffd);
+	
+	if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
+		/* Try again with old-style LO_CRYPT_XX if
+                   new-style LO_CRYPT_CRYPTOAPI ioctl didn't work */
+		if (tried_old) {
+			error("The cipher does not exist, or a cipher module "
+			      "needs to be loaded into the kernel");
+			perror ("ioctl: LOOP_SET_STATUS");
+			goto out_ioctl;
+		}
+		strncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
+		loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
+		loopinfo.lo_encrypt_type = name_to_id (encryption);
+		tried_old = 1;
+		goto again;
+	}
+	close (fd);
+	close (ffd);
+	if (verbose > 1)
+		printf(_("set_loop(%s,%s,%d): success\n"),
+		       device, file, offset);
+	return 0;
+out_ioctl:
+	(void) ioctl (fd, LOOP_CLR_FD, 0);
+	return 1;
+}
+
+int
+set_loop_passwd(struct loop_info *loopinfo, int pfd, int keysz, 
+		const char *encryption, int fd, int ffd)
+{
+	int i;
+	int keylength;
+	char *pass;
+	char keybits[2*HASHLENGTH]; 
+	char passwdbuff[PASSWDBUFFLEN];
+	struct cipher_info info;
+
+	switch (loopinfo->lo_encrypt_type) {
 	case LO_CRYPT_NONE:
-		loopinfo.lo_encrypt_key_size = 0;
+		loopinfo->lo_encrypt_key_size = 0;
 		break;
 	case LO_CRYPT_XOR:
           /* WARNING: xgetpass() can return massive amounts of data,
            * not only 128 bytes like the original getpass(3) */
 		pass = xgetpass (pfd,_("Password: "));
-		strncpy (loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE);
-		loopinfo.lo_encrypt_key[LO_KEY_SIZE - 1] = 0;
-		loopinfo.lo_encrypt_key_size = strlen(loopinfo.lo_encrypt_key);
+		strncpy (loopinfo->lo_encrypt_key, pass, LO_KEY_SIZE);
+		loopinfo->lo_encrypt_key[LO_KEY_SIZE - 1] = 0;
+		loopinfo->lo_encrypt_key_size = strlen(loopinfo->lo_encrypt_key);
 		break;
 	case LO_CRYPT_DES:
 		printf(_("WARNING: Use of DES is depreciated.\n"));
 		pass = xgetpass (pfd,_("Password: "));
-		strncpy (loopinfo.lo_encrypt_key, pass, 8);
-		loopinfo.lo_encrypt_key[8] = 0;
-		loopinfo.lo_encrypt_key_size = 8;
+		strncpy (loopinfo->lo_encrypt_key, pass, 8);
+		loopinfo->lo_encrypt_key[8] = 0;
+		loopinfo->lo_encrypt_key_size = 8;
 		pass = getpass (_("Init (up to 16 hex digits): "));
 		for (i = 0; i < 16 && pass[i]; i++)
 			if (isxdigit (pass[i])) {
-				loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ?
+				loopinfo->lo_init[i >> 3] |= (pass[i] > '9' ?
 				  (islower (pass[i]) ? toupper (pass[i]) :
 				   pass[i])-'A'+10 : pass[i]-'0') << (i&7) * 4;
 			} else {
@@ -355,28 +346,21 @@
 		passwdbuff[0] = 'A';
 		rmd160_hash_buffer(keybits,pass,strlen(pass));
 		rmd160_hash_buffer(keybits+HASHLENGTH,passwdbuff,strlen(pass)+1);
-		memcpy((char*)loopinfo.lo_encrypt_key,keybits,2*HASHLENGTH);
+		memcpy((char*)loopinfo->lo_encrypt_key,keybits,2*HASHLENGTH);
 		keylength=0;
 		for(i=0; crypt_type_tbl[i].id != -1; i++){
-		         if(loopinfo.lo_encrypt_type == crypt_type_tbl[i].id){
+		         if(loopinfo->lo_encrypt_type == crypt_type_tbl[i].id){
 			         keylength = crypt_type_tbl[i].keylength;
 				 break;
 			 }
 		}
-		loopinfo.lo_encrypt_key_size=keylength;
+		loopinfo->lo_encrypt_key_size=keylength;
 		break;
 	case LO_CRYPT_CRYPTOAPI:
-		snprintf(loopinfo.lo_name, sizeof(loopinfo.lo_name),
-			 "%s-cbc", encryption);
-		loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
 		/* Give the kernel an opportunity to load the cipher */
-		(void) ioctl (fd, LOOP_SET_FD, ffd);
 		(void) ioctl (fd, LOOP_SET_STATUS, &loopinfo);
-		(void) ioctl (fd, LOOP_CLR_FD, 0);
-		if (get_cipher_info(loopinfo.lo_name, &info) < 0) {
-			error("The cipher does not exist, or a cipher module "
-			      "needs to be loaded into the kernel");
-			goto out_ioctl;
+		if (get_cipher_info(loopinfo->lo_name, &info) < 0) {
+			return 1;
 		}
 		if (keysz > 0 &&
 		    !((1 << ((keysz / 8) - 1)) & info.keysize_mask)) {
@@ -392,8 +376,7 @@
 			char keysize[200];
 			printf("Available keysizes (bits): ");
 			for (; i < 32; i++) {
-				if (info.keysize_mask & (1 << i) &&
-				    8*(i+1) <= 160) {
+				if (info.keysize_mask & (1 << i)) {
 					printf("%d ", 8*(i+1));
 					available = 1;
 				}
@@ -411,36 +394,23 @@
 		passwdbuff[0] = 'A';
 		rmd160_hash_buffer(keybits,pass,strlen(pass));
 		rmd160_hash_buffer(keybits+HASHLENGTH,passwdbuff,strlen(pass)+1);
-		memcpy((char*)loopinfo.lo_encrypt_key,keybits,2*HASHLENGTH);
+		memcpy((char*)loopinfo->lo_encrypt_key,keybits,2*HASHLENGTH);
 
-		loopinfo.lo_encrypt_key_size=keysz/8;
+		loopinfo->lo_encrypt_key_size=keysz/8;
 
 		break;
 	default:
 		fprintf (stderr,
 			 _("Don't know how to get key for encryption system %d\n"),
-			 loopinfo.lo_encrypt_type);
-		return 1;
-	}
-	if (ioctl (fd, LOOP_SET_FD, ffd) < 0) {
-		perror ("ioctl: LOOP_SET_FD");
+			 loopinfo->lo_encrypt_type);
 		return 1;
 	}
-	if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
-		perror ("ioctl: LOOP_SET_STATUS");
-		goto out_ioctl;
-	}
-	close (fd);
-	close (ffd);
-	if (verbose > 1)
-		printf(_("set_loop(%s,%s,%d): success\n"),
-		       device, file, offset);
-	return 0;
-out_ioctl:
-	(void) ioctl (fd, LOOP_CLR_FD, 0);
-	return 1;
+        return 0;
 }
 
+
+
+
 int 
 del_loop (const char *device) {
 	int fd;
@@ -638,3 +608,60 @@
 }
 #endif
 #endif
+
+static int get_cipher_info(const char *name, struct cipher_info *res)
+{
+	char path[PATH_MAX];
+	char buf[2000];
+	FILE *f;
+	struct {
+		int *out;
+		const char *prefix;
+	} fields[] = {{&res->blocksize, "blocksize:"},
+		      {&res->keysize_mask, "keysize_mask:"},
+		      {&res->ivsize, "ivsize:"},
+		      {&res->key_schedule_size, "key_schedule_size:"}};
+	snprintf(path, sizeof(path), "/proc/crypto/cipher/%s", name);
+	f = fopen(path, "r");
+	while(f && fgets(buf, sizeof(buf), f)) {
+		int i;
+		for (i = 0; i < sizeof(fields)/sizeof(fields[0]); i++) {
+			int len = strlen(fields[i].prefix);
+			if (strncmp(buf, fields[i].prefix, len) == 0) {
+				*fields[i].out = strtoul(&buf[len+1], NULL, 0);
+				break;
+			}
+		}
+		
+	}
+	if (!f) 
+		return -1;
+	return 0;
+}
+
+
+static int 
+name_to_id(const char *name) 
+{
+	int i;
+
+	if (name) {
+		for (i = 0; crypt_type_tbl[i].id != -1; i++)
+			if (!strcasecmp (name, crypt_type_tbl[i].name))
+				return crypt_type_tbl[i].id;
+	}
+	return LO_CRYPT_CRYPTOAPI;
+}
+
+#ifdef MAIN
+static char *
+id_to_name(int id) {
+	int i;
+
+	for (i = 0; crypt_type_tbl[i].id != -1; i++)
+		if (id == crypt_type_tbl[i].id)
+			return crypt_type_tbl[i].name;
+	return "undefined";
+}
+#endif
+