[Pkg-cryptsetup-devel] cryptsetup keyscript-framework / OpenPGP keyscript

David Härdeman david at hardeman.nu
Tue Jun 24 18:01:23 UTC 2008


On Tue, Jun 24, 2008 at 05:12:03PM +0200, Christoph Anton Mitterer wrote:
>On Mon, 2008-06-23 at 20:59 +0200, David Härdeman wrote:
>> To elaborate on the hint I gave before...my current preference would be 
>> that if a keyscript is called without any parameters, it prints a list 
>> to stdout of all applications it depends on, one per line.
>I remember this,... the main problem is that current keyscripts use
>simply $1 instead of looking for an option like [--]source <filename>.
>Unfortunately I assume that you're not willing to change this, are you?

Current keyscripts (that are in cryptsetup SVN) would have to be adapted 
of course.

>While I agree with you that printing out the deps when no parameter is
>used at all I think that this might lead to new problems if we ever want
>to extend the capabilities of keyscripts again (e.g. I can think of a
>mechanism that the right keyscript is chosen automatically depending on
>the key itself, thus a keyscript must be able to tell which key-types it
>can handle).

Sorry, I can't follow this argument.

>Another reason against it is, that it breaks with the usage of
>initramfs-hooks/scripts where "prereq" is expected...

keyscripts are not initramfs hooks.

>I'd strongly suggest to keep it homogen with the hooks/scripts,... but
>then we'd have the problem, that we either have to:
>a) change the current way keyscripts work (use [--]source <filename>
>parameter)
>b) use prereq and don't allow people to use "prereq" as filename

What's the benefit?

>c) use "" like you suggested.

No...argv[1] == "" is not the same as no argv[1].

>Personally I'd prefer a),.. because I think there are not so much
>scripts,... and I consider this to be the cleanest solution (consistency
>with hooks/scripts).
>Both b) and c) have the disadvantage that you cannot use "prereq" and/or
>(at leas I assume this) "none" as filename.

As I said in the first mail...."none" is already the standard for no 
keyfile...so a keyscript that might expect it would have to handle 
"none" as argv[1] in the current situation anyway...

>> If calling a keyscript with no parameters generates that list, we
>> could 
>> easily do a separate pass at the end of the cryptsetup initramfs hook 
>> that does something like this:
>> IFS='
>> '
>> for script in $(ls -1 "${dst}/where/all/keyscripts/are/"); do
>> 	list=$($script)
>> 	for item in $list; do
>> 		copy_exec "$item"
>> 	done
>> done
>I wouldn't suggest this! What you do here is simply copy_exec the
>binaries that are printed by the keyscripts. This is less mighty than my
>solution (where this would be done by separate scripts) because there
>might be keyscripts, that need "more" than just copy_exec a binary.
>
>Think of smartcard support for gpg,.. where you might not only want to
>copy gpg and pcscd to the initrd,... but also scan for the right library
>to be used (e.g. libccid or libtowkito or whatever)... ok stupid
>example, but got the point?

No, because the only thing that can "scan" for the correct libraries is 
the keyscript itself...so the keyscript (in the unlikely case that it 
dlopen's a library) would need to output that library as one of the 
dependencies. All dynamically linked libraries are copied automatically 
by copy_exec as is today. In addition, copy_exec works fine with e.g. 
text files as well....are you sure that you've fully understood how 
copy_exec works?

>And the same as above: To keep this consistent with the "normal"
>initramfs-hooks, I'd suggest that the dependencies are other
>hook-scripts (that solve the dependencies).

Again, keyscripts are not initramfs hook scripts.

>> A second change that I think might make sense to add is to set 
>> environment variables with additional information (like cipher, 
>> keylength, etc). Then keyscripts that are interested can use that 
>> information in a backwards compatible manner.
>That's surely a nice idea :-)
>This remembers me to the tries/timeout thing....
>Who is actually handling this now? They keyscript or someting
>"above" (you've mentioned askpass or so?)?

Timeout is not correctly handled in many situations (or even most 
situations). If I look into my magic crystal ball it says that the 
timeout option will probably disappear in the future.

Tries is handled by the cryptsetup init scripts and initramfs scripts. 
Keyscripts are expected to provide one try only (and the keyscript will 
be executed $tries number of times).

>> However, I'm not sure these changes are a good idea to do pre-Lenny as 
>> large changes close to a release is generally a bad idea.
>You could just upload them to unstable but not to testing?

If we upload it to unstable we can't do any last minute changes to 
testing since testing changes need to come from unstable.

>> >mount_usb_stick 1>&2 #secure that it doesn't write to stdout
>> >decrypt_openpgp "$1"
>> >umount_usb_stick
>> 
>> passdev would do this..."passdev /dev/disk/something:/my/file | gpg 
>> --blah --foo --bar --decrypt --readfromstdin --writetostdout"
>1) First of all I don't think passdev is (better said "can be") generic
>enough.
>I assume it simply tries to mount the device-part from device:file in
>crypttab, right?

Umm...I'm not sure I follow...passdev called with device:path as argv[1] 
will mount the device and read the file specified as argv[1].

>This doesn't allow to use LABEL or UUID,... and it does not allow to
>make things like "beep as soon as you can eject the key).

LABEL:

mypass=$(passdev device:/dev/disk/by-label/something)

UUID:

mypass=$(passdev device:/dev/disk/by-uuid/something)

BEEP:

mypass=$(passdev device:/dev/disk/whatever)
send_beep_ok_to_remove_dev()

>btw: Does it wait for the device to be created? (e.g. my USB-stick is
>not yet inserted or detected by the kernel/udev - the later happened in
>my setup,.. even though I'm booting from the very same stick)

passdev will wait until the dev is available yes...

>2) It breaks the specification of the 3rd fiel in crypttab. (This could
>and perhaps should be changed - I mean the specification for the 3rd
>field)

Why?

>3) Right now, you cannot combine it with a decrypt_* script, can you?
>And you cannot write both in crypttab like keyscript=passdev
>+decrypt_openpgp or so...

