>From looking at the dm_crypt code, it appears that it can be
interrogated to report the current key. Some quick testing shows:
# dmsetup table /dev/mapper/volume1
0 2000000 crypt aes-plain 0123456789abcdef0123456789abcdef 0 7:0 0
Obviously, root can in principle recover this password from the
running kernel but it seems silly to make it so easy.
Moreover, it seems this facility exists to support some form of
automated table storage (LVM?). As we don't want anyone/anything
accidentally storing our passwords on disk in the clear, we probably
shouldn't facilitate this. Perhaps we can stick something here like
"<secret>" that the dm_crypt constructor can reject.
--
Mathematics is the supreme nostalgia of our time.
On Wed, Feb 02, 2005 at 01:19:16PM -0800, Matt Mackall wrote:
> # dmsetup table /dev/mapper/volume1
> 0 2000000 crypt aes-plain 0123456789abcdef0123456789abcdef 0 7:0 0
> Obviously, root can in principle recover this password from the
> running kernel but it seems silly to make it so easy.
There seemed little point obfuscating it - someone will only
write a trivial utility that recovers it.
The current approach has the advantage of making it
obvious to you that if you have root access, you have
access to the password while the encrypted data volumes
are mounted.
Consider instead *why* you're worried about the password being
held in RAM and look for better solutions to *your*
perceived threats.
Threat: Someone could run "dmsetup" while I've gone for a coffee
break leaving my laptop unattended logged on as root...
Threat: My laptop is stolen while it's got a screen saver running
(or suspended) and the thief could interrogate RAM and get the
password, giving them access to my encrypted data volumes.
Possible fixes: Automatically unmount those volumes before
starting the screen saver. Automatically unmount them
after a certain amount of inactivity. Require the password
to be re-entered at regular intervals. New risks: regular
entry of password means more chance of its being observed,
so consider one-time passwords to gain access to it, or
USB dongle periodically inserted etc. etc.
Alasdair
--
[email protected]
On Wed, Feb 02, 2005 at 11:50:02PM +0000, Alasdair G Kergon wrote:
> On Wed, Feb 02, 2005 at 01:19:16PM -0800, Matt Mackall wrote:
> > # dmsetup table /dev/mapper/volume1
> > 0 2000000 crypt aes-plain 0123456789abcdef0123456789abcdef 0 7:0 0
>
> > Obviously, root can in principle recover this password from the
> > running kernel but it seems silly to make it so easy.
>
> There seemed little point obfuscating it - someone will only
> write a trivial utility that recovers it.
So instead let's do the work for them? We could perhaps put it in the
root prompt. Pray tell, what is the value to the user of exposing the
whole password, ever?
> Consider instead *why* you're worried about the password being
> held in RAM and look for better solutions to *your*
> perceived threats.
My perceived threat, as I've already stated, is that automated suite
of utilities like LVM or EVMS or even initscripts will silently store
this information in the clear on disk in an effort to make life
easier, oblivious to the fact that it might contain security-sensitive
information.
What drives this perception is that the output of "dmsetup tables"
invites it: it appears tailor-made to be fed into a future "dmsetup
create". Thus someone clever (but unaware of dm_crypt) _will_
eventually try this if it's not already happening. Further, there is
nothing in the dmsetup manpage to suggest that its output should be
guarded, etc. See "principle of least surprise."
Given the potential risk of naive use of dmsetup tables, what's the
upside again?
--
Mathematics is the supreme nostalgia of our time.
Am Mittwoch, den 02.02.2005, 13:19 -0800 schrieb Matt Mackall:
> From looking at the dm_crypt code, it appears that it can be
> interrogated to report the current key. Some quick testing shows:
>
> # dmsetup table /dev/mapper/volume1
> 0 2000000 crypt aes-plain 0123456789abcdef0123456789abcdef 0 7:0 0
>
> Obviously, root can in principle recover this password from the
> running kernel but it seems silly to make it so easy.
I already tried that. It took me about five minutes using a shell, dd
and hexdump to get the key out of the running kernel...
> Moreover, it seems this facility exists to support some form of
> automated table storage (LVM?). As we don't want anyone/anything
> accidentally storing our passwords on disk in the clear, we probably
> shouldn't facilitate this. Perhaps we can stick something here like
> "<secret>" that the dm_crypt constructor can reject.
Yes, the reason is that the device-mapper supports on-the-fly
modifications of the device. cryptsetup has a command to resize the
mapping for example. It can do that without asking for the password
again. Features like this are the reason I'm doing this. Userspace tools
should be able to assume that they can use the result of a table status
command to create a new table with this information.
An alternativ would be to use some form of handle to point to the key
after it has been given to the kernel. But that would require some more
infrastructure.
I could imagine something like this:
Some kernel infrastructure for key management. It can hold keys which
are referenced by some form of handle. The keys are refcounted and wiped
if the reference count drops to zero.
If you want to create a dm-crypt mapping (or something else that uses
some form of cryptographic key) you create a new handle and assign the
key. Then you give the handle to dm-crypt which increments reference
count. When cryptsetup exits its reference to the key is dropped but the
key still has a reference from the active dm-crypt mapping. Later on
another application could then safely do something with that handle. As
long as an application or in-kernel user references the key it won't be
dropped so it's safe for a userspace application to play around with it.
BTW: The setkey command also seems to return the keys in use for IPSEC
connections.
On Thu, Feb 03, 2005 at 02:33:01AM +0100, Christophe Saout wrote:
> Am Mittwoch, den 02.02.2005, 13:19 -0800 schrieb Matt Mackall:
>
> > From looking at the dm_crypt code, it appears that it can be
> > interrogated to report the current key. Some quick testing shows:
> >
> > # dmsetup table /dev/mapper/volume1
> > 0 2000000 crypt aes-plain 0123456789abcdef0123456789abcdef 0 7:0 0
> >
> > Obviously, root can in principle recover this password from the
> > running kernel but it seems silly to make it so easy.
>
> I already tried that. It took me about five minutes using a shell, dd
> and hexdump to get the key out of the running kernel...
Indeed.
> Yes, the reason is that the device-mapper supports on-the-fly
> modifications of the device. cryptsetup has a command to resize the
> mapping for example. It can do that without asking for the password
> again. Features like this are the reason I'm doing this. Userspace tools
> should be able to assume that they can use the result of a table status
> command to create a new table with this information.
Hmm, interesting. A password per resize is not terribly onerous though.
> An alternativ would be to use some form of handle to point to the key
> after it has been given to the kernel. But that would require some more
> infrastructure.
There's been some talk about such infrastructure already. I believe
some pieces of it may already be in place.
> BTW: The setkey command also seems to return the keys in use for IPSEC
> connections.
While possibly suboptimal, this won't surprise anyone. But dmsetup has
no mention of security in its manpage and doesn't show keys in typical
LVM usage. So people might reasonably assume that data from dmsetup
tables is not secret.
--
Mathematics is the supreme nostalgia of our time.
Am Mittwoch, den 02.02.2005, 17:52 -0800 schrieb Matt Mackall:
> > An alternativ would be to use some form of handle to point to the key
> > after it has been given to the kernel. But that would require some more
> > infrastructure.
>
> There's been some talk about such infrastructure already. I believe
> some pieces of it may already be in place.
Yes, you are right. I didn't follow the discussion but it actually looks
very promising. The keys in the infrastructure are reference-counted.
That's good.
The keyrings can be attached to either thread, processes, sessions or
users.
It seems that it's possible to have floating keys (not attached to any
keyring). So we would just need to figure out how to use these keyrings
to allow communication with userspace applications. Process keyrings
seem to have the advantage that the keyring is dropped when it exits so
that all keys that are not in use by the kernel are also dropped. A
keyring for the root user would have the problem that if the cryptsetup
application aborts in the middle you would end up with old keys lying
around forever.
The keyring API seems very flexible. You can define your own type of
keys and give them names. Well, the name is probably irrelevant here and
should be chosen randomly but it's less likely to collide with someone
else.
On Thu, Feb 03, 2005 at 03:34:29AM +0100, Christophe Saout wrote:
> The keyring API seems very flexible. You can define your own type of
> keys and give them names. Well, the name is probably irrelevant here and
> should be chosen randomly but it's less likely to collide with someone
> else.
Dunno here, seems that having one tool that gave the kernel a key named
"foo" and then telling dm-crypt to use key "foo" is probably not a bad
way to go. Then we don't have stuff like "echo <key> | dmsetup create"
and the like and the key-handling smarts can all be put in one
separate place.
Getting from here to there might be interesting though. Perhaps we can
teach dm-crypt to understand keys of the form "keyname:<foo>"? in
addition to raw keys to keep compatibility. Might even be possible to
push this down into crypt_decode_key() (or a smarter variant of same).
Meanwhile, I'd still like to hide the raw key in crypt_status().
--
Mathematics is the supreme nostalgia of our time.
Am Mittwoch, den 02.02.2005, 20:05 -0800 schrieb Matt Mackall:
> On Thu, Feb 03, 2005 at 03:34:29AM +0100, Christophe Saout wrote:
> > The keyring API seems very flexible. You can define your own type of
> > keys and give them names. Well, the name is probably irrelevant here and
> > should be chosen randomly but it's less likely to collide with someone
> > else.
>
> Dunno here, seems that having one tool that gave the kernel a key named
> "foo" and then telling dm-crypt to use key "foo" is probably not a bad
> way to go. Then we don't have stuff like "echo <key> | dmsetup create"
> and the like and the key-handling smarts can all be put in one
> separate place.
Yes. I could also change cryptsetup to not mlockall the whole
application just because the key is passed down to libdevmapper which
does not treat parameters with special care.
> Getting from here to there might be interesting though. Perhaps we can
> teach dm-crypt to understand keys of the form "keyname:<foo>"? in
> addition to raw keys to keep compatibility. Might even be possible to
> push this down into crypt_decode_key() (or a smarter variant of same).
>
> Meanwhile, I'd still like to hide the raw key in crypt_status().
Well, I don't. I don't know any tools that actually use the
DM_DEVICE_TABLE command except cryptsetup. I don't like to make the
interface inconsistent just because there might be an incompetent root
sitting in front of the machine.
On Wed, 2005-02-02 at 20:05 -0800, Matt Mackall wrote:
> Dunno here, seems that having one tool that gave the kernel a key named
> "foo" and then telling dm-crypt to use key "foo" is probably not a bad
> way to go. Then we don't have stuff like "echo <key> | dmsetup create"
> and the like and the key-handling smarts can all be put in one
> separate place.
>
> Getting from here to there might be interesting though. Perhaps we can
> teach dm-crypt to understand keys of the form "keyname:<foo>"? in
> addition to raw keys to keep compatibility. Might even be possible to
> push this down into crypt_decode_key() (or a smarter variant of same).
Way too complicated. This is a crypto project, why does nobody think of
crypto to solve the problem :). Here's the idea:
Keys are handed to dm-crypt regularly the first time. But when dm-crypt
hands keys back to user space, it uses some sort of blinding to make the
keys meaningless for user space.
That can easily be done by generating a kernel internal secret after
boot, and then before handing out the keys to user space, XOR-ing the
kernel secret into the key. When these keys are handed back from user
space to the kernel, the process is reversed.
That's an effective blinding mechanism. The kernel has to remember
nothing but a single secret. No special out-of-band setup of "keyname:"
tokens, no additional management for these tokens and blinded key
becomes useless after reboot.
Of course, the blinded keys need to be distinguished from regular keys.
I propose to prepend "!" to the keys handed back to the user space, so
we have "!<hex..key>", and add a simple conditional post processing to
crypt_decode_key.
Of course, one can use encryption instead of XOR-ing with the kernel
secret as blinding mechanism, as the kernel secret can easily be
recovered by setting up a all-zero key. But the main intend of this
approach is to protect against incompetent roots and user space
programs, so I think this XOR OTP is sufficient, and further, trivially
to implement. (Actually it's a Multi Time Pad.)
--
Fruhwirth Clemens <[email protected]> http://clemens.endorphin.org
On Thu, Feb 03, 2005 at 03:18:20PM +0100, Fruhwirth Clemens wrote:
> (Actually it's a Multi Time Pad.)
And you call this "crypto"?
On Thu, 2005-02-03 at 15:47 +0100, Andries Brouwer wrote:
> On Thu, Feb 03, 2005 at 03:18:20PM +0100, Fruhwirth Clemens wrote:
>
> > (Actually it's a Multi Time Pad.)
>
> And you call this "crypto"?
Is the quoted part all you have read?
--
Fruhwirth Clemens <[email protected]> http://clemens.endorphin.org
On Thu, 2005-02-03 at 15:18 +0100, Fruhwirth Clemens wrote:
> On Wed, 2005-02-02 at 20:05 -0800, Matt Mackall wrote:
>
> > Dunno here, seems that having one tool that gave the kernel a key named
> > "foo" and then telling dm-crypt to use key "foo" is probably not a bad
> > way to go. Then we don't have stuff like "echo <key> | dmsetup create"
> > and the like and the key-handling smarts can all be put in one
> > separate place.
> >
> > Getting from here to there might be interesting though. Perhaps we can
> > teach dm-crypt to understand keys of the form "keyname:<foo>"? in
> > addition to raw keys to keep compatibility. Might even be possible to
> > push this down into crypt_decode_key() (or a smarter variant of same).
>
> Way too complicated. This is a crypto project, why does nobody think of
> crypto to solve the problem :). Here's the idea:
>
> Keys are handed to dm-crypt regularly the first time. But when dm-crypt
> hands keys back to user space, it uses some sort of blinding to make the
> keys meaningless for user space.
>
> That can easily be done by generating a kernel internal secret after
> boot, and then before handing out the keys to user space, XOR-ing the
> kernel secret into the key. When these keys are handed back from user
> space to the kernel, the process is reversed.
>
> That's an effective blinding mechanism. The kernel has to remember
> nothing but a single secret. No special out-of-band setup of "keyname:"
> tokens, no additional management for these tokens and blinded key
> becomes useless after reboot.
>
> Of course, the blinded keys need to be distinguished from regular keys.
> I propose to prepend "!" to the keys handed back to the user space, so
> we have "!<hex..key>", and add a simple conditional post processing to
> crypt_decode_key.
>
> Of course, one can use encryption instead of XOR-ing with the kernel
> secret as blinding mechanism, as the kernel secret can easily be
> recovered by setting up a all-zero key. But the main intend of this
> approach is to protect against incompetent roots and user space
> programs, so I think this XOR OTP is sufficient, and further, trivially
> to implement. (Actually it's a Multi Time Pad.)
I've been following this thread and i'm clearly at a loss as to how any
of this will prevent someone from writing a util to get the key?
Currently i'm trying to figure out exactly how one would prevent the key
from being retrieved. This after stumbling into dm-crypt almost 24 hours
ago and applying it into a system. Albeit, I haven't been thinking about
it long, none of the above will stop incompetent roots from leaving a
machine open with root. Subsequently, allowing one who's far less
incompetent from taking advantage of the machine. The only logical
solution seems to be perceived threats idea. Why put something into
place that isn't going to make it any more difficult? How about, don't
leave yourself logged in as root and if you're using scripts, etc make
sure they have the proper permissions set etc.
--
Christopher Warner
On Thu, 2005-02-03 at 05:15 -0500, Christopher Warner wrote:
> On Thu, 2005-02-03 at 15:18 +0100, Fruhwirth Clemens wrote:
> >
> > Keys are handed to dm-crypt regularly the first time. But when dm-crypt
> > hands keys back to user space, it uses some sort of blinding to make the
> > keys meaningless for user space.
> I've been following this thread and i'm clearly at a loss as to how any
> of this will prevent someone from writing a util to get the key?
This is not about trying to hide something which cannot be hidden.
See http://lkml.org/lkml/2005/2/2/256 . It's about a design that can
cope with unintentional program/user errors. Think of it as a trigger
safety.
--
Fruhwirth Clemens <[email protected]> http://clemens.endorphin.org
Hi!
> > # dmsetup table /dev/mapper/volume1
> > 0 2000000 crypt aes-plain 0123456789abcdef0123456789abcdef 0 7:0 0
>
> > Obviously, root can in principle recover this password from the
> > running kernel but it seems silly to make it so easy.
>
> There seemed little point obfuscating it - someone will only
> write a trivial utility that recovers it.
>
> The current approach has the advantage of making it
> obvious to you that if you have root access, you have
> access to the password while the encrypted data volumes
> are mounted.
>
> Consider instead *why* you're worried about the password being
> held in RAM and look for better solutions to *your*
> perceived threats.
Actually, this *is* bad. I bet someone is going to post their secret
key to lkml when debugging...
Or I can see conversation like this:
admin: "My devices work too slowly, is there something wrong with
device mapper?"
Pavel walks to his console, says: "Okay, show me your
/dev/mapper/volume1"
admin does that.
For this to be usefull Pavel'd have to remember the key before admin
realizes what he has done, but..... Or imagine pavel shoulder-surfing
admin trying to debug device mapper.
Pavel
--
People were complaining that M$ turns users into beta-testers...
...jr ghea gurz vagb qrirybcref, naq gurl frrz gb yvxr vg gung jnl!
On Thu, Feb 03, 2005 at 03:18:20PM +0100, Fruhwirth Clemens wrote:
> Way too complicated. This is a crypto project, why does nobody think of
> crypto to solve the problem :). Here's the idea:
> [see original post, http://lkml.org/lkml/2005/2/3/109 , for idea]
Very simple patch. With that, it's really hard for root to reveal his real
keys accidentally.
Of course the intended
dmsetup table foo > foo-table
dmsetup remove foo
dmsetup create foo foo-table
works. If anyone is interested in that feature, this fellow has to clean the
patch and push it.
--- linux-2.6.11-rc1-mm1-therp/drivers/md/dm-crypt.c.orig 2005-02-04 12:53:57.000000000 +0100
+++ linux-2.6.11-rc1-mm1-therp/drivers/md/dm-crypt.c 2005-02-04 14:14:34.927560784 +0100
@@ -18,6 +18,7 @@
#include <asm/scatterlist.h>
#include <asm/page.h>
+#include <linux/random.h>
#include "dm.h"
#define PFX "crypt: "
@@ -488,6 +489,33 @@
queue_work(_kcryptd_workqueue, &io->work);
}
+/* Trigger safety */
+
+static char *asure_dc_secret(int want_size) {
+ static char *secret = NULL;
+ static int secret_size = 0;
+
+ // FIXME: obtain some lock
+ if(secret_size < want_size) {
+ char *new_secret = kmalloc(want_size,GFP_KERNEL);
+ // FIXME malloc fail check
+ if(secret) {
+ memcpy(new_secret, secret, secret_size);
+ kfree(secret);
+ }
+
+ get_random_bytes(new_secret+secret_size, want_size - secret_size);
+ secret = new_secret; secret_size = want_size;
+ }
+ return secret;
+}
+
+static void xor_with_secret(char *p, int size) {
+ char *secret = asure_dc_secret(size);
+ while(size--)
+ *p++ ^= *secret++;
+}
+
/*
* Decode key from its hex representation
*/
@@ -496,9 +524,14 @@
char buffer[3];
char *endp;
unsigned int i;
+ int post_process = 0;
buffer[2] = '\0';
+ if(*hex == '!') {
+ post_process = 1;
+ hex++;
+ }
for(i = 0; i < size; i++) {
buffer[0] = *hex++;
buffer[1] = *hex++;
@@ -512,6 +545,9 @@
if (*hex != '\0')
return -EINVAL;
+ if (post_process)
+ xor_with_secret(key,size);
+
return 0;
}
@@ -522,6 +558,7 @@
{
unsigned int i;
+ *hex++ = '!';
for(i = 0; i < size; i++) {
sprintf(hex, "%02x", *key);
hex += 2;
@@ -689,6 +726,8 @@
} else
cc->iv_mode = NULL;
+ xor_with_secret(cc->key, cc->key_size);
+
ti->private = cc;
return 0;
@@ -899,11 +938,11 @@
DMEMIT("%s-%s ", cipher, chainmode);
if (cc->key_size > 0) {
- if ((maxlen - sz) < ((cc->key_size << 1) + 1))
+ if ((maxlen - sz) < ((cc->key_size << 1) + 2))
return -ENOMEM;
crypt_encode_key(result + sz, cc->key, cc->key_size);
- sz += cc->key_size << 1;
+ sz += (cc->key_size << 1) + 1;
} else {
if (sz >= maxlen)
return -ENOMEM;
Am Mittwoch, den 02.02.2005, 20:05 -0800 schrieb Matt Mackall:
> Dunno here, seems that having one tool that gave the kernel a key named
> "foo" and then telling dm-crypt to use key "foo" is probably not a bad
> way to go. Then we don't have stuff like "echo <key> | dmsetup create"
> and the like and the key-handling smarts can all be put in one
> separate place.
>
> Getting from here to there might be interesting though. Perhaps we can
> teach dm-crypt to understand keys of the form "keyname:<foo>"? in
> addition to raw keys to keep compatibility. Might even be possible to
> push this down into crypt_decode_key() (or a smarter variant of same).
I've hacked together a working implementation. It's just a prototype
though. The patch requires that the key retention service is activated
unconditionally. It would probably be better to introduce #ifdefs and
the possibility turn of the cleartext key way in the kernel
configuration.
I've separated out the crypto configuration from the device-mapper
configuration. Several device mappings can now share/reference the same
key. This might be useful if you want to span your mapping over several
devices (without stacking device mappings on top of each other). So
basically the crypto and the device-mapper part of the configuration are
in its own "classes" now. It makes even more sense now to rename IV
operations to crypto/key operations (which only work on the new
structure) like it's done in the LRW patch.
This crypto configuration that I separated out can be referenced by the
device-mapper target directly (old way) or indirectly by the new key
retention service. It holds the cipher, chaining mode and IV mechanisms
as well as the key itself.
A dm table configuration line then looks like "0 1000000 crypt key
my_key_name 0 /dev/bla 0".
And dm-crypt.c is slowly getting large. Thirty functions already. Hmm.