#850756 cryptsetup: Please save password to kernel keyring

Package:
cryptsetup
Source:
cryptsetup
Description:
disk encryption support - startup scripts
Submitter:
Laurent Bigonville
Date:
2018-12-24 23:51:02 UTC
Severity:
wishlist
#850756#5
Date:
2017-01-09 22:58:11 UTC
From:
To:
Hi,

Since gdm 3.22, there is a new pam module that unlock the gnome-keyring
using the keyring using the password of the luks partition.

The idea is that on a single user laptop, the user uses the same
password for his encrypted root and user in addition to autologin.

Tje pam module read the kernel keyring to find that password with the
followin code:

        serial = find_key_by_type_and_desc ("user", "cryptsetup", 0);
        if (serial == 0)
                return PAM_AUTHINFO_UNAVAIL;

        r = keyctl_read_alloc (serial, &cached_password);

So it would be nice if cryptsetup could store that password in the
keyring after opening successfully the main luks partition.

Regards,

Laurent Bigonville

#850756#12
Date:
2017-01-10 00:07:00 UTC
From:
To:
On Mon, 09 Jan 2017 23:58:11 +0100 Laurent Bigonville <bigon@debian.org>  wrote:
 > Hi,
 >
 > Since gdm 3.22, there is a new pam module that unlock the gnome-keyring
 > using the keyring using the password of the luks partition.
 >
 > The idea is that on a single user laptop, the user uses the same
 > password for his encrypted root and user in addition to autologin.
 >
 > Tje pam module read the kernel keyring to find that password with the
 > followin code:
 >
 > serial = find_key_by_type_and_desc ("user", "cryptsetup", 0);
 > if (serial == 0)
 > return PAM_AUTHINFO_UNAVAIL;
 >
 > r = keyctl_read_alloc (serial, &cached_password);
 >
 > So it would be nice if cryptsetup could store that password in the
 > keyring after opening successfully the main luks partition.

Looking at systemd, I see that they are doing something similar:

serial = add_key("user", keyname, p, n, KEY_SPEC_USER_KEYRING);

with keyname="cryptsetup"

I see two options here, either debian/askpass.c is modified to either
call add_key() function directly or "--keyname=cryptsetup" is passed to
systemd-ask-password.

Or the keyctl command line is used with something like: keyctl add user
cryptsetup my_password @u

#850756#17
Date:
2017-01-10 00:33:55 UTC
From:
To:
Don't think this should happen automatically... after all there are n
non-single-user-laptop scenarios, and while GDM/GNOME may be targeted
primarily towards only this scenario, Debian should not.


Cheers,
Chris.

#850756#22
Date:
2017-01-10 09:26:01 UTC
From:
To:
On Tue, 10 Jan 2017 01:33:55 +0100 Christoph Anton Mitterer
<calestyo@scientia.net> wrote:
 > On Mon, 2017-01-09 at 23:58 +0100, Laurent Bigonville wrote:
 > > Since gdm 3.22, there is a new pam module that unlock the gnome-
 > > keyring
 > > using the keyring using the password of the luks partition.
 > >
 > > The idea is that on a single user laptop, the user uses the same
 > > password for his encrypted root and user in addition to autologin.
 >
 > Don't think this should happen automatically... after all there are n
 > non-single-user-laptop scenarios, and while GDM/GNOME may be targeted
 > primarily towards only this scenario, Debian should not.

Well we need this to be integrated in cryptsetup if we want this to work.

Do you have any specific concerns about enabling this automatically?
Anything in mind that might break?

#850756#27
Date:
2017-01-10 13:37:23 UTC
From:
To:
Especially in the security-relevant context it's IMO always
questionable whether everything should work automagically out-of-the-
box.
Basically three:

- From what you wrote it wasn't clear to me, whether the auto-login
  would happen per default, i.e. without the sysadmin (and not just a
  user) enabling it, or not.
  Many people (especially on not-just-single-user-desktop) may likely
  not want such auto-login.

- Security-wise it's particularly bad to made such sensitive material
  as the key accessible to such a big piece of software-bloat.
  Looking at gdm3 it has quite an amount of direct and indirect
  dependencies including such which seem to communicate with the
  internet (e.g. gdm3 built on top of gnome shell, which uses gnome-
  online-accounts.
  Such crucial things as the dm-crypt keys/passphrase should IMO be
  used with as little as possible code.

- The whole "utopia" code has shown at least once that it may have
  tremendous security flaws, I vaguely remember some hole in some of
  devicekit/udisk/polkit, which lead to exporting the dm-crypt keys to
  ever user (may be #576687, which I recall here... or something else).


Instead of unconditionally adding the key to the keyring, why not just
including a keyscript in the package, which allows users to do just
that?
Maybe one can combine this with the already existing decrypt_keyctl.


Cheers,
Chris.

#850756#32
Date:
2017-01-10 16:28:41 UTC
From:
To:
Le 10/01/17 à 14:37, Christoph Anton Mitterer a écrit :

So the only question here should be: does it introduce a security risk
or not.

And any software running as root can extract the key I think if the luks
partition is already open.

No, the user needs to explicitly enable the autologin. If the autologin
is enabled, the pam_gdm module will be called and try to retrieve the
password for the kernel keyring and use it to try to unlock the
gnome-keyring. And anyway even if gdm was enabling auto-login by
default, this is not a concern for cryptsetup.

Isn't that true for any pam service as the pam module code is run in the
process context?

Note that only the gdm-session-worker process is running as root,
gnome-shell and the rest is running as Debian-gdm user and thus doesn't
have access to the root user's kernel keyring.

a keyscript might be a solution but it would requires manual setup from
the enduser.

Note also that the decrypt_keyctl script is also using the kernel
keyring to store the keys, so for a security POV it's the same IMHO

#850756#37
Date:
2017-01-10 17:00:05 UTC
From:
To:
I think having something like a keyscript, which needs to be manually
enabled by root, is friendly enough, isn't it?
It's the e.g. the same as with libpam-krb5 - that doesn't just happen
unconditionally but at least requires installation of that extra
package.
Well not necessarily in the sense of a concrete hole/bug - I'm rather
talking about an increased attack surface.
Not sure about that,... probably... but maybe not under things like
SELiux where even root can be restricted.
IIRC, at least normal cryptsetup binary still requires a valid
key[file] when doing operations like dumping the master key, even if
the device is already mapped... or do I remember wrong?
hmm that's IMO already unfortunate... I think only root should be able
to do such thing.
In which sense? pam is rather small, less code - less attack surface.
Sure, but still a bigger attack surface... one never knows by which
update such sensitive information is e.g. passed on via IPC...
But this isn't too much, is it?

And apart from that, running a "fully encrypted" system (and desiring
to single-user-auto-login with that) IMO only makes sense if the owner
of the system keeps something like a USB stick and boots from it for
many attack scenarios.
The notable exception is random theft of the device.

For any attack, where the owner is specifically targeted, the attacker
would rather simply exchange the (unencrypted) kernel on the harddisk
with a rogue version - which is why one needs to boot from USB (and
always have that with oneself) in order to circumvent this (more or
less).
This setup however, requires anyway manual steps by the user/admin.
Sure, but it's still something and admin needs to enable.


btw: One could also think about all this possibly allowing some where
obscure attacks.
Imagine a system where the a valid local user (who tries to attack dm-
crypt) has no physical access to the storage devices.
He also has no access to the dm-crypt device i.e. he cannot even try to
manually set up/guess the dm-crypt key.

Now when he's the one (an not root) who controls that exporting of the
dm-crypt key respectively it's use in auto-login respectively whether
auto-login is performed for his user acc... one can imagine that this
can be used to guess&confirm the passphrase - simply by changing the
user password and trying whether auto-login succeeds or not.

Sure, this is likely not a practicable attack, but it kinda shows that
such things may have tremendous security impact in special setups - and
I'm rather scared about attack vectors I cannot imagine ;-)


Cheers,
Chris.

#850756#42
Date:
2018-04-13 16:01:27 UTC
From:
To:
On Mon, 09 Jan 2017 23:58:11 +0100 Laurent Bigonville <bigon@debian.org>  wrote:

 > Hi,
 >
 > Since gdm 3.22, there is a new pam module that unlock the gnome-keyring
 > using the keyring using the password of the luks partition.
 >
 > The idea is that on a single user laptop, the user uses the same
 > password for his encrypted root and user in addition to autologin.
 >
 > Tje pam module read the kernel keyring to find that password with the
 > followin code:
 >
 > serial = find_key_by_type_and_desc ("user", "cryptsetup", 0);
 > if (serial == 0)
 > return PAM_AUTHINFO_UNAVAIL;
 >
 > r = keyctl_read_alloc (serial, &cached_password);
 >
 > So it would be nice if cryptsetup could store that password in the
 > keyring after opening successfully the main luks partition.
 >
 > Regards,

OK, what could be done for this?

I guess that askpass could store the password in the keyring if a flag
is passed to it asking for it?

Would that be a viable solution?

The difficult part would be to detect a wrong password and not store it
I guess?

#850756#47
Date:
2018-12-24 23:48:23 UTC
From:
To:
Hi Laurent,

I just had a look at this and as I wrote in #917067's message 65:

| AFAICT, when systemd tries to open a LUKS device, it starts by searching
| in the user keyring for a key named “cryptsetup”.  If found, the content
| is interpreted as a NUL-delimited list of passphrases, each one being
| successfully tried against the device to open.  At this point, if the
| device is still locked, the user is prompted for the passphrase until
| the device opens, or until the maximum number of tries exceeds; moreover
| each passphrase entered (whether it's valid or not) is appended to the
| NUL-delimited list contained in the key named “cryptsetup”.
|
| However I'm personally extremely reluctant to adopt such logic in
| src:cryptsetup (for instance in cryptdisks_start(8) or in our initramfs
| scripts), because 1/ splitting on NUL bytes breaks binary passphrases,
| which are currently allowed through askpass' passfifo; and 2/
| successively trying each passphrase previously entered is a waste of time
| and resources, especially with modern PBKDFs.

Does this pam module splits on NUL bytes as well, or take the raw
content of the user keyring?

I assume you want the passphrase used for unlocking at initramfs stage
to be used later?  Then `systemd-ask-password --keyname=cryptsetup`
isn't an option, because systemd-ask-password(1) is not copied to the
initramfs image.

IMHO caching passphrases passed to askpass should not be the default.
Since Linux 4.10 it's possible to offload volume keys of dm-crypt
targets to the kernel keyring.  This is the default for LUKS2 devices
(due to be the default LUKS format some time early next year), and such
volumes keys can't be read by userspace.  Hence caching passphrases,
even with a timeout, does change the threat model somewhat.

Moreover, the order in which dm-crypt devices are mapped at initramfs
stage is currently undocumented.  Not a big deal, we could certainly
document that, but what if there are several targets?  Should we try to
use the last cached value before prompting the user?  I'm really not
keen on caching all passphrases (valid or not) in a NUL-separated list
like systemd does.  If there are several passphrases for the targets,
should we keep only the first one, or should the later one override it?

Our ‘decrypt_keyctl’ keyscript can be used for that.  Currently the key
name is hardcoded to "cryptkey-$CRYPTTAB_KEY" (where $CRYPTTAB_KEY is
the value of the 3rd column), but it's an implementation detail and we
could change that to "cryptsetup" when $CRYPTTAB_KEY has a special value
like "none".  (Conveniently "none" has a special meaning when there is
no keyscript, and used to to have vague semantics with keyscripts, cf.
#826124.)

We could also add a crypttab(5) flag like “cache” and implement the
caching logic in askpass (checking whether the CRYPTTAB_OPTION_cache
environment variable is set), but I don't see the advantage over
decrypt_keyctl.  Moreover, introducing new crypttab(5) options is
sub-optimal since it increases our delta with the systemd
implementation.

Cheers,