From ed6e3b727059e0533b5ccf7bb697a7fe1a5f151b Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Wed, 13 Feb 2019 14:11:00 +0100 Subject: [PATCH] zkey-cryptsetup: Obtain PBKDF from existing key-slot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For zkey-cryptsetup commands reencipher and setkey, use the same password-based key derivation function (PBKDF) when creating unbound key-sots that the key slot uses, which was unlocked through the specified passphrase. That way the unlocked key slots created by these commands inherit the PBKDF from the existing key slot. This feature requires libcryptsetup version 2.1 or later. If an older libcryptsetup version is available at compile time, then PBKDF2 is used for newly created unbound key slots. Signed-off-by: Ingo Franzki Signed-off-by: Jan Höppner --- zkey/zkey-cryptsetup.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/zkey/zkey-cryptsetup.c b/zkey/zkey-cryptsetup.c index c269b8b7..4942c9c0 100644 --- a/zkey/zkey-cryptsetup.c +++ b/zkey/zkey-cryptsetup.c @@ -35,6 +35,11 @@ #include "misc.h" #include "pkey.h" +/* Detect if cryptsetup 2.1 or later is available */ +#ifdef CRYPT_LOG_DEBUG_JSON +#define HAVE_CRYPT_KEYSLOT_GET_PBKDF +#endif + #define MAX_KEY_SIZE (8 * 1024 * 1024) #define MAX_PASSWORD_SIZE 512 #define KEYFILE_BUFLEN 4096 @@ -1319,6 +1324,9 @@ static int open_keyslot(int keyslot, char **key, size_t *keysize, char **password, size_t *password_len, const char *prompt) { +#ifdef HAVE_CRYPT_KEYSLOT_GET_PBKDF + struct crypt_pbkdf_type pbkdf; +#endif char *vkey = NULL; char *pw = NULL; long long tries; @@ -1370,6 +1378,30 @@ static int open_keyslot(int keyslot, char **key, size_t *keysize, keyslot = rc; pr_verbose("Volume key obtained from key slot %d", keyslot); +#ifdef HAVE_CRYPT_KEYSLOT_GET_PBKDF + /* + * Get PBKDF of the key slot that was opened, and use its PBKDF for + * new key slots. + */ + memset(&pbkdf, 0, sizeof(pbkdf)); + rc = crypt_keyslot_get_pbkdf(g.cd, keyslot, &pbkdf); + if (rc != 0) { + warnx("Failed to get the PBKDF for key slot %d: %s", + keyslot, strerror(-rc)); + goto out; + } + + /* Reuse already benchmarked number of iterations */ + pbkdf.flags |= CRYPT_PBKDF_NO_BENCHMARK; + + rc = crypt_set_pbkdf_type(g.cd, &pbkdf); + if (rc != 0) { + warnx("Failed to set the PBKDF for new key slots: %s", + strerror(-rc)); + goto out; + } +#endif + if (key != NULL) *key = vkey; else