mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Allow specific integrity key size.
This patch add support for setting of integrity key size for LUKS2 devices. It adds new (optional) JSON "key_size" attribute in segment.integrity JSON object. If not set, the code use hash length size (backward compatible). For LUKS2, we do not allow smaller keys than 128 bits. Mostly based on code from Ingo Franzki <ifranzki@linux.ibm.com>
This commit is contained in:
@@ -37,6 +37,8 @@
|
||||
|
||||
#define LUKS2_DIGEST_MAX 8
|
||||
|
||||
#define LUKS2_MIN_INTEGRITY_KEY_BYTES 16
|
||||
|
||||
#define CRYPT_ANY_SEGMENT -1
|
||||
#define CRYPT_DEFAULT_SEGMENT -2
|
||||
#define CRYPT_ONE_SEGMENT -3
|
||||
@@ -377,6 +379,7 @@ int LUKS2_generate_hdr(
|
||||
const struct volume_key *vk,
|
||||
const char *cipher_spec,
|
||||
const char *integrity,
|
||||
uint32_t integrity_key_size, /* in bytes, only if separate (HMAC) */
|
||||
const char *uuid,
|
||||
unsigned int sector_size,
|
||||
uint64_t data_offset,
|
||||
@@ -404,6 +407,7 @@ int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic);
|
||||
uint32_t LUKS2_get_sector_size(struct luks2_hdr *hdr);
|
||||
const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment);
|
||||
const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment);
|
||||
int LUKS2_get_integrity_key_size(struct luks2_hdr *hdr, int segment);
|
||||
int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
struct luks2_keyslot_params *params);
|
||||
int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment);
|
||||
|
||||
@@ -292,7 +292,7 @@ void json_segment_remove_flag(json_object *jobj_segment, const char *flag);
|
||||
uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise);
|
||||
json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption);
|
||||
json_object *json_segment_create_crypt(uint64_t offset, uint64_t iv_offset, const uint64_t *length,
|
||||
const char *cipher, const char *integrity,
|
||||
const char *cipher, const char *integrity, uint32_t integrity_key_size,
|
||||
uint32_t sector_size, unsigned reencryption);
|
||||
json_object *json_segment_create_opal(uint64_t offset, const uint64_t *length,
|
||||
uint32_t segment_number, uint32_t key_size);
|
||||
|
||||
@@ -193,6 +193,7 @@ int LUKS2_generate_hdr(
|
||||
const struct volume_key *vk,
|
||||
const char *cipher_spec,
|
||||
const char *integrity,
|
||||
uint32_t integrity_key_size, /* in bytes, only if separate (HMAC) */
|
||||
const char *uuid,
|
||||
unsigned int sector_size, /* in bytes */
|
||||
uint64_t data_offset, /* in bytes */
|
||||
@@ -279,8 +280,8 @@ int LUKS2_generate_hdr(
|
||||
if (!opal_key_size)
|
||||
jobj_segment = json_segment_create_crypt(data_offset, 0,
|
||||
NULL, cipher_spec,
|
||||
integrity, sector_size,
|
||||
0);
|
||||
integrity, integrity_key_size,
|
||||
sector_size, 0);
|
||||
else if (opal_key_size && cipher_spec)
|
||||
jobj_segment = json_segment_create_opal_crypt(data_offset, &device_size_bytes,
|
||||
opal_segment_number, opal_key_size, 0,
|
||||
|
||||
@@ -2129,6 +2129,10 @@ static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
json_object_object_get_ex(jobj1, "type", &jobj2))
|
||||
log_std(cd, "\tintegrity: %s\n", json_object_get_string(jobj2));
|
||||
|
||||
if (json_object_object_get_ex(jobj_segment, "integrity", &jobj1) &&
|
||||
json_object_object_get_ex(jobj1, "key_size", &jobj2))
|
||||
log_std(cd, "\tintegrity key size: %" PRIu32 " [bits]\n", crypt_jobj_get_uint32(jobj2) * 8);
|
||||
|
||||
if (json_object_object_get_ex(jobj_segment, "flags", &jobj1) &&
|
||||
(flags = (int)json_object_array_length(jobj1)) > 0) {
|
||||
jobj2 = json_object_array_get_idx(jobj1, 0);
|
||||
@@ -2364,6 +2368,24 @@ const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment)
|
||||
return json_object_get_string(jobj3);
|
||||
}
|
||||
|
||||
int LUKS2_get_integrity_key_size(struct luks2_hdr *hdr, int segment)
|
||||
{
|
||||
json_object *jobj1, *jobj2, *jobj3;
|
||||
|
||||
jobj1 = LUKS2_get_segment_jobj(hdr, segment);
|
||||
if (!jobj1)
|
||||
return -1;
|
||||
|
||||
if (!json_object_object_get_ex(jobj1, "integrity", &jobj2))
|
||||
return -1;
|
||||
|
||||
/* The value is optional, do not fail if not present */
|
||||
if (!json_object_object_get_ex(jobj2, "key_size", &jobj3))
|
||||
return 0;
|
||||
|
||||
return json_object_get_int(jobj3);
|
||||
}
|
||||
|
||||
/* FIXME: this only ensures that once we have journal encryption, it is not ignored. */
|
||||
/* implement segment count and type restrictions (crypt and only single crypt) */
|
||||
static int LUKS2_integrity_compatible(struct luks2_hdr *hdr)
|
||||
@@ -2715,7 +2737,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_key_size(cd), crypt_get_integrity_tag_size(cd),
|
||||
crypt_get_sector_size(cd));
|
||||
} else
|
||||
r = dm_linear_target_set(&dmd.segment, 0,
|
||||
|
||||
@@ -310,7 +310,7 @@ static json_object *reencrypt_make_hot_segments_encrypt_shift(struct luks2_hdr *
|
||||
rh->offset >> SECTOR_SHIFT,
|
||||
&rh->length,
|
||||
reencrypt_segment_cipher_new(hdr),
|
||||
NULL, /* integrity */
|
||||
NULL, 0, /* integrity */
|
||||
reencrypt_get_sector_size_new(hdr),
|
||||
1);
|
||||
|
||||
@@ -366,7 +366,7 @@ static json_object *reencrypt_make_segment_new(struct crypt_device *cd,
|
||||
crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT),
|
||||
segment_length,
|
||||
reencrypt_segment_cipher_new(hdr),
|
||||
NULL, /* integrity */
|
||||
NULL, 0, /* integrity */
|
||||
reencrypt_get_sector_size_new(hdr), 0);
|
||||
case CRYPT_REENCRYPT_DECRYPT:
|
||||
return json_segment_create_linear(data_offset + segment_offset, segment_length, 0);
|
||||
@@ -478,7 +478,7 @@ static json_object *reencrypt_make_segment_reencrypt(struct crypt_device *cd,
|
||||
crypt_get_iv_offset(cd) + (iv_offset >> SECTOR_SHIFT),
|
||||
segment_length,
|
||||
reencrypt_segment_cipher_new(hdr),
|
||||
NULL, /* integrity */
|
||||
NULL, 0, /* integrity */
|
||||
reencrypt_get_sector_size_new(hdr), 1);
|
||||
case CRYPT_REENCRYPT_DECRYPT:
|
||||
return json_segment_create_linear(data_offset + segment_offset, segment_length, 1);
|
||||
@@ -503,7 +503,7 @@ static json_object *reencrypt_make_segment_old(struct crypt_device *cd,
|
||||
crypt_get_iv_offset(cd) + (segment_offset >> SECTOR_SHIFT),
|
||||
segment_length,
|
||||
reencrypt_segment_cipher_old(hdr),
|
||||
NULL, /* integrity */
|
||||
NULL, 0, /* integrity */
|
||||
reencrypt_get_sector_size_old(hdr),
|
||||
0);
|
||||
break;
|
||||
@@ -2027,7 +2027,7 @@ static int reencrypt_set_decrypt_shift_segments(struct crypt_device *cd,
|
||||
r = -EINVAL;
|
||||
jobj_segment_first = json_segment_create_crypt(0, crypt_get_iv_offset(cd),
|
||||
&moved_segment_length, crypt_get_cipher_spec(cd),
|
||||
NULL, crypt_get_sector_size(cd), 0);
|
||||
NULL, 0, crypt_get_sector_size(cd), 0);
|
||||
|
||||
if (!jobj_segment_first) {
|
||||
log_dbg(cd, "Failed generate 1st segment.");
|
||||
@@ -2043,7 +2043,7 @@ static int reencrypt_set_decrypt_shift_segments(struct crypt_device *cd,
|
||||
crypt_get_iv_offset(cd) + (moved_segment_length >> SECTOR_SHIFT),
|
||||
NULL,
|
||||
crypt_get_cipher_spec(cd),
|
||||
NULL, /* integrity */
|
||||
NULL, 0, /* integrity */
|
||||
crypt_get_sector_size(cd), 0);
|
||||
if (!jobj_segment_second) {
|
||||
r = -EINVAL;
|
||||
@@ -2532,7 +2532,7 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
|
||||
json_segment_get_iv_offset(jobj_tmp),
|
||||
device_size ? &device_size : NULL,
|
||||
json_segment_get_cipher(jobj_tmp),
|
||||
NULL, /* integrity */
|
||||
NULL, 0, /* integrity */
|
||||
json_segment_get_sector_size(jobj_tmp),
|
||||
0);
|
||||
} else {
|
||||
@@ -2579,7 +2579,7 @@ static int reencrypt_make_backup_segments(struct crypt_device *cd,
|
||||
}
|
||||
jobj_segment_new = json_segment_create_crypt(segment_offset,
|
||||
crypt_get_iv_offset(cd),
|
||||
NULL, cipher, NULL, sector_size, 0);
|
||||
NULL, cipher, NULL, 0, sector_size, 0);
|
||||
} else if (params->mode == CRYPT_REENCRYPT_DECRYPT) {
|
||||
segment_offset = data_offset;
|
||||
if (modify_offset(&segment_offset, data_shift, params->direction)) {
|
||||
|
||||
@@ -270,7 +270,7 @@ json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length,
|
||||
}
|
||||
|
||||
static bool json_add_crypt_fields(json_object *jobj_segment, uint64_t iv_offset,
|
||||
const char *cipher, const char *integrity,
|
||||
const char *cipher, const char *integrity, uint32_t integrity_key_size,
|
||||
uint32_t sector_size, unsigned reencryption)
|
||||
{
|
||||
json_object *jobj_integrity;
|
||||
@@ -289,6 +289,8 @@ static bool json_add_crypt_fields(json_object *jobj_segment, uint64_t iv_offset,
|
||||
json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
|
||||
json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
|
||||
json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
|
||||
if (integrity_key_size)
|
||||
json_object_object_add(jobj_integrity, "key_size", json_object_new_int(integrity_key_size));
|
||||
json_object_object_add(jobj_segment, "integrity", jobj_integrity);
|
||||
}
|
||||
|
||||
@@ -300,7 +302,7 @@ static bool json_add_crypt_fields(json_object *jobj_segment, uint64_t iv_offset,
|
||||
|
||||
json_object *json_segment_create_crypt(uint64_t offset,
|
||||
uint64_t iv_offset, const uint64_t *length,
|
||||
const char *cipher, const char *integrity,
|
||||
const char *cipher, const char *integrity, uint32_t integrity_key_size,
|
||||
uint32_t sector_size, unsigned reencryption)
|
||||
{
|
||||
json_object *jobj = _segment_create_generic("crypt", offset, length);
|
||||
@@ -308,7 +310,7 @@ json_object *json_segment_create_crypt(uint64_t offset,
|
||||
if (!jobj)
|
||||
return NULL;
|
||||
|
||||
if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, sector_size, reencryption))
|
||||
if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, integrity_key_size, sector_size, reencryption))
|
||||
return jobj;
|
||||
|
||||
json_object_put(jobj);
|
||||
@@ -350,7 +352,7 @@ json_object *json_segment_create_opal_crypt(uint64_t offset, const uint64_t *len
|
||||
|
||||
json_add_opal_fields(jobj, length, segment_number, key_size);
|
||||
|
||||
if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, sector_size, reencryption))
|
||||
if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, 0, sector_size, reencryption))
|
||||
return jobj;
|
||||
|
||||
json_object_put(jobj);
|
||||
|
||||
Reference in New Issue
Block a user