[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
+