No, you get to call passdev from your custom script. (And you get to 
make sure that passdev is available in the initramfs...that will 
hopefully change in the future using the mechanism discussed before).

>4) And on the other side,.. there might be lot of situations (mostly
>when already booted) where all devices are already available...

So?

>> Only if you write your scripts in a non-clean manner...passdev
>> already solves this for you.
>see above,.. and please explain me how I'd have to use this with my
>decrypt_openpgp script?

I already did:

passdev device:path | gpg --lots --of --options --to-read-from-stdin 
                           --and-output-to-stdout

>> The current setup should be as secure as is currently feasible. Data
>> is piped to stdout by keyscripts and read from stdin by cryptsetup.
>What happens when using passdev? I mean the data-flow?

I suggest you read the source of passdev for now. But basically it waits 
for device to appear, mounts it in a tmp location, reads the path from 
the tmp location, umounts the tmp location and sends the contents of the 
file at path to stdout.

"passdev /dev/disk/by-label/mykey:/keys/secret" will wait for 
/dev/disk/by-label/mykey to appear, mount it somewhere (no need to care 
about where), read /keys/secret from the device, umount it and send the 
contents of /keys/secret to stdout.

>> This 
>> means the data passes through a pipe using kernel memory which is 
>> (unless I'm mistaken) not swapped to disk.
>I think so too,... but wasn't sure.
>
>>  In addition, the initramfs 
>> scripts run before swap is setup, so no swapping is possible. If run 
>> after the initramfs stage, swap should be encrypted (debian-installer 
>> has code to enforce it) so even if e.g. the keyscript application and 
>> it's memory is swapped, that should be encrypted.
>Of course... I've already written this,... but you'd still have "little"
>security problems,.. e.g. when someone gains root,... and can dd
>if=/dev/swapdevice...
>Ok,..this would mean that he can also get your data anyway...
>However,.. just wanted to say,... that I have a better feeling when the
>key is nowhere written to (which is obviously the case)

If someone has root on your system she can run dmsetup table --showkeys 
or just scp your entire fs to somewhere...game over...crypting your 
harddisk will not and cannot protect against a local root compromise no 
matter which setup you have.

>> Portable logging is a bit of a problem right now. "askpass" helps in 
>> some respects since it should handle password prompts in a generic 
>> manner for you.
>Is there any documentation for askpass??? ;P

Not much, but there isn't that much necessary really. Similarly to 
passdev it takes one argument (the user prompt) and sends the result to 
stdout.

password=$(askpass "Please input top secret key: ")

askpass will take care of the details like communicating with the 
console or with usplash to get a passphrase from the user. (And in the 
future it'll support splashy as well). We're going to use askpass for 
all passphrase prompts in the near future.

>> Using the lsb logging functions should also work both in 
>> initramfs and sysv-init script situations...but it's not ideal.
>And it probably doesn't support splashy/usplash/etc, does it?

I think usplash inserts it's own lsb logging functions if it's 
installed, shouldn't be that hard to check?

>>  Beyond 
>> passphrase prompts you should really be able to rely on the additional 
>> messages that the cryptsetup scripts print as much as possible...
>You mean I could cut most of my messages? Which of these are already
>handeled by cryptsetup's scripts? Probably decryption
>failed/succeeded ??

That's about it yes :)

>btw and before I forget it:
>How does cryptsetup and the scripts behave,.. I specify that a device is
>encrypted (in crypttab),... and I present the correct key on boot (e.g.
>via my USB-stick),.. but the filesystem is actually not encrypted?
>Will it be simply mounted and everything continues?

You'll get an error message since a mapping will be setup using the 
unencrypted device and a keyphrase for e.g. dm-crypt which will create a 
dm-crypt volume with gibberish.

>If so, I consider this a possible grave security leak,... which hast to
>be fixed.
>Because an attacker (that has access to you hardware) could exchange it
>with an unencrypted version,.. with en empty debian,.. that does nothing
>than stealing your key (for example).

An attacker with access to your hardware can replace your initramfs to 
log your input anyway. And if you have the initramfs on e.g. a usb key, 
I don't see how you believe that an unencrypted fs would steal your 
keypresses.

>>>For (5 & 8) but also for other points (like deciding whether the key
>>> may be written to "disk":
>> 
>> Your script should work for both initrd and non-initrd scenarios. 
>> Therefore it should never write to "disk". Therefore it should not
>> need 
>> to know where it is running because it should always use worst-case 
>> assumptions.
>Yeah,.. my mean reason behind this was: If I'm in the inird... I could
>use the /scripts/functions log-functions,... if not... I would use
>echo..
>So no way for this? Or a better way for logging?

That's on the TODO radar...to provide initramfs/sysv-agnostic logging 
functions but in general the lsb logging functions should (as far as I 
know and it's not my bug if it doesn't) provide the same functionality 
no matter what.

Regards :)

-- 
David Härdeman



More information about the Pkg-cryptsetup-devel mailing list