mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-06 00:10:04 +01:00
TCRYPT: support keyfiles
This commit is contained in:
@@ -395,6 +395,8 @@ struct crypt_params_verity {
|
|||||||
struct crypt_params_tcrypt {
|
struct crypt_params_tcrypt {
|
||||||
const char *passphrase;
|
const char *passphrase;
|
||||||
size_t passphrase_size;
|
size_t passphrase_size;
|
||||||
|
const char **keyfiles;
|
||||||
|
unsigned int keyfiles_count;
|
||||||
const char *hash_name; /**< hash function for PBKDF */
|
const char *hash_name; /**< hash function for PBKDF */
|
||||||
const char *cipher[3]; /**< cipher chain */
|
const char *cipher[3]; /**< cipher chain */
|
||||||
const char *mode; /**< cipher block mode */
|
const char *mode; /**< cipher block mode */
|
||||||
|
|||||||
12
lib/setup.c
12
lib/setup.c
@@ -634,9 +634,15 @@ static int _crypt_load_tcrypt(struct crypt_device *cd, struct crypt_params_tcryp
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = TCRYPT_read_phdr(cd, &cd->tcrypt_hdr, &cd->tcrypt_params,
|
memcpy(&cd->tcrypt_params, params, sizeof(*params));
|
||||||
params->passphrase, params->passphrase_size,
|
|
||||||
params->flags);
|
r = TCRYPT_read_phdr(cd, &cd->tcrypt_hdr, &cd->tcrypt_params);
|
||||||
|
|
||||||
|
cd->tcrypt_params.passphrase = NULL;
|
||||||
|
cd->tcrypt_params.passphrase_size = 0;
|
||||||
|
cd->tcrypt_params.keyfiles = NULL;
|
||||||
|
cd->tcrypt_params.keyfiles_count = 0;
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@@ -248,24 +248,80 @@ static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pool_keyfile(struct crypt_device *cd,
|
||||||
|
unsigned char pool[TCRYPT_KEY_POOL_LEN],
|
||||||
|
const char *keyfile)
|
||||||
|
{
|
||||||
|
unsigned char data[TCRYPT_KEYFILE_LEN];
|
||||||
|
int i, j, fd, data_size;
|
||||||
|
uint32_t crc;
|
||||||
|
unsigned char *crc_c = (unsigned char*)&crc;
|
||||||
|
|
||||||
|
log_dbg("TCRYPT: using keyfile %s.", keyfile);
|
||||||
|
|
||||||
|
fd = open(keyfile, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
log_err(cd, _("Failed to open key file.\n"));
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: add while */
|
||||||
|
data_size = read(fd, data, TCRYPT_KEYFILE_LEN);
|
||||||
|
close(fd);
|
||||||
|
if (data_size < 0) {
|
||||||
|
log_err(cd, _("Error reading keyfile %s.\n"), keyfile);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0, j = 0, crc = ~0U; i < data_size; i++) {
|
||||||
|
crc = crypt_crc32(crc, &data[i], 1);
|
||||||
|
pool[j++] += crc_c[3];
|
||||||
|
pool[j++] += crc_c[2];
|
||||||
|
pool[j++] += crc_c[1];
|
||||||
|
pool[j++] += crc_c[0];
|
||||||
|
j %= TCRYPT_KEY_POOL_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = 0;
|
||||||
|
memset(data, 0, TCRYPT_KEYFILE_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int TCRYPT_init_hdr(struct crypt_device *cd,
|
static int TCRYPT_init_hdr(struct crypt_device *cd,
|
||||||
struct tcrypt_phdr *hdr,
|
struct tcrypt_phdr *hdr,
|
||||||
struct crypt_params_tcrypt *params,
|
struct crypt_params_tcrypt *params)
|
||||||
const char *passphrase,
|
|
||||||
size_t passphrase_size)
|
|
||||||
{
|
{
|
||||||
|
unsigned char pwd[TCRYPT_KEY_POOL_LEN] = {};
|
||||||
|
size_t passphrase_size;
|
||||||
char *key;
|
char *key;
|
||||||
int r, i;
|
int r, i;
|
||||||
|
|
||||||
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
|
if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (params->keyfiles_count)
|
||||||
|
passphrase_size = TCRYPT_KEY_POOL_LEN;
|
||||||
|
else
|
||||||
|
passphrase_size = params->passphrase_size;
|
||||||
|
|
||||||
|
/* Calculate pool content from keyfiles */
|
||||||
|
for (i = 0; i < params->keyfiles_count; i++) {
|
||||||
|
r = pool_keyfile(cd, pwd, params->keyfiles[i]);
|
||||||
|
if (r < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If provided password, combine it with pool */
|
||||||
|
for (i = 0; i < params->passphrase_size; i++)
|
||||||
|
pwd[i] += params->passphrase[i];
|
||||||
|
|
||||||
for (i = 0; tcrypt_kdf[i].name; i++) {
|
for (i = 0; tcrypt_kdf[i].name; i++) {
|
||||||
/* Derive header key */
|
/* Derive header key */
|
||||||
log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
|
log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
|
||||||
tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations);
|
tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations);
|
||||||
r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash,
|
r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash,
|
||||||
passphrase, passphrase_size,
|
(char*)pwd, passphrase_size,
|
||||||
hdr->salt, TCRYPT_HDR_SALT_LEN,
|
hdr->salt, TCRYPT_HDR_SALT_LEN,
|
||||||
key, TCRYPT_HDR_KEY_LEN,
|
key, TCRYPT_HDR_KEY_LEN,
|
||||||
tcrypt_kdf[i].iterations);
|
tcrypt_kdf[i].iterations);
|
||||||
@@ -277,25 +333,26 @@ static int TCRYPT_init_hdr(struct crypt_device *cd,
|
|||||||
if (r != -EPERM)
|
if (r != -EPERM)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
free(key);
|
|
||||||
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
goto out;
|
||||||
|
|
||||||
r = hdr_from_disk(hdr, params, i, r);
|
r = hdr_from_disk(hdr, params, i, r);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
goto out;
|
||||||
|
|
||||||
hdr_info(cd, hdr, params);
|
hdr_info(cd, hdr, params);
|
||||||
return 0;
|
out:
|
||||||
|
memset(pwd, 0, TCRYPT_KEY_POOL_LEN);
|
||||||
|
if (key)
|
||||||
|
memset(key, 0, TCRYPT_HDR_KEY_LEN);
|
||||||
|
free(key);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TCRYPT_read_phdr(struct crypt_device *cd,
|
int TCRYPT_read_phdr(struct crypt_device *cd,
|
||||||
struct tcrypt_phdr *hdr,
|
struct tcrypt_phdr *hdr,
|
||||||
struct crypt_params_tcrypt *params,
|
struct crypt_params_tcrypt *params)
|
||||||
const char *passphrase,
|
|
||||||
size_t passphrase_size,
|
|
||||||
uint32_t flags)
|
|
||||||
{
|
{
|
||||||
struct device *device = crypt_metadata_device(cd);
|
struct device *device = crypt_metadata_device(cd);
|
||||||
ssize_t hdr_size = sizeof(struct tcrypt_phdr);
|
ssize_t hdr_size = sizeof(struct tcrypt_phdr);
|
||||||
@@ -312,19 +369,18 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & CRYPT_TCRYPT_HIDDEN_HEADER) &&
|
if ((params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) &&
|
||||||
lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) < 0) {
|
lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) < 0) {
|
||||||
log_err(cd, _("Cannot seek to hidden header for %s.\n"), device_path(device));
|
log_err(cd, _("Cannot seek to hidden header for %s.\n"), device_path(device));
|
||||||
r = -EIO;
|
close(devfd);
|
||||||
goto out;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read_blockwise(devfd, device_block_size(device), hdr, hdr_size) == hdr_size) {
|
if (read_blockwise(devfd, device_block_size(device), hdr, hdr_size) == hdr_size)
|
||||||
params->flags = flags;
|
r = TCRYPT_init_hdr(cd, hdr, params);
|
||||||
r = TCRYPT_init_hdr(cd, hdr, params, passphrase, passphrase_size);
|
else
|
||||||
} else
|
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
out:
|
|
||||||
close(devfd);
|
close(devfd);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
#define TCRYPT_HDR_HIDDEN_OFFSET 65536
|
#define TCRYPT_HDR_HIDDEN_OFFSET 65536
|
||||||
|
|
||||||
#define TCRYPT_LRW_IKEY_LEN 16
|
#define TCRYPT_LRW_IKEY_LEN 16
|
||||||
|
#define TCRYPT_KEY_POOL_LEN 64
|
||||||
|
#define TCRYPT_KEYFILE_LEN 1048576
|
||||||
|
|
||||||
#define TCRYPT_HDR_FLAG_SYSTEM (1 << 0)
|
#define TCRYPT_HDR_FLAG_SYSTEM (1 << 0)
|
||||||
#define TCRYPT_HDR_FLAG_NONSYSTEM (1 << 1)
|
#define TCRYPT_HDR_FLAG_NONSYSTEM (1 << 1)
|
||||||
@@ -64,10 +66,7 @@ struct tcrypt_phdr {
|
|||||||
|
|
||||||
int TCRYPT_read_phdr(struct crypt_device *cd,
|
int TCRYPT_read_phdr(struct crypt_device *cd,
|
||||||
struct tcrypt_phdr *hdr,
|
struct tcrypt_phdr *hdr,
|
||||||
struct crypt_params_tcrypt *params,
|
struct crypt_params_tcrypt *params);
|
||||||
const char *passphrase,
|
|
||||||
size_t passphrase_size,
|
|
||||||
uint32_t flags);
|
|
||||||
|
|
||||||
int TCRYPT_activate(struct crypt_device *cd,
|
int TCRYPT_activate(struct crypt_device *cd,
|
||||||
const char *name,
|
const char *name,
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#define MAX_CIPHER_LEN 32
|
#define MAX_CIPHER_LEN 32
|
||||||
#define MAX_CIPHER_LEN_STR "32"
|
#define MAX_CIPHER_LEN_STR "32"
|
||||||
|
#define MAX_KEYFILES 32
|
||||||
|
|
||||||
struct crypt_device;
|
struct crypt_device;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,11 @@
|
|||||||
static const char *opt_cipher = NULL;
|
static const char *opt_cipher = NULL;
|
||||||
static const char *opt_hash = NULL;
|
static const char *opt_hash = NULL;
|
||||||
static int opt_verify_passphrase = 0;
|
static int opt_verify_passphrase = 0;
|
||||||
|
|
||||||
static const char *opt_key_file = NULL;
|
static const char *opt_key_file = NULL;
|
||||||
|
static int opt_keyfiles_count = 0;
|
||||||
|
static const char *opt_keyfiles[MAX_KEYFILES];
|
||||||
|
|
||||||
static const char *opt_master_key_file = NULL;
|
static const char *opt_master_key_file = NULL;
|
||||||
static const char *opt_header_backup_file = NULL;
|
static const char *opt_header_backup_file = NULL;
|
||||||
static const char *opt_uuid = NULL;
|
static const char *opt_uuid = NULL;
|
||||||
@@ -258,7 +262,10 @@ out:
|
|||||||
static int action_tcryptOpen(int arg __attribute__((unused)))
|
static int action_tcryptOpen(int arg __attribute__((unused)))
|
||||||
{
|
{
|
||||||
struct crypt_device *cd = NULL;
|
struct crypt_device *cd = NULL;
|
||||||
struct crypt_params_tcrypt params = {};
|
struct crypt_params_tcrypt params = {
|
||||||
|
.keyfiles = opt_keyfiles,
|
||||||
|
.keyfiles_count = opt_keyfiles_count,
|
||||||
|
};
|
||||||
const char *activated_name;
|
const char *activated_name;
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
int r;
|
int r;
|
||||||
@@ -271,11 +278,8 @@ static int action_tcryptOpen(int arg __attribute__((unused)))
|
|||||||
/* TCRYPT header is encrypted, get passphrase now */
|
/* TCRYPT header is encrypted, get passphrase now */
|
||||||
r = crypt_get_key(_("Enter passphrase: "),
|
r = crypt_get_key(_("Enter passphrase: "),
|
||||||
CONST_CAST(char**)¶ms.passphrase,
|
CONST_CAST(char**)¶ms.passphrase,
|
||||||
¶ms.passphrase_size,
|
¶ms.passphrase_size, 0, 0, NULL, opt_timeout,
|
||||||
opt_keyfile_offset, opt_keyfile_size,
|
_verify_passphrase(0), cd);
|
||||||
NULL, opt_timeout,
|
|
||||||
_verify_passphrase(0),
|
|
||||||
cd);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -1216,7 +1220,7 @@ int main(int argc, const char **argv)
|
|||||||
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
|
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
|
||||||
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
|
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
|
||||||
{ "verify-passphrase", 'y', POPT_ARG_NONE, &opt_verify_passphrase, 0, N_("Verifies the passphrase by asking for it twice"), NULL },
|
{ "verify-passphrase", 'y', POPT_ARG_NONE, &opt_verify_passphrase, 0, N_("Verifies the passphrase by asking for it twice"), NULL },
|
||||||
{ "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 0, N_("Read the key from a file."), NULL },
|
{ "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 5, N_("Read the key from a file."), NULL },
|
||||||
{ "master-key-file", '\0', POPT_ARG_STRING, &opt_master_key_file, 0, N_("Read the volume (master) key from file."), NULL },
|
{ "master-key-file", '\0', POPT_ARG_STRING, &opt_master_key_file, 0, N_("Read the volume (master) key from file."), NULL },
|
||||||
{ "dump-master-key", '\0', POPT_ARG_NONE, &opt_dump_master_key, 0, N_("Dump volume (master) key instead of keyslots info."), NULL },
|
{ "dump-master-key", '\0', POPT_ARG_NONE, &opt_dump_master_key, 0, N_("Dump volume (master) key instead of keyslots info."), NULL },
|
||||||
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
|
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
|
||||||
@@ -1266,6 +1270,12 @@ int main(int argc, const char **argv)
|
|||||||
unsigned long long ull_value;
|
unsigned long long ull_value;
|
||||||
char *endp;
|
char *endp;
|
||||||
|
|
||||||
|
if (r == 5) {
|
||||||
|
if (opt_keyfiles_count < MAX_KEYFILES)
|
||||||
|
opt_keyfiles[opt_keyfiles_count++] = poptGetOptArg(popt_context);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ull_value = strtoull(popt_tmp, &endp, 0);
|
ull_value = strtoull(popt_tmp, &endp, 0);
|
||||||
if (*endp || !*popt_tmp ||
|
if (*endp || !*popt_tmp ||
|
||||||
|
|||||||
Reference in New Issue
Block a user