From 3c886ccff87b8c06a638d3d844f9e448f628fca9 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Tue, 29 Dec 2020 15:05:12 +0100 Subject: [PATCH] tcrypt: Support --hash and --cipher options to limit opening time. If user knows which particular PBKDF2 hash or cipher is used for True/VeraCrypt container, using --hash of --cipher option in tcryptDump and tcryptOpen can scan only these variants. Note for the cipher it means substring (all cipher chains containing the cipher are tried). For example, you can use cryptsetup tcryptDump --hash sha512 Note: for speed up, usually the hash option matters, cipher variants are scanned very quickly. Use witch care, in a script it can reveal some sensitive attribute of the container. Fixes #608. --- lib/tcrypt/tcrypt.c | 12 ++++++++---- man/cryptsetup.8 | 8 ++++++-- src/cryptsetup.c | 6 +++++- tests/tcrypt-compat-test | 5 +++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/tcrypt/tcrypt.c b/lib/tcrypt/tcrypt.c index 037244ee..a8f9aada 100644 --- a/lib/tcrypt/tcrypt.c +++ b/lib/tcrypt/tcrypt.c @@ -425,13 +425,15 @@ out: } static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, - const char *key, uint32_t flags) + const char *key, struct crypt_params_tcrypt *params) { struct tcrypt_phdr hdr2; int i, j, r = -EINVAL; for (i = 0; tcrypt_cipher[i].chain_count; i++) { - if (!(flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy) + if (params->cipher && !strstr(tcrypt_cipher[i].long_name, params->cipher)) + continue; + if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_cipher[i].legacy) continue; log_dbg(cd, "TCRYPT: trying cipher %s-%s", tcrypt_cipher[i].long_name, tcrypt_cipher[i].mode); @@ -463,7 +465,7 @@ static int TCRYPT_decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr, r = i; break; } - if ((flags & CRYPT_TCRYPT_VERA_MODES) && + if ((params->flags & CRYPT_TCRYPT_VERA_MODES) && !strncmp(hdr2.d.magic, VCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) { log_dbg(cd, "TCRYPT: Signature magic detected (Veracrypt)."); memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN); @@ -568,6 +570,8 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, pwd[i] += params->passphrase[i]; for (i = 0; tcrypt_kdf[i].name; i++) { + if (params->hash_name && strcmp(params->hash_name, tcrypt_kdf[i].hash)) + continue; if (!(params->flags & CRYPT_TCRYPT_LEGACY_MODES) && tcrypt_kdf[i].legacy) continue; if (!(params->flags & CRYPT_TCRYPT_VERA_MODES) && tcrypt_kdf[i].veracrypt) @@ -598,7 +602,7 @@ static int TCRYPT_init_hdr(struct crypt_device *cd, } /* Decrypt header */ - r = TCRYPT_decrypt_hdr(cd, hdr, key, params->flags); + r = TCRYPT_decrypt_hdr(cd, hdr, key, params); if (r == -ENOENT) { skipped++; r = -EPERM; diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index 58d7519a..137265c7 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -716,12 +716,16 @@ a mapping . \fB\fR can be [\-\-key\-file, \-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup, \-\-readonly, \-\-test\-passphrase, \-\-allow-discards, \-\-veracrypt, \-\-veracrypt\-pim, \-\-veracrypt\-query\-pim, -\-\-header]. +\-\-header, \-\-cipher, \-\-hash]. The keyfile parameter allows a combination of file content with the passphrase and can be repeated. Note that using keyfiles is compatible with TCRYPT and is different from LUKS keyfile logic. +If \fB\-\-\cipher\fR or \fB\-\-hash\fR options are used, only cipher chains or +PBKDF2 variants with the specified hash algoprithms are checked. This could speed +up opening of the device (but also it reveals some information about the container). + \fBWARNING:\fR Option \fB\-\-allow\-discards\fR cannot be combined with option \fB\-\-tcrypt\-hidden\fR. For normal mapping, it can cause the \fBdestruction of hidden volume\fR (hidden volume appears as unused space @@ -741,7 +745,7 @@ This means that if the master key is compromised, the whole device has to be erased to prevent further access. Use this option carefully. \fB\fR can be [\-\-dump\-master\-key, \-\-key\-file, -\-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup]. +\-\-tcrypt\-hidden, \-\-tcrypt\-system, \-\-tcrypt\-backup, \-\-cipher, \-\-hash]. The keyfile parameter allows a combination of file content with the passphrase and can be repeated. diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 3bc0cd26..bef44fdb 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -453,6 +453,8 @@ static int action_open_tcrypt(void) .flags = CRYPT_TCRYPT_LEGACY_MODES | (ARG_SET(OPT_VERACRYPT_ID) ? CRYPT_TCRYPT_VERA_MODES : 0), .veracrypt_pim = ARG_UINT32(OPT_VERACRYPT_PIM_ID), + .hash_name = ARG_STR(OPT_HASH_ID), + .cipher = ARG_STR(OPT_CIPHER_ID), }; const char *activated_name; uint32_t activate_flags = 0; @@ -588,7 +590,9 @@ static int action_tcryptDump(void) .keyfiles_count = keyfiles_count, .flags = CRYPT_TCRYPT_LEGACY_MODES | (ARG_SET(OPT_VERACRYPT_ID) ? CRYPT_TCRYPT_VERA_MODES : 0), - .veracrypt_pim = ARG_UINT32(OPT_VERACRYPT_PIM_ID) + .veracrypt_pim = ARG_UINT32(OPT_VERACRYPT_PIM_ID), + .hash_name = ARG_STR(OPT_HASH_ID), + .cipher = ARG_STR(OPT_CIPHER_ID), }; int r; r = crypt_init_data_device(&cd, ARG_STR(OPT_HEADER_ID) ?: action_argv[0], action_argv[0]); diff --git a/tests/tcrypt-compat-test b/tests/tcrypt-compat-test index e706427b..7ad79b8e 100755 --- a/tests/tcrypt-compat-test +++ b/tests/tcrypt-compat-test @@ -111,6 +111,11 @@ for file in $(ls $TST_DIR/[tv]c_* $TST_DIR/vcpim_* $TST_DIR/sys_[tv]c_*) ; do SYS_OPT="" [[ $file =~ sys_.* ]] && SYS_OPT="--tcrypt-system" echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt $SYS_OPT $PIM_OPT $file >/dev/null || fail + if [[ $file =~ .*-sha512-xts-aes$ ]] ; then + echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt $SYS_OPT $PIM_OPT -h sha512 -c aes $file >/dev/null || fail + echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt $SYS_OPT $PIM_OPT -h xxxx $file 2>/dev/null && fail + echo $PASSWORD | $CRYPTSETUP tcryptDump --veracrypt $SYS_OPT $PIM_OPT -h sha512 -c xxx $file 2>/dev/null && fail + fi echo " [OK]" done