cryptsetup: Add tcrypt support

Tcrypt uses a different approach to passphrases/key files. The
passphrase and all key files are incorporated into the "password"
to open the volume. So, the idea of slots that provide a way to
open the volume with different passphrases/key files that are
independent from each other like with LUKS does not apply.

Therefore, we use the key file from /etc/crypttab as the source
for the passphrase. The actual key files that are combined with
the passphrase into a password are provided as a new option in
/etc/crypttab and can be given multiple times if more than one
key file is used by a volume.
This commit is contained in:
Jan Janssen 2013-07-13 13:19:38 +02:00 committed by Lennart Poettering
parent 10fb4e35fd
commit 8cf3ca8068
3 changed files with 283 additions and 148 deletions

View file

@ -576,7 +576,7 @@ AC_SUBST(AUDIT_LIBS)
have_libcryptsetup=no
AC_ARG_ENABLE(libcryptsetup, AS_HELP_STRING([--disable-libcryptsetup], [disable libcryptsetup tools]))
if test "x$enable_libcryptsetup" != "xno"; then
PKG_CHECK_MODULES(LIBCRYPTSETUP, [ libcryptsetup >= 1.4.2 ],
PKG_CHECK_MODULES(LIBCRYPTSETUP, [ libcryptsetup >= 1.6.0 ],
[AC_DEFINE(HAVE_LIBCRYPTSETUP, 1, [Define if libcryptsetup is available]) have_libcryptsetup=yes], have_libcryptsetup=no)
if test "x$have_libcryptsetup" = xno -a "x$enable_libcryptsetup" = xyes; then
AC_MSG_ERROR([*** libcryptsetup support requested but libraries not found])

View file

@ -75,23 +75,29 @@
fields are mandatory, the remaining two are
optional.</para>
<para>Setting up encrypted block devices using this file
supports three encryption modes: LUKS, TrueCrypt and plain.
See <citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for more information about each mode. When no mode is specified
in the options field and the block device contains a LUKS
signature, it is opened as a LUKS device; otherwise, it is
assumed to be in raw dm-crypt (plain mode) format.</para>
<para>The first field contains the name of the
resulting encrypted block device; the device is set up
within <filename>/dev/mapper/</filename>.</para>
<para>The second field contains a path to the
underlying block device, or a specification of a block
underlying block device or file, or a specification of a block
device via <literal>UUID=</literal> followed by the
UUID. If the block device contains a LUKS signature,
it is opened as a LUKS encrypted partition; otherwise,
it is assumed to be a raw dm-crypt partition.</para>
UUID.</para>
<para>The third field specifies the encryption
password. If the field is not present or the password
is set to none, the password has to be manually
entered during system boot. Otherwise, the field is
interpreted as a path to a file containing the
encryption password. For swap encryption,
is set to <literal>none</literal> or <literal>-</literal>,
the password has to be manually entered during system boot.
Otherwise, the field is interpreted as a absolute path to
a file containing the encryption password. For swap encryption,
<filename>/dev/urandom</filename> or the hardware
device <filename>/dev/hw_random</filename> can be used
as the password file; using
@ -104,181 +110,237 @@
options are recognized:</para>
<variablelist class='crypttab-options'>
<varlistentry>
<term><varname>allow-discards</varname></term>
<listitem><para>Allow discard requests to be
passed through the encrypted block device. This
improves performance on SSD storage but has
security implications.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>cipher=</varname></term>
<listitem><para>Specifies the cipher
to use; see
<listitem><para>Specifies the cipher to use. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default
value of this option. A cipher with
unpredictable IV values, such as
<literal>aes-cbc-essiv:sha256</literal>,
is recommended. </para></listitem>
for possible values and the default value of
this option. A cipher with unpredictable IV
values, such as <literal>aes-cbc-essiv:sha256</literal>,
is recommended.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>size=</varname></term>
<term><varname>hash=</varname></term>
<listitem><para>Specifies the key size
in bits; see
<listitem><para>Specifies the hash to use for
password hashing. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default
value of this
option. </para></listitem>
for possible values and the default value of
this option.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>keyfile-offset=</varname></term>
<listitem><para>Specifies the number of bytes to
skip at the start of the key file. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default value of
this option.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>keyfile-size=</varname></term>
<listitem><para>Specifies the maximum number
of bytes to read from the keyfile; see
of bytes to read from the key file. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default
value of this option. This option is ignored
in plain encryption mode, as the keyfile-size is then given by the key size.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>keyfile-offset=</varname></term>
<listitem><para>Specifies the number
of bytes to skip at the start of
the keyfile; see
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default
value of this option.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>hash=</varname></term>
<listitem><para>Specifies the hash to
use for password hashing; see
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry> for possible values and
the default value of this
option. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tries=</varname></term>
<listitem><para>Specifies the maximum
number of times the user is queried
for a password.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>verify</varname></term>
<listitem><para> If the encryption
password is read from console, it has
to be entered twice (to prevent
typos). </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>read-only</varname></term><term><varname>readonly</varname></term>
<listitem><para>Set up the encrypted
block device in read-only
mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>allow-discards</varname></term>
<listitem><para>Allow discard requests
to be passed through the encrypted
block device. This improves
performance on SSD storage but has
security
implications.</para></listitem>
for possible values and the default value of
this option. This option is ignored in plain
encryption mode, as the key file size is then
given by the key size.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>luks</varname></term>
<listitem><para>Force LUKS mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>plain</varname></term>
<listitem><para>Force plain encryption
mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>timeout=</varname></term>
<listitem><para>Specify the timeout
for querying for a password. If no
unit is specified seconds is used.
Supported units are s, ms, us, min, h,
d. A timeout of 0 waits indefinitely
(which is the
default).</para></listitem>
<listitem><para>Force LUKS mode. When this mode
is used the following options are ignored since
they are provided by the LUKS header on the
device: <varname>cipher=</varname>,
<varname>hash=</varname>,
<varname>size=</varname>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>noauto</varname></term>
<listitem><para> This device will not
be automatically unlocked on
boot. </para></listitem>
<listitem><para>This device will not be
automatically unlocked on boot.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>nofail</varname></term>
<listitem><para>The system will not
wait for the device to show up and be
unlocked at boot, and not fail the
boot if it does not show
up.</para></listitem>
<listitem><para>The system will not wait for the
device to show up and be unlocked at boot, and
not fail the boot if it does not show up.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>plain</varname></term>
<listitem><para>Force plain encryption mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>read-only</varname></term><term><varname>readonly</varname></term>
<listitem><para>Set up the encrypted block
device in read-only mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>size=</varname></term>
<listitem><para>Specifies the key size
in bits. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for possible values and the default value of
this option.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>swap</varname></term>
<listitem><para> The encrypted block
device will be used as a swap
partition, and will be formatted as a
swap partition after setting up the
encrypted block device, with
<citerefentry><refentrytitle>mkswap</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<listitem><para>The encrypted block device will
be used as a swap device, and will be formatted
accordingly after setting up the encrypted
block device, with
<citerefentry><refentrytitle>mkswap</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
This option implies <varname>plain</varname>.</para>
<para>WARNING: Using the
<varname>swap</varname> option will
destroy the contents of the named
partition during every boot, so make
sure the underlying block device is
specified
correctly. </para></listitem>
<para>WARNING: Using the <varname>swap</varname>
option will destroy the contents of the named
partition during every boot, so make sure the
underlying block device is specified correctly.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tcrypt</varname></term>
<listitem><para>Use TrueCrypt encryption mode.
When this mode is used the following options are
ignored since they are provided by the TrueCrypt
header on the device or do not apply:
<varname>cipher=</varname>,
<varname>hash=</varname>,
<varname>keyfile-offset=</varname>,
<varname>keyfile-size=</varname>,
<varname>size=</varname>.</para>
<para>When this mode is used, the passphrase is
read from the key file given in the third field.
Only the first line of this file is read,
excluding the new line character.</para>
<para>Note that the TrueCrypt format uses both
passphrase and key files to derive a password
for the volume. Therefore, the passphrase and
all key files need to be provided. Use
<varname>tcrypt-keyfile=</varname> to provide
the absolute path to all key files. When using
an empty passphrase in combination with one or
more key files, use <literal>/dev/null</literal>
as the password file in the third field.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tcrypt-hidden</varname></term>
<listitem><para>Use the hidden TrueCrypt volume.
This implies <varname>tcrypt</varname>.</para>
<para>This will map the hidden volume that is
inside of the volume provided in the second
field. Please note that there is no protection
for the hidden volume if the outer volume is
mounted instead. See
<citerefentry><refentrytitle>cryptsetup</refentrytitle><manvolnum>8</manvolnum></citerefentry>
for more information on this limitation.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tcrypt-keyfile=</varname></term>
<listitem><para>Specifies the absolute path to a
key file to use for a TrueCrypt volume. This
implies <varname>tcrypt</varname> and can be
used more than once to provide several key
files.</para>
<para>See the entry for <varname>tcrypt</varname>
on the behavior of the passphrase and key files
when using TrueCrypt encryption mode.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tcrypt-system</varname></term>
<listitem><para>Use TrueCrypt in system
encryption mode. This implies
<varname>tcrypt</varname>.</para>
<para>Please note that when using this mode, the
whole device needs to be given in the second
field instead of the partition. For example: if
<literal>/dev/sda2</literal> is the system
encrypted TrueCrypt patition, <literal>/dev/sda</literal>
has to be given.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>timeout=</varname></term>
<listitem><para>Specifies the timeout for
querying for a password. If no unit is
specified, seconds is used. Supported units are
s, ms, us, min, h, d. A timeout of 0 waits
indefinitely (which is the default).</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tmp</varname></term>
<listitem><para>The encrypted block
device will be prepared for using it
as <filename>/tmp</filename>
partition: it will be formatted using
<citerefentry><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<listitem><para>The encrypted block device will
be prepared for using it as <filename>/tmp</filename>;
it will be formatted using
<citerefentry><refentrytitle>mke2fs</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
This option implies <varname>plain</varname>.</para>
<para>WARNING: Using the
<varname>tmp</varname> option will
destroy the contents of the named
partition during every boot, so make
sure the underlying block device is
specified
correctly. </para></listitem>
<para>WARNING: Using the <varname>tmp</varname>
option will destroy the contents of the named
partition during every boot, so make sure the
underlying block device is specified correctly.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>tries=</varname></term>
<listitem><para>Specifies the maximum number of
times the user is queried for a password.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>verify</varname></term>
<listitem><para> If the encryption password is
read from console, it has to be entered twice to
prevent typos.</para></listitem>
</varlistentry>
</variablelist>
<para>At early boot and when the system manager
@ -291,12 +353,14 @@
<title>Example</title>
<example>
<title>/etc/crypttab example</title>
<para>Set up two encrypted block devices with
LUKS: one normal one for storage, and another
one for usage as swap device.</para>
<para>Set up four encrypted block devices. One using
LUKS for normal storage, another one for usage as a swap
device and two TrueCrypt volumes.</para>
<programlisting>luks-2505567a-9e27-4efe-a4d5-15ad146c258b UUID=2505567a-9e27-4efe-a4d5-15ad146c258b - timeout=0
swap /dev/sda7 /dev/urandom swap</programlisting>
<programlisting>luks UUID=2505567a-9e27-4efe-a4d5-15ad146c258b
swap /dev/sda7 /dev/urandom swap
truecrypt /dev/sda2 /etc/container_password tcrypt
hidden /mnt/tc_hidden /null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile</programlisting>
</example>
</refsect1>

View file

@ -27,6 +27,7 @@
#include <libcryptsetup.h>
#include <libudev.h>
#include "fileio.h"
#include "log.h"
#include "util.h"
#include "path-util.h"
@ -34,7 +35,7 @@
#include "ask-password-api.h"
#include "def.h"
static const char *opt_type = NULL; /* LUKS1 or PLAIN */
static const char *opt_type = NULL; /* CRYPT_LUKS1, CRYPT_TCRYPT or CRYPT_PLAIN */
static char *opt_cipher = NULL;
static unsigned opt_key_size = 0;
static unsigned opt_keyfile_size = 0;
@ -44,6 +45,9 @@ static unsigned opt_tries = 0;
static bool opt_readonly = false;
static bool opt_verify = false;
static bool opt_discards = false;
static bool opt_tcrypt_hidden = false;
static bool opt_tcrypt_system = false;
static char **opt_tcrypt_keyfiles = NULL;
static usec_t opt_timeout = 0;
/* Options Debian's crypttab knows we don't:
@ -82,6 +86,14 @@ static int parse_one_option(const char *option) {
return 0;
}
} else if (startswith(option, "tcrypt-keyfile=")) {
opt_type = CRYPT_TCRYPT;
if (path_is_absolute(option+15))
opt_tcrypt_keyfiles = strv_append(opt_tcrypt_keyfiles, strdup(option+15));
else
log_error("Key file path '%s' is not absolute. Ignoring.", option+15);
} else if (startswith(option, "keyfile-size=")) {
if (safe_atou(option+13, &opt_keyfile_size) < 0) {
@ -121,7 +133,15 @@ static int parse_one_option(const char *option) {
opt_discards = true;
else if (streq(option, "luks"))
opt_type = CRYPT_LUKS1;
else if (streq(option, "plain") ||
else if (streq(option, "tcrypt"))
opt_type = CRYPT_TCRYPT;
else if (streq(option, "tcrypt-hidden")) {
opt_type = CRYPT_TCRYPT;
opt_tcrypt_hidden = true;
} else if (streq(option, "tcrypt-system")) {
opt_type = CRYPT_TCRYPT;
opt_tcrypt_system = true;
} else if (streq(option, "plain") ||
streq(option, "swap") ||
streq(option, "tmp"))
opt_type = CRYPT_PLAIN;
@ -301,6 +321,53 @@ static int get_password(const char *name, usec_t until, bool accept_cached, char
return 0;
}
static int attach_tcrypt(struct crypt_device *cd,
const char *name,
const char *key_file,
char **passwords,
uint32_t flags) {
int r = 0;
_cleanup_free_ char *passphrase = NULL;
struct crypt_params_tcrypt params = {
.flags = CRYPT_TCRYPT_LEGACY_MODES,
.keyfiles = (const char **)opt_tcrypt_keyfiles,
.keyfiles_count = strv_length(opt_tcrypt_keyfiles)
};
assert(cd);
assert(name);
assert(key_file || passwords);
if (opt_tcrypt_hidden)
params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
if (opt_tcrypt_system)
params.flags |= CRYPT_TCRYPT_SYSTEM_HEADER;
if (key_file) {
r = read_one_line_file(key_file, &passphrase);
if (r < 0) {
log_error("Failed to read password file '%s': %s", key_file, strerror(-r));
return -EAGAIN;
}
params.passphrase = passphrase;
} else
params.passphrase = passwords[0];
params.passphrase_size = strlen(params.passphrase);
r = crypt_load(cd, CRYPT_TCRYPT, &params);
if (r < 0) {
if (key_file && r == -EPERM) {
log_error("Failed to activate using password file '%s'.", key_file);
return -EAGAIN;
}
return r;
}
return crypt_activate_by_volume_key(cd, name, NULL, 0, flags);;
}
static int attach_luks_or_plain(struct crypt_device *cd,
const char *name,
const char *key_file,
@ -450,7 +517,7 @@ int main(int argc, char *argv[]) {
!streq(argv[4], "none")) {
if (!path_is_absolute(argv[4]))
log_error("Password file path %s is not absolute. Ignoring.", argv[4]);
log_error("Password file path '%s' is not absolute. Ignoring.", argv[4]);
else
key_file = argv[4];
}
@ -532,7 +599,10 @@ int main(int argc, char *argv[]) {
goto finish;
}
k = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags);
if (streq_ptr(opt_type, CRYPT_TCRYPT))
k = attach_tcrypt(cd, argv[2], key_file, passwords, flags);
else
k = attach_luks_or_plain(cd, argv[2], key_file, passwords, flags);
if (k >= 0)
break;
else if (k == -EAGAIN) {
@ -583,6 +653,7 @@ finish:
free(opt_cipher);
free(opt_hash);
strv_free(opt_tcrypt_keyfiles);
return r;
}