mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 19:00:02 +01:00
TCRYPT: parse cipher chain on init.
This commit is contained in:
@@ -399,9 +399,9 @@ struct crypt_params_tcrypt {
|
|||||||
const char **keyfiles;
|
const char **keyfiles;
|
||||||
unsigned int keyfiles_count;
|
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; /**< cipher chain c1[-c2[-c3]] */
|
||||||
const char *mode; /**< cipher block mode */
|
const char *mode; /**< cipher block mode */
|
||||||
size_t key_size; /**< key size in bytes */
|
size_t key_size; /**< key size in bytes (the whole chain) */
|
||||||
uint32_t flags; /**< CRYPT_TCRYPT* flags */
|
uint32_t flags; /**< CRYPT_TCRYPT* flags */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
12
lib/setup.c
12
lib/setup.c
@@ -751,7 +751,8 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isTCRYPT(cd->type)) {
|
} else if (isTCRYPT(cd->type)) {
|
||||||
//FIXME
|
r = TCRYPT_init_by_name(cd, name, &dmd, &cd->tcrypt_params,
|
||||||
|
&cd->tcrypt_hdr);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
crypt_free_volume_key(dmd.u.crypt.vk);
|
crypt_free_volume_key(dmd.u.crypt.vk);
|
||||||
@@ -2344,6 +2345,9 @@ const char *crypt_get_cipher(struct crypt_device *cd)
|
|||||||
if (isLOOPAES(cd->type))
|
if (isLOOPAES(cd->type))
|
||||||
return cd->loopaes_cipher;
|
return cd->loopaes_cipher;
|
||||||
|
|
||||||
|
if (isTCRYPT(cd->type))
|
||||||
|
return cd->tcrypt_params.cipher;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2358,6 +2362,9 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd)
|
|||||||
if (isLOOPAES(cd->type))
|
if (isLOOPAES(cd->type))
|
||||||
return cd->loopaes_cipher_mode;
|
return cd->loopaes_cipher_mode;
|
||||||
|
|
||||||
|
if (isTCRYPT(cd->type))
|
||||||
|
return cd->tcrypt_params.mode;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2402,6 +2409,9 @@ int crypt_get_volume_key_size(struct crypt_device *cd)
|
|||||||
if (isVERITY(cd->type))
|
if (isVERITY(cd->type))
|
||||||
return cd->verity_root_hash_size;
|
return cd->verity_root_hash_size;
|
||||||
|
|
||||||
|
if (isTCRYPT(cd->type))
|
||||||
|
return cd->tcrypt_params.key_size;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,17 +111,14 @@ static void hdr_info(struct crypt_device *cd, struct tcrypt_phdr *hdr,
|
|||||||
log_dbg("Flags: %d", (int)hdr->d.flags);
|
log_dbg("Flags: %d", (int)hdr->d.flags);
|
||||||
log_dbg("MK: offset %d, size %d", (int)hdr->d.mk_offset, (int)hdr->d.mk_size);
|
log_dbg("MK: offset %d, size %d", (int)hdr->d.mk_offset, (int)hdr->d.mk_size);
|
||||||
log_dbg("KDF: PBKDF2, hash %s", params->hash_name);
|
log_dbg("KDF: PBKDF2, hash %s", params->hash_name);
|
||||||
log_dbg("Cipher: %s%s%s%s%s-%s",
|
log_dbg("Cipher: %s-%s", params->cipher, params->mode);
|
||||||
params->cipher[0],
|
|
||||||
params->cipher[1] ? "-" : "", params->cipher[1] ?: "",
|
|
||||||
params->cipher[2] ? "-" : "", params->cipher[2] ?: "",
|
|
||||||
params->mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hdr_from_disk(struct tcrypt_phdr *hdr,
|
static int hdr_from_disk(struct tcrypt_phdr *hdr,
|
||||||
struct crypt_params_tcrypt *params,
|
struct crypt_params_tcrypt *params,
|
||||||
int kdf_index, int cipher_index)
|
int kdf_index, int cipher_index)
|
||||||
{
|
{
|
||||||
|
char cipher_name[MAX_CIPHER_LEN * 4];
|
||||||
uint32_t crc32;
|
uint32_t crc32;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
@@ -170,11 +167,26 @@ static int hdr_from_disk(struct tcrypt_phdr *hdr,
|
|||||||
|
|
||||||
params->hash_name = tcrypt_kdf[kdf_index].hash;
|
params->hash_name = tcrypt_kdf[kdf_index].hash;
|
||||||
|
|
||||||
params->cipher[0] = tcrypt_cipher[cipher_index].cipher[0].name;
|
params->key_size = tcrypt_cipher[cipher_index].cipher[0].key_size;
|
||||||
params->cipher[1] = tcrypt_cipher[cipher_index].cipher[1].name;
|
strncpy(cipher_name, tcrypt_cipher[cipher_index].cipher[0].name,
|
||||||
params->cipher[2] = tcrypt_cipher[cipher_index].cipher[2].name;
|
sizeof(cipher_name));
|
||||||
params->mode = tcrypt_cipher[cipher_index].mode;
|
|
||||||
params->key_size = tcrypt_cipher[cipher_index].cipher[0].key_size; //fixme
|
if (tcrypt_cipher[cipher_index].cipher[1].name) {
|
||||||
|
strcat(cipher_name, "-");
|
||||||
|
strncat(cipher_name, tcrypt_cipher[cipher_index].cipher[1].name,
|
||||||
|
MAX_CIPHER_LEN);
|
||||||
|
params->key_size += tcrypt_cipher[cipher_index].cipher[1].key_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcrypt_cipher[cipher_index].cipher[2].name) {
|
||||||
|
strcat(cipher_name, "-");
|
||||||
|
strncat(cipher_name, tcrypt_cipher[cipher_index].cipher[2].name,
|
||||||
|
MAX_CIPHER_LEN);
|
||||||
|
params->key_size += tcrypt_cipher[cipher_index].cipher[2].key_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
params->cipher = strdup(cipher_name);
|
||||||
|
params->mode = strdup(tcrypt_cipher[cipher_index].mode);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -494,12 +506,8 @@ int TCRYPT_activate(struct crypt_device *cd,
|
|||||||
{
|
{
|
||||||
char cipher[MAX_CIPHER_LEN], dm_name[PATH_MAX], dm_dev_name[PATH_MAX];
|
char cipher[MAX_CIPHER_LEN], dm_name[PATH_MAX], dm_dev_name[PATH_MAX];
|
||||||
struct device *device = NULL;
|
struct device *device = NULL;
|
||||||
int i, r;
|
int i, r, num_ciphers;
|
||||||
struct tcrypt_alg tcipher[3] = {
|
char cname[3][MAX_CIPHER_LEN];
|
||||||
{ params->cipher[0], params->key_size, 0 },
|
|
||||||
{ params->cipher[1], params->key_size, 0 },
|
|
||||||
{ params->cipher[2], params->key_size, 0 }
|
|
||||||
};
|
|
||||||
struct crypt_dm_active_device dmd = {
|
struct crypt_dm_active_device dmd = {
|
||||||
.target = DM_CRYPT,
|
.target = DM_CRYPT,
|
||||||
.size = 0,
|
.size = 0,
|
||||||
@@ -521,13 +529,23 @@ int TCRYPT_activate(struct crypt_device *cd,
|
|||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
dmd.u.crypt.vk = crypt_alloc_volume_key(params->key_size, NULL);
|
/* Parse cipher chain from c1[-c2[-c3]] */
|
||||||
|
cname[0][0] = cname[1][0] = cname[2][0] = '\0';
|
||||||
|
num_ciphers = sscanf(params->cipher, "%" MAX_CIPHER_LEN_STR "[^-]-%"
|
||||||
|
MAX_CIPHER_LEN_STR "[^-]-%"
|
||||||
|
MAX_CIPHER_LEN_STR "s",
|
||||||
|
cname[0], cname[1], cname[2]);
|
||||||
|
if (num_ciphers < 1)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Frome here, key size for every cipher must be the same */
|
||||||
|
dmd.u.crypt.vk = crypt_alloc_volume_key(params->key_size / num_ciphers, NULL);
|
||||||
if (!dmd.u.crypt.vk)
|
if (!dmd.u.crypt.vk)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 2; i >= 0; i--) {
|
for (i = 2; i >= 0; i--) {
|
||||||
|
|
||||||
if (!params->cipher[i])
|
if (!cname[i][0])
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
@@ -539,12 +557,11 @@ int TCRYPT_activate(struct crypt_device *cd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
snprintf(cipher, sizeof(cipher), "%s-%s",
|
snprintf(cipher, sizeof(cipher), "%s-%s",
|
||||||
params->cipher[i], params->mode);
|
cname[i], params->mode);
|
||||||
copy_key(dmd.u.crypt.vk->key, hdr->d.keys,
|
copy_key(dmd.u.crypt.vk->key, hdr->d.keys, num_ciphers - 1,
|
||||||
top_cipher(tcipher),
|
params->key_size / num_ciphers, i, params->mode);
|
||||||
params->key_size, i, params->mode);
|
|
||||||
|
|
||||||
if (top_cipher(tcipher) != i) {
|
if ((num_ciphers -1) != i) {
|
||||||
snprintf(dm_dev_name, sizeof(dm_dev_name), "%s/%s_%d",
|
snprintf(dm_dev_name, sizeof(dm_dev_name), "%s/%s_%d",
|
||||||
dm_get_dir(), name, i + 1);
|
dm_get_dir(), name, i + 1);
|
||||||
r = device_alloc(&device, dm_dev_name);
|
r = device_alloc(&device, dm_dev_name);
|
||||||
@@ -622,3 +639,62 @@ out:
|
|||||||
free(CONST_CAST(void*)dmd.uuid);
|
free(CONST_CAST(void*)dmd.uuid);
|
||||||
return (r == -ENODEV) ? 0 : r;
|
return (r == -ENODEV) ? 0 : r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int status_one(struct crypt_device *cd, const char *name,
|
||||||
|
const char *base_uuid, int index,
|
||||||
|
size_t *key_size, char *cipher)
|
||||||
|
{
|
||||||
|
struct crypt_dm_active_device dmd = {};
|
||||||
|
char dm_name[PATH_MAX], *c;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (snprintf(dm_name, sizeof(dm_name), "%s_%d", name, index) < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = dm_status_device(cd, dm_name);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = dm_query_device(cd, dm_name, DM_ACTIVE_UUID |
|
||||||
|
DM_ACTIVE_CRYPT_CIPHER |
|
||||||
|
DM_ACTIVE_CRYPT_KEYSIZE, &dmd);
|
||||||
|
if (r > 0)
|
||||||
|
r = 0;
|
||||||
|
if (!r && !strncmp(dmd.uuid, base_uuid, strlen(base_uuid))) {
|
||||||
|
if ((c = strchr(dmd.u.crypt.cipher, '-')))
|
||||||
|
*c = '\0';
|
||||||
|
strcat(cipher, "-");
|
||||||
|
strncat(cipher, dmd.u.crypt.cipher, MAX_CIPHER_LEN);
|
||||||
|
*key_size += dmd.u.crypt.vk->keylength;
|
||||||
|
} else
|
||||||
|
r = -ENODEV;
|
||||||
|
|
||||||
|
free(CONST_CAST(void*)dmd.uuid);
|
||||||
|
free(CONST_CAST(void*)dmd.u.crypt.cipher);
|
||||||
|
crypt_free_volume_key(dmd.u.crypt.vk);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TCRYPT_init_by_name(struct crypt_device *cd, const char *name,
|
||||||
|
const struct crypt_dm_active_device *dmd,
|
||||||
|
struct crypt_params_tcrypt *tcrypt_params,
|
||||||
|
struct tcrypt_phdr *tcrypt_hdr)
|
||||||
|
{
|
||||||
|
char cipher[MAX_CIPHER_LEN * 4], *mode;
|
||||||
|
|
||||||
|
memset(tcrypt_params, 0, sizeof(*tcrypt_params));
|
||||||
|
memset(tcrypt_hdr, 0, sizeof(*tcrypt_hdr));
|
||||||
|
strncpy(cipher, dmd->u.crypt.cipher, MAX_CIPHER_LEN);
|
||||||
|
|
||||||
|
if ((mode = strchr(cipher, '-'))) {
|
||||||
|
*mode = '\0';
|
||||||
|
tcrypt_params->mode = strdup(++mode);
|
||||||
|
}
|
||||||
|
tcrypt_params->key_size = dmd->u.crypt.vk->keylength;
|
||||||
|
|
||||||
|
if (!status_one(cd, name, dmd->uuid, 1, &tcrypt_params->key_size, cipher))
|
||||||
|
status_one(cd, name, dmd->uuid, 2, &tcrypt_params->key_size, cipher);
|
||||||
|
|
||||||
|
tcrypt_params->cipher = strdup(cipher);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,10 +64,17 @@ struct tcrypt_phdr {
|
|||||||
};
|
};
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
|
struct crypt_dm_active_device dmd;
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
int TCRYPT_init_by_name(struct crypt_device *cd, const char *name,
|
||||||
|
const struct crypt_dm_active_device *dmd,
|
||||||
|
struct crypt_params_tcrypt *tcrypt_params,
|
||||||
|
struct tcrypt_phdr *tcrypt_hdr);
|
||||||
|
|
||||||
int TCRYPT_activate(struct crypt_device *cd,
|
int TCRYPT_activate(struct crypt_device *cd,
|
||||||
const char *name,
|
const char *name,
|
||||||
struct tcrypt_phdr *hdr,
|
struct tcrypt_phdr *hdr,
|
||||||
|
|||||||
Reference in New Issue
Block a user