Skip to content

Commit

Permalink
libdevmapper: Support dm-crypt integrity_key_size option
Browse files Browse the repository at this point in the history
This patch implement support for setting specific integrity key size
option in dm-crypt, available since dm-crypt version 1.28.0.

This can be used for setting non-standard HMAC key length.

Mostly based on code from Ingo Franzki <[email protected]>
  • Loading branch information
mbroz committed Nov 26, 2024
1 parent 82bee1c commit ec57658
Show file tree
Hide file tree
Showing 12 changed files with 39 additions and 35 deletions.
2 changes: 1 addition & 1 deletion lib/bitlk/bitlk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1365,7 +1365,7 @@ static int _activate(struct crypt_device *cd,
crypt_get_cipher_spec(cd),
segments[i].iv_offset,
segments[i].iv_offset,
NULL, 0,
NULL, 0, 0,
params->sector_size);
if (r)
goto out;
Expand Down
3 changes: 1 addition & 2 deletions lib/fvault2/fvault2.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,8 +835,7 @@ static int _activate(
r = dm_crypt_target_set(&dm_dev.segment, 0, dm_dev.size,
crypt_data_device(cd), vol_key, cipher,
crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd),
crypt_get_sector_size(cd));
NULL, 0, 0, crypt_get_sector_size(cd));

if (!r)
r = dm_create_device(cd, name, CRYPT_FVAULT2, &dm_dev);
Expand Down
24 changes: 20 additions & 4 deletions lib/libdevmapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ static void _dm_set_crypt_compat(struct crypt_device *cd,
if (_dm_satisfies_version(1, 26, 0, crypt_maj, crypt_min, crypt_patch))
_dm_flags |= DM_CRYPT_HIGH_PRIORITY_SUPPORTED;

if (_dm_satisfies_version(1, 28, 0, crypt_maj, crypt_min, crypt_patch))
_dm_flags |= DM_CRYPT_INTEGRITY_KEY_SIZE_OPT_SUPPORTED;

_dm_crypt_checked = true;
}

Expand Down Expand Up @@ -540,6 +543,7 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0;
char *params = NULL, *hexkey = NULL;
char sector_feature[32], features[512], integrity_dm[256], cipher_dm[256];
char int_ksize_feature[32];

if (!tgt)
return NULL;
Expand Down Expand Up @@ -567,9 +571,11 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
num_options++;
if (tgt->u.crypt.sector_size != SECTOR_SIZE)
num_options++;
if (tgt->u.crypt.integrity && tgt->u.crypt.integrity_key_size)
num_options++;

if (num_options) { /* MAX length int32 + 15 + 15 + 23 + 18 + 19 + 17 + 14 + 13 + int32 + integrity_str */
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s%s%s", num_options,
if (num_options) { /* MAX length int32 + 15 + 15 + 23 + 18 + 19 + 17 + 14 + 13 + int32 + integrity_str + 21 + int32 */
r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s%s%s%s", num_options,
(flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "",
(flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "",
(flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "",
Expand All @@ -579,7 +585,9 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
(flags & CRYPT_ACTIVATE_HIGH_PRIORITY) ? " high_priority" : "",
(tgt->u.crypt.sector_size != SECTOR_SIZE) ?
_uf(sector_feature, sizeof(sector_feature), "sector_size", tgt->u.crypt.sector_size) : "",
integrity_dm);
integrity_dm,
(tgt->u.crypt.integrity && tgt->u.crypt.integrity_key_size) ?
_uf(int_ksize_feature, sizeof(int_ksize_feature), "integrity_key_size", tgt->u.crypt.integrity_key_size) : "");
if (r < 0 || (size_t)r >= sizeof(features))
goto out;
} else
Expand Down Expand Up @@ -1748,6 +1756,10 @@ int dm_create_device(struct crypt_device *cd, const char *name,
log_err(cd, _("The device size is not multiple of the requested sector size."));
r = -EINVAL;
}
if (dmd->segment.u.crypt.integrity_key_size && !(dmt_flags & DM_CRYPT_INTEGRITY_KEY_SIZE_OPT_SUPPORTED)) {
log_err(cd, _("Requested integrity_key_size option is not supported."));
r = -EINVAL;
}
}

if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
Expand Down Expand Up @@ -2065,6 +2077,8 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags,
if (!rintegrity)
goto err;
rintegrity++;
} else if (sscanf(arg, "integrity_key_size:%u", &val) == 1) {
tgt->u.crypt.integrity_key_size = val;
} else if (sscanf(arg, "sector_size:%u", &val) == 1) {
tgt->u.crypt.sector_size = val;
} else /* unknown option */
Expand Down Expand Up @@ -3142,7 +3156,8 @@ int dm_is_dm_kernel_name(const char *name)

int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
struct device *data_device, struct volume_key *vk, const char *cipher,
uint64_t iv_offset, uint64_t data_offset, const char *integrity, uint32_t tag_size,
uint64_t iv_offset, uint64_t data_offset,
const char *integrity, uint32_t integrity_key_size, uint32_t tag_size,
uint32_t sector_size)
{
char *dm_integrity = NULL;
Expand All @@ -3168,6 +3183,7 @@ int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg
tgt->u.crypt.offset = data_offset;
tgt->u.crypt.tag_size = tag_size;
tgt->u.crypt.sector_size = sector_size;
tgt->u.crypt.integrity_key_size = integrity_key_size;

return 0;
}
Expand Down
5 changes: 2 additions & 3 deletions lib/loopaes/loopaes.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,8 @@ int LOOPAES_activate(struct crypt_device *cd,
return -ENOMEM;

r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
vk, cipher, crypt_get_iv_offset(cd),
crypt_get_data_offset(cd), crypt_get_integrity(cd),
crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
vk, cipher, crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
NULL, 0, 0, crypt_get_sector_size(cd));

if (r) {
free(cipher);
Expand Down
2 changes: 1 addition & 1 deletion lib/luks1/keyencryption.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static int LUKS_endec_template(char *src, size_t srcLength,

r = dm_crypt_target_set(&dmd.segment, 0, dmd.size,
crypt_metadata_device(ctx), vk, cipher_spec, 0, sector,
NULL, 0, SECTOR_SIZE);
NULL, 0, 0, SECTOR_SIZE);
if (r)
goto out;

Expand Down
3 changes: 1 addition & 2 deletions lib/luks1/keymanage.c
Original file line number Diff line number Diff line change
Expand Up @@ -1204,8 +1204,7 @@ int LUKS1_activate(struct crypt_device *cd,

r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd),
crypt_get_data_offset(cd), crypt_get_integrity(cd),
crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
crypt_get_data_offset(cd), NULL, 0, 0, crypt_get_sector_size(cd));
if (!r)
r = create_or_reload_device(cd, name, CRYPT_LUKS1, &dmd);

Expand Down
4 changes: 2 additions & 2 deletions lib/luks2/luks2_json_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -2519,7 +2519,7 @@ int LUKS2_assembly_multisegment_dmd(struct crypt_device *cd,
crypt_data_device(cd), vk,
json_segment_get_cipher(jobj),
json_segment_get_iv_offset(jobj),
segment_offset, "none", 0,
segment_offset, "none", 0, 0,
json_segment_get_sector_size(jobj));
if (r) {
log_err(cd, _("Failed to set dm-crypt segment."));
Expand Down Expand Up @@ -2715,7 +2715,7 @@ int LUKS2_activate(struct crypt_device *cd,
crypt_key, crypt_get_cipher_spec(cd),
crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
crypt_get_integrity(cd) ?: "none",
crypt_get_integrity_tag_size(cd),
0, /* FIXME */, crypt_get_integrity_tag_size(cd),
crypt_get_sector_size(cd));
} else
r = dm_linear_target_set(&dmd.segment, 0,
Expand Down
3 changes: 1 addition & 2 deletions lib/luks2/luks2_reencrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2114,8 +2114,7 @@ static int reencrypt_make_targets(struct crypt_device *cd,
json_segment_get_cipher(jobj),
json_segment_get_iv_offset(jobj),
segment_offset,
"none",
0,
"none", 0, 0,
json_segment_get_sector_size(jobj));
if (r) {
log_err(cd, _("Failed to set dm-crypt segment."));
Expand Down
5 changes: 2 additions & 3 deletions lib/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,8 +609,7 @@ int PLAIN_activate(struct crypt_device *cd,

r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, crypt_data_device(cd),
vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd),
crypt_get_data_offset(cd), crypt_get_integrity(cd),
crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd));
crypt_get_data_offset(cd), NULL, 0, 0, crypt_get_sector_size(cd));
if (r < 0)
return r;

Expand Down Expand Up @@ -3701,7 +3700,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
r = dm_crypt_target_set(&dmd.segment, 0, new_size, crypt_data_device(cd),
tgt->u.crypt.vk, crypt_get_cipher_spec(cd),
crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
crypt_get_integrity(cd), crypt_get_integrity_tag_size(cd),
crypt_get_integrity(cd), 0 /* FIXME */, crypt_get_integrity_tag_size(cd),
crypt_get_sector_size(cd));
if (r < 0)
goto out;
Expand Down
5 changes: 1 addition & 4 deletions lib/tcrypt/tcrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -887,10 +887,7 @@ int TCRYPT_activate(struct crypt_device *cd,
}

r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, ptr_dev, vk,
cipher_spec, iv_offset, offset,
crypt_get_integrity(cd),
crypt_get_integrity_tag_size(cd),
crypt_get_sector_size(cd));
cipher_spec, iv_offset, offset, NULL, 0, 0, crypt_get_sector_size(cd));
if (r)
break;

Expand Down
7 changes: 5 additions & 2 deletions lib/utils_dm.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ static inline uint32_t act2dmflags(uint32_t act_flags)
#define DM_INTEGRITY_RESET_RECALC_SUPPORTED (1 << 27) /* dm-integrity automatic recalculation supported */
#define DM_VERITY_TASKLETS_SUPPORTED (1 << 28) /* dm-verity tasklets supported */
#define DM_CRYPT_HIGH_PRIORITY_SUPPORTED (1 << 29) /* dm-crypt high priority workqueue flag supported */
#define DM_CRYPT_INTEGRITY_KEY_SIZE_OPT_SUPPORTED (1 << 30) /* dm-crypt support for integrity_key_size option */

typedef enum { DM_CRYPT = 0, DM_VERITY, DM_INTEGRITY, DM_LINEAR, DM_ERROR, DM_ZERO, DM_UNKNOWN } dm_target_type;
enum tdirection { TARGET_EMPTY = 0, TARGET_SET, TARGET_QUERY };
Expand Down Expand Up @@ -109,6 +110,7 @@ struct dm_target {
uint64_t iv_offset; /* IV initialisation sector */
uint32_t tag_size; /* additional on-disk tag size */
uint32_t sector_size; /* encryption sector size */
uint32_t integrity_key_size; /* for wrapped key HMAC */
} crypt;
struct {
struct device *hash_device;
Expand Down Expand Up @@ -183,8 +185,9 @@ void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd

int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
struct device *data_device, struct volume_key *vk, const char *cipher,
uint64_t iv_offset, uint64_t data_offset, const char *integrity,
uint32_t tag_size, uint32_t sector_size);
uint64_t iv_offset, uint64_t data_offset,
const char *integrity, uint32_t integrity_key_size, uint32_t tag_size,
uint32_t sector_size);
int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
struct device *data_device, struct device *hash_device, struct device *fec_device,
const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
Expand Down
11 changes: 2 additions & 9 deletions lib/utils_storage_wrappers.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,8 @@ static int crypt_storage_dmcrypt_init(
if (vk->key_description)
dmd.flags |= CRYPT_ACTIVATE_KEYRING_KEY;

r = dm_crypt_target_set(&dmd.segment, 0, dmd.size,
device,
vk,
cipher_spec,
iv_start,
device_offset,
NULL,
0,
sector_size);
r = dm_crypt_target_set(&dmd.segment, 0, dmd.size, device, vk, cipher_spec, iv_start,
device_offset, NULL, 0, 0, sector_size);
if (r)
return r;

Expand Down

0 comments on commit ec57658

Please sign in to comment.