Commit 1f2d8de9 authored by Milan Broz's avatar Milan Broz

Support VeraCrypt devices (TrueCrypt extension).

Add CRYPT_TCRYPT_VERA_MODES libcryptswtup flag and
--veracrypt option.

Fixes issue#245.
parent dced2694
......@@ -405,7 +405,7 @@ struct crypt_params_tcrypt {
uint32_t flags; /**< CRYPT_TCRYPT* flags */
};
/** Include legacy modes ehn scannig for header*/
/** Include legacy modes for header*/
#define CRYPT_TCRYPT_LEGACY_MODES (1 << 0)
/** Try to load hidden header (describing hidden device) */
#define CRYPT_TCRYPT_HIDDEN_HEADER (1 << 1)
......@@ -413,6 +413,8 @@ struct crypt_params_tcrypt {
#define CRYPT_TCRYPT_BACKUP_HEADER (1 << 2)
/** Device contains encrypted system (with boot loader) */
#define CRYPT_TCRYPT_SYSTEM_HEADER (1 << 3)
/** Include Veracrypt modes for header*/
#define CRYPT_TCRYPT_VERA_MODES (1 << 4)
/** @} */
......
/*
* TCRYPT (TrueCrypt-compatible) volume handling
* TCRYPT (TrueCrypt-compatible) and VeraCrypt volume handling
*
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
* Copyright (C) 2012-2014, Milan Broz
* Copyright (C) 2012-2015, Milan Broz
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -33,16 +33,23 @@
/* TCRYPT PBKDF variants */
static struct {
unsigned int legacy:1;
unsigned int veracrypt:1;
const char *name;
const char *hash;
unsigned int iterations;
} tcrypt_kdf[] = {
{ 0, "pbkdf2", "ripemd160", 2000 },
{ 0, "pbkdf2", "ripemd160", 1000 },
{ 0, "pbkdf2", "sha512", 1000 },
{ 0, "pbkdf2", "whirlpool", 1000 },
{ 1, "pbkdf2", "sha1", 2000 },
{ 0, NULL, NULL, 0 }
{ 0, 0, "pbkdf2", "ripemd160", 2000 },
{ 0, 0, "pbkdf2", "ripemd160", 1000 },
{ 0, 0, "pbkdf2", "sha512", 1000 },
{ 0, 0, "pbkdf2", "whirlpool", 1000 },
{ 1, 0, "pbkdf2", "sha1", 2000 },
{ 0, 1, "pbkdf2", "sha512", 500000 },
{ 0, 1, "pbkdf2", "whirlpool", 500000 },
{ 0, 1, "pbkdf2", "sha256", 500000 }, // VeraCrypt 1.0f
{ 0, 1, "pbkdf2", "sha256", 200000 }, // boot only
{ 0, 1, "pbkdf2", "ripemd160", 655331 },
{ 0, 1, "pbkdf2", "ripemd160", 327661 }, // boot only
{ 0, 0, NULL, NULL, 0 }
};
struct tcrypt_alg {
......@@ -196,7 +203,7 @@ static int TCRYPT_hdr_from_disk(struct tcrypt_phdr *hdr,
/* Convert header to cpu format */
hdr->d.version = be16_to_cpu(hdr->d.version);
hdr->d.version_tc = le16_to_cpu(hdr->d.version_tc);
hdr->d.version_tc = be16_to_cpu(hdr->d.version_tc);
hdr->d.keys_crc32 = be32_to_cpu(hdr->d.keys_crc32);
......@@ -393,13 +400,13 @@ out:
}
static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
const char *key, int legacy_modes)
const char *key, uint32_t flags)
{
struct tcrypt_phdr hdr2;
int i, j, r = -EINVAL;
for (i = 0; tcrypt_cipher[i].chain_count; i++) {
if (!legacy_modes && tcrypt_cipher[i].legacy)
if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy)
continue;
log_dbg("TCRYPT: trying cipher %s-%s",
tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode);
......@@ -431,6 +438,13 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
r = i;
break;
}
if ((flags & CRYPT_TCRYPT_VERA_MODES) &&
!strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
log_dbg("TCRYPT: Signature magic detected (Veracrypt).");
memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
r = i;
break;
}
r = -EPERM;
}
......@@ -485,7 +499,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
size_t passphrase_size;
char *key;
unsigned int i, skipped = 0;
int r = -EPERM, legacy_modes;
int r = -EPERM;
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
return -ENOMEM;
......@@ -512,9 +526,10 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
for (i = 0; i < params->passphrase_size; i++)
pwd[i] += params->passphrase[i];
legacy_modes = params->flags & CRYPT_TCRYPT_LEGACY_MODES ? 1 : 0;
for (i = 0; tcrypt_kdf[i].name; i++) {
if (!legacy_modes && tcrypt_kdf[i].legacy)
if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy)
continue;
if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt)
continue;
/* Derive header key */
log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
......@@ -533,7 +548,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
break;
/* Decrypt header */
r = TCRYPT_decrypt_hdr(cd, hdr, key, legacy_modes);
r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags);
if (r == -ENOENT) {
skipped++;
r = -EPERM;
......@@ -553,10 +568,11 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
r = TCRYPT_hdr_from_disk(hdr, params, i, r);
if (!r) {
log_dbg("TCRYPT: Header version: %d, req. %d, sector %d"
log_dbg("TCRYPT: Magic: %s, Header version: %d, req. %d, sector %d"
", mk_offset %" PRIu64 ", hidden_size %" PRIu64
", volume size %" PRIu64, (int)hdr->d.version,
(int)hdr->d.version_tc, (int)hdr->d.sector_size,
", volume size %" PRIu64, tcrypt_kdf[i].veracrypt ?
VCRYPT_HDR_MAGIC : TCRYPT_HDR_MAGIC,
(int)hdr->d.version, (int)hdr->d.version_tc, (int)hdr->d.sector_size,
hdr->d.mk_offset, hdr->d.hidden_volume_size, hdr->d.volume_size);
log_dbg("TCRYPT: Header cipher %s-%s, key size %zu",
params->cipher, params->mode, params->key_size);
......@@ -1026,11 +1042,13 @@ int TCRYPT_dump(struct crypt_device *cd,
struct tcrypt_phdr *hdr,
struct crypt_params_tcrypt *params)
{
log_std(cd, "TCRYPT header information for %s\n",
log_std(cd, "%s header information for %s\n",
hdr->d.magic[0] == 'T' ? "TCRYPT" : "VERACRYPT",
device_path(crypt_metadata_device(cd)));
if (hdr->d.version) {
log_std(cd, "Version: \t%d\n", hdr->d.version);
log_std(cd, "Driver req.:\t%d\n", hdr->d.version_tc);
log_std(cd, "Driver req.:\t%x.%x\n", hdr->d.version_tc >> 8,
hdr->d.version_tc & 0xFF);
log_std(cd, "Sector size:\t%" PRIu32 "\n", hdr->d.sector_size);
log_std(cd, "MK offset:\t%" PRIu64 "\n", hdr->d.mk_offset);
......
......@@ -29,6 +29,7 @@
#define TCRYPT_HDR_LEN 448
#define TCRYPT_HDR_KEY_LEN 192
#define TCRYPT_HDR_MAGIC "TRUE"
#define VCRYPT_HDR_MAGIC "VERA"
#define TCRYPT_HDR_MAGIC_LEN 4
#define TCRYPT_HDR_HIDDEN_OFFSET_OLD -1536
......
......@@ -419,8 +419,9 @@ size).
.PP
See also section 7 of the FAQ and \fBhttp://loop-aes.sourceforge.net\fR
for more information regarding loop-AES.
.SH TCRYPT (TrueCrypt-compatible) EXTENSION
cryptsetup supports mapping of TrueCrypt or tcplay encrypted partition
.SH TCRYPT (TrueCrypt-compatible and VeraCrypt) EXTENSION
cryptsetup supports mapping of TrueCrypt, tcplay or VeraCrypt
(with \fB\-\-veracrypt\fR option) encrypted partition
using a native Linux kernel API.
Header formatting and TCRYPT header change is not supported, cryptsetup
never changes TCRYPT header on-device.
......@@ -438,6 +439,11 @@ Cryptsetup should recognize all header variants, except legacy cipher chains
using LRW encryption mode with 64 bits encryption block (namely Blowfish
in LRW mode is not recognized, this is limitation of kernel crypto API).
To recognize VeraCrypt device use \fB\-\-veracrypt\fR option.
VeraCrypt is just extension of TrueCrypt header with increased
iteration count so unlocking can take quite a lot of time (in comparison
with TCRYPT device).
\fBNOTE:\fR Activation with \fBtcryptOpen\fR is supported only for cipher chains
using LRW or XTS encryption modes.
......
......@@ -63,6 +63,7 @@ static int opt_test_passphrase = 0;
static int opt_tcrypt_hidden = 0;
static int opt_tcrypt_system = 0;
static int opt_tcrypt_backup = 0;
static int opt_veracrypt = 0;
static const char **action_argv;
static int action_argc;
......@@ -288,7 +289,8 @@ static int action_open_tcrypt(void)
struct crypt_params_tcrypt params = {
.keyfiles = opt_keyfiles,
.keyfiles_count = opt_keyfiles_count,
.flags = CRYPT_TCRYPT_LEGACY_MODES,
.flags = CRYPT_TCRYPT_LEGACY_MODES |
(opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
};
const char *activated_name;
uint32_t activate_flags = 0;
......@@ -361,7 +363,8 @@ static int action_tcryptDump(void)
struct crypt_params_tcrypt params = {
.keyfiles = opt_keyfiles,
.keyfiles_count = opt_keyfiles_count,
.flags = CRYPT_TCRYPT_LEGACY_MODES,
.flags = CRYPT_TCRYPT_LEGACY_MODES |
(opt_veracrypt ? CRYPT_TCRYPT_VERA_MODES : 0),
};
int r;
......@@ -1505,6 +1508,7 @@ int main(int argc, const char **argv)
{ "tcrypt-hidden", '\0', POPT_ARG_NONE, &opt_tcrypt_hidden, 0, N_("Use hidden header (hidden TCRYPT device)."), NULL },
{ "tcrypt-system", '\0', POPT_ARG_NONE, &opt_tcrypt_system, 0, N_("Device is system TCRYPT drive (with bootloader)."), NULL },
{ "tcrypt-backup", '\0', POPT_ARG_NONE, &opt_tcrypt_backup, 0, N_("Use backup (secondary) TCRYPT header."), NULL },
{ "veracrypt", '\0', POPT_ARG_NONE, &opt_veracrypt, 0, N_("Scan also for VeraCrypt compatible device."), NULL },
{ "type", 'M', POPT_ARG_STRING, &opt_type, 0, N_("Type of device metadata: luks, plain, loopaes, tcrypt."), NULL },
{ "force-password", '\0', POPT_ARG_NONE, &opt_force_password, 0, N_("Disable password quality check (if enabled)."), NULL },
{ "perf-same_cpu_crypt",'\0', POPT_ARG_NONE, &opt_perf_same_cpu_crypt, 0, N_("Use dm-crypt same_cpu_crypt performance compatibility option."), NULL },
......@@ -1609,6 +1613,8 @@ int main(int argc, const char **argv)
} else if (!strcmp(aname, "tcryptOpen")) {
aname = "open";
opt_type = "tcrypt";
} else if (!strcmp(aname, "tcryptDump")) {
opt_type = "tcrypt";
} else if (!strcmp(aname, "remove") ||
!strcmp(aname, "plainClose") ||
!strcmp(aname, "luksClose") ||
......@@ -1724,6 +1730,11 @@ int main(int argc, const char **argv)
_("Option --tcrypt-hidden cannot be combined with --allow-discards.\n"),
poptGetInvocationName(popt_context));
if (opt_veracrypt && strcmp(opt_type, "tcrypt"))
usage(popt_context, EXIT_FAILURE,
_("Option --veracrypt is supported only for TCRYPT device type.\n"),
poptGetInvocationName(popt_context));
if (opt_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);
......
......@@ -70,23 +70,23 @@ export LANG=C
[ ! -d $TST_DIR ] && tar xjf tcrypt-images.tar.bz2
echo "HEADER CHECK"
for file in $(ls $TST_DIR/tc_*) ; do
for file in $(ls $TST_DIR/[tv]c_*) ; do
echo -n " $file"
echo $PASSWORD | $CRYPTSETUP tcryptDump $file >/dev/null || fail
echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt $file >/dev/null || fail
echo " [OK]"
done
echo "HEADER CHECK (HIDDEN)"
for file in $(ls $TST_DIR/tc_*-hidden) ; do
for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
echo -n " $file (hidden)"
echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptDump --tcrypt-hidden $file >/dev/null || fail
echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptDump --tcrypt-hidden --veracrypt $file >/dev/null || fail
echo " [OK]"
done
echo "HEADER KEYFILES CHECK"
for file in $(ls $TST_DIR/tck_*) ; do
for file in $(ls $TST_DIR/[tv]ck_*) ; do
echo -n " $file"
echo $PASSWORD | $CRYPTSETUP tcryptDump -d $TST_DIR/keyfile1 -d $TST_DIR/keyfile2 $file >/dev/null || fail
echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt -d $TST_DIR/keyfile1 -d $TST_DIR/keyfile2 $file >/dev/null || fail
echo " [OK]"
done
......@@ -97,9 +97,9 @@ if [ $(id -u) != 0 ]; then
fi
echo "ACTIVATION FS UUID CHECK"
for file in $(ls $TST_DIR/tc_*) ; do
for file in $(ls $TST_DIR/[tv]c_*) ; do
echo -n " $file"
out=$(echo $PASSWORD | $CRYPTSETUP tcryptOpen -r $file $MAP 2>&1)
out=$(echo $PASSWORD | $CRYPTSETUP tcryptOpen --veracrypt -r $file $MAP 2>&1)
ret=$?
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
......@@ -113,9 +113,9 @@ for file in $(ls $TST_DIR/tc_*) ; do
done
echo "ACTIVATION FS UUID (HIDDEN) CHECK"
for file in $(ls $TST_DIR/tc_*-hidden) ; do
for file in $(ls $TST_DIR/[tv]c_*-hidden) ; do
echo -n " $file"
out=$(echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptOpen -r $file $MAP --tcrypt-hidden 2>&1)
out=$(echo $PASSWORD_HIDDEN | $CRYPTSETUP tcryptOpen --veracrypt -r $file $MAP --tcrypt-hidden 2>&1)
ret=$?
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT legacy mode" ) && echo " [N/A]" && continue
[ $ret -eq 1 ] && ( echo "$out" | grep -q -e "TCRYPT compatible mapping" ) && echo " [N/A]" && continue
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment