"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/luks2/luks2_json_metadata.c" between
cryptsetup-2.3.6.tar.xz and cryptsetup-2.4.0.tar.xz

About: cryptsetup is a utility used to conveniently setup disk encryption based on the dm-crypt kernel module. These include plain dm-crypt volumes, LUKS volumes, loop-AES and TrueCrypt compatible format.

luks2_json_metadata.c  (cryptsetup-2.3.6.tar.xz):luks2_json_metadata.c  (cryptsetup-2.4.0.tar.xz)
skipping to change at line 406 skipping to change at line 406
return 0; return 0;
} }
} }
i++; i++;
} }
return 1; return 1;
} }
static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_jobj static int LUKS2_keyslot_validate(struct crypt_device *cd, json_object *hdr_jobj
, json_object *hdr_keyslot, const char *key) __attribute__((unused)),
json_object *hdr_keyslot, const char *key)
{ {
json_object *jobj_key_size; json_object *jobj_key_size;
if (!json_contains(cd, hdr_keyslot, key, "Keyslot", "type", json_type_str ing)) if (!json_contains(cd, hdr_keyslot, key, "Keyslot", "type", json_type_str ing))
return 1; return 1;
if (!(jobj_key_size = json_contains(cd, hdr_keyslot, key, "Keyslot", "key _size", json_type_int))) if (!(jobj_key_size = json_contains(cd, hdr_keyslot, key, "Keyslot", "key _size", json_type_int)))
return 1; return 1;
/* enforce uint32_t type */ /* enforce uint32_t type */
if (!validate_json_uint32(jobj_key_size)) { if (!validate_json_uint32(jobj_key_size)) {
skipping to change at line 519 skipping to change at line 520
return 1; return 1;
if (LUKS2_token_validate(cd, hdr_jobj, val, key)) if (LUKS2_token_validate(cd, hdr_jobj, val, key))
return 1; return 1;
} }
return 0; return 0;
} }
static int hdr_validate_crypt_segment(struct crypt_device *cd, static int hdr_validate_crypt_segment(struct crypt_device *cd,
json_object *jobj, const char *key, json_ob ject *jobj_digests, json_object *jobj, const char *key, json_ob ject *jobj_digests,
uint64_t offset, uint64_t size) uint64_t offset __attribute__((unused)), ui nt64_t size)
{ {
json_object *jobj_ivoffset, *jobj_sector_size, *jobj_integrity; json_object *jobj_ivoffset, *jobj_sector_size, *jobj_integrity;
uint32_t sector_size; uint32_t sector_size;
uint64_t ivoffset; uint64_t ivoffset;
if (!(jobj_ivoffset = json_contains(cd, jobj, key, "Segment", "iv_tweak", json_type_string)) || if (!(jobj_ivoffset = json_contains(cd, jobj, key, "Segment", "iv_tweak", json_type_string)) ||
!json_contains(cd, jobj, key, "Segment", "encryption", json_type_stri ng) || !json_contains(cd, jobj, key, "Segment", "encryption", json_type_stri ng) ||
!(jobj_sector_size = json_contains(cd, jobj, key, "Segment", "sector_ size", json_type_int))) !(jobj_sector_size = json_contains(cd, jobj, key, "Segment", "sector_ size", json_type_int)))
return 1; return 1;
skipping to change at line 723 skipping to change at line 724
for (; i < count; i++) { for (; i < count; i++) {
if (!json_segments_get_segment(jobj_segments, i)) { if (!json_segments_get_segment(jobj_segments, i)) {
log_dbg(cd, "Gap at key %d in segments object.", i); log_dbg(cd, "Gap at key %d in segments object.", i);
return 1; return 1;
} }
} }
return 0; return 0;
} }
uint64_t LUKS2_metadata_size(json_object *jobj) static uint64_t LUKS2_metadata_size_jobj(json_object *jobj)
{ {
json_object *jobj1, *jobj2; json_object *jobj1, *jobj2;
uint64_t json_size; uint64_t json_size;
json_object_object_get_ex(jobj, "config", &jobj1); json_object_object_get_ex(jobj, "config", &jobj1);
json_object_object_get_ex(jobj1, "json_size", &jobj2); json_object_object_get_ex(jobj1, "json_size", &jobj2);
json_str_to_uint64(jobj2, &json_size); json_str_to_uint64(jobj2, &json_size);
return json_size + LUKS2_HDR_BIN_LEN; return json_size + LUKS2_HDR_BIN_LEN;
} }
uint64_t LUKS2_metadata_size(struct luks2_hdr *hdr)
{
return LUKS2_metadata_size_jobj(hdr->jobj);
}
static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj) static int hdr_validate_areas(struct crypt_device *cd, json_object *hdr_jobj)
{ {
struct interval *intervals; struct interval *intervals;
json_object *jobj_keyslots, *jobj_offset, *jobj_length, *jobj_segments, * jobj_area; json_object *jobj_keyslots, *jobj_offset, *jobj_length, *jobj_segments, * jobj_area;
int length, ret, i = 0; int length, ret, i = 0;
uint64_t metadata_size; uint64_t metadata_size;
if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots)) if (!json_object_object_get_ex(hdr_jobj, "keyslots", &jobj_keyslots))
return 1; return 1;
/* segments are already validated */ /* segments are already validated */
if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments))
return 1; return 1;
/* config is already validated */ /* config is already validated */
metadata_size = LUKS2_metadata_size(hdr_jobj); metadata_size = LUKS2_metadata_size_jobj(hdr_jobj);
length = json_object_object_length(jobj_keyslots); length = json_object_object_length(jobj_keyslots);
/* Empty section */ /* Empty section */
if (length == 0) if (length == 0)
return 0; return 0;
if (length < 0) { if (length < 0) {
log_dbg(cd, "Invalid keyslot areas specification."); log_dbg(cd, "Invalid keyslot areas specification.");
return 1; return 1;
skipping to change at line 796 skipping to change at line 802
} }
i++; i++;
} }
if (length != i) { if (length != i) {
free(intervals); free(intervals);
return 1; return 1;
} }
ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_ and_areas_size(hdr_jobj)) ? 0 : 1; ret = validate_intervals(cd, length, intervals, metadata_size, LUKS2_hdr_ and_areas_size_jobj(hdr_jobj)) ? 0 : 1;
free(intervals); free(intervals);
return ret; return ret;
} }
static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj) static int hdr_validate_digests(struct crypt_device *cd, json_object *hdr_jobj)
{ {
json_object *jarr_keys, *jarr_segs, *jobj, *jobj_keyslots, *jobj_segments ; json_object *jarr_keys, *jarr_segs, *jobj, *jobj_keyslots, *jobj_segments ;
skipping to change at line 1044 skipping to change at line 1050
} }
void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr) void LUKS2_hdr_free(struct crypt_device *cd, struct luks2_hdr *hdr)
{ {
if (json_object_put(hdr->jobj)) if (json_object_put(hdr->jobj))
hdr->jobj = NULL; hdr->jobj = NULL;
else if (hdr->jobj) else if (hdr->jobj)
log_dbg(cd, "LUKS2 header still in use"); log_dbg(cd, "LUKS2 header still in use");
} }
uint64_t LUKS2_keyslots_size(json_object *jobj) static uint64_t LUKS2_keyslots_size_jobj(json_object *jobj)
{ {
json_object *jobj1, *jobj2; json_object *jobj1, *jobj2;
uint64_t keyslots_size; uint64_t keyslots_size;
json_object_object_get_ex(jobj, "config", &jobj1); json_object_object_get_ex(jobj, "config", &jobj1);
json_object_object_get_ex(jobj1, "keyslots_size", &jobj2); json_object_object_get_ex(jobj1, "keyslots_size", &jobj2);
json_str_to_uint64(jobj2, &keyslots_size); json_str_to_uint64(jobj2, &keyslots_size);
return keyslots_size; return keyslots_size;
} }
uint64_t LUKS2_hdr_and_areas_size(json_object *jobj) uint64_t LUKS2_keyslots_size(struct luks2_hdr *hdr)
{
return LUKS2_keyslots_size_jobj(hdr->jobj);
}
uint64_t LUKS2_hdr_and_areas_size_jobj(json_object *jobj)
{ {
return 2 * LUKS2_metadata_size(jobj) + LUKS2_keyslots_size(jobj); return 2 * LUKS2_metadata_size_jobj(jobj) + LUKS2_keyslots_size_jobj(jobj
);
}
uint64_t LUKS2_hdr_and_areas_size(struct luks2_hdr *hdr)
{
return LUKS2_hdr_and_areas_size_jobj(hdr->jobj);
} }
int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr, int LUKS2_hdr_backup(struct crypt_device *cd, struct luks2_hdr *hdr,
const char *backup_file) const char *backup_file)
{ {
struct device *device = crypt_metadata_device(cd); struct device *device = crypt_metadata_device(cd);
int fd, devfd, r = 0; int fd, devfd, r = 0;
ssize_t hdr_size; ssize_t hdr_size;
ssize_t ret, buffer_size; ssize_t ret, buffer_size;
char *buffer = NULL; char *buffer = NULL;
hdr_size = LUKS2_hdr_and_areas_size(hdr->jobj); hdr_size = LUKS2_hdr_and_areas_size(hdr);
buffer_size = size_round_up(hdr_size, crypt_getpagesize()); buffer_size = size_round_up(hdr_size, crypt_getpagesize());
buffer = crypt_safe_alloc(buffer_size); buffer = crypt_safe_alloc(buffer_size);
if (!buffer) if (!buffer)
return -ENOMEM; return -ENOMEM;
log_dbg(cd, "Storing backup of header (%zu bytes).", hdr_size); log_dbg(cd, "Storing backup of header (%zu bytes).", hdr_size);
log_dbg(cd, "Output backup file size: %zu bytes.", buffer_size); log_dbg(cd, "Output backup file size: %zu bytes.", buffer_size);
r = device_read_lock(cd, device); r = device_read_lock(cd, device);
skipping to change at line 1181 skipping to change at line 1197
} }
/* do not allow header restore from backup with unmet requirements */ /* do not allow header restore from backup with unmet requirements */
if (LUKS2_unmet_requirements(cd, &hdr_file, CRYPT_REQUIREMENT_ONLINE_REEN CRYPT, 1)) { if (LUKS2_unmet_requirements(cd, &hdr_file, CRYPT_REQUIREMENT_ONLINE_REEN CRYPT, 1)) {
log_err(cd, _("Forbidden LUKS2 requirements detected in backup %s ."), log_err(cd, _("Forbidden LUKS2 requirements detected in backup %s ."),
backup_file); backup_file);
r = -ETXTBSY; r = -ETXTBSY;
goto out; goto out;
} }
buffer_size = LUKS2_hdr_and_areas_size(hdr_file.jobj); buffer_size = LUKS2_hdr_and_areas_size(&hdr_file);
buffer = crypt_safe_alloc(buffer_size); buffer = crypt_safe_alloc(buffer_size);
if (!buffer) { if (!buffer) {
r = -ENOMEM; r = -ENOMEM;
goto out; goto out;
} }
fd = open(backup_file, O_RDONLY); fd = open(backup_file, O_RDONLY);
if (fd == -1) { if (fd == -1) {
log_err(cd, _("Cannot open header backup file %s."), backup_file) ; log_err(cd, _("Cannot open header backup file %s."), backup_file) ;
r = -EINVAL; r = -EINVAL;
skipping to change at line 1221 skipping to change at line 1237
diff_uuid = 1; diff_uuid = 1;
if (!reqs_reencrypt(reqs)) { if (!reqs_reencrypt(reqs)) {
log_dbg(cd, "Checking LUKS2 header size and offsets."); log_dbg(cd, "Checking LUKS2 header size and offsets.");
if (LUKS2_get_data_offset(&tmp_hdr) != LUKS2_get_data_off set(&hdr_file)) { if (LUKS2_get_data_offset(&tmp_hdr) != LUKS2_get_data_off set(&hdr_file)) {
log_err(cd, _("Data offset differ on device and b ackup, restore failed.")); log_err(cd, _("Data offset differ on device and b ackup, restore failed."));
r = -EINVAL; r = -EINVAL;
goto out; goto out;
} }
/* FIXME: what could go wrong? Erase if we're fine with c onsequences */ /* FIXME: what could go wrong? Erase if we're fine with c onsequences */
if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(tmp _hdr.jobj)) { if (buffer_size != (ssize_t) LUKS2_hdr_and_areas_size(&tm p_hdr)) {
log_err(cd, _("Binary header with keyslot areas s ize differ on device and backup, restore failed.")); log_err(cd, _("Binary header with keyslot areas s ize differ on device and backup, restore failed."));
r = -EINVAL; r = -EINVAL;
goto out; goto out;
} }
} }
} }
r = snprintf(msg, sizeof(msg), _("Device %s %s%s%s%s"), device_path(devic e), r = snprintf(msg, sizeof(msg), _("Device %s %s%s%s%s"), device_path(devic e),
r ? _("does not contain LUKS2 header. Replacing header can d estroy data on that device.") : r ? _("does not contain LUKS2 header. Replacing header can d estroy data on that device.") :
_("already contains LUKS2 header. Replacing header will destroy existing keyslots."), _("already contains LUKS2 header. Replacing header will destroy existing keyslots."),
skipping to change at line 1623 skipping to change at line 1639
json_object_object_get_ex(val, "type", &jobj2); json_object_object_get_ex(val, "type", &jobj2);
tmps = json_object_get_string(jobj2); tmps = json_object_get_string(jobj2);
log_std(cd, " %s: %s\n", token, tmps); log_std(cd, " %s: %s\n", token, tmps);
LUKS2_token_dump(cd, j); LUKS2_token_dump(cd, j);
json_object_object_get_ex(val, "keyslots", &jobj2); json_object_object_get_ex(val, "keyslots", &jobj2);
for (i = 0; i < (int) json_object_array_length(jobj2); i++) { for (i = 0; i < (int) json_object_array_length(jobj2); i++) {
jobj3 = json_object_array_get_idx(jobj2, i); jobj3 = json_object_array_get_idx(jobj2, i);
log_std(cd, "\tKeyslot: %s\n", json_object_get_string(jo bj3)); log_std(cd, "\tKeyslot: %s\n", json_object_get_string( jobj3));
} }
} }
} }
static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj) static void hdr_dump_segments(struct crypt_device *cd, json_object *hdr_jobj)
{ {
char segment[16]; char segment[16];
json_object *jobj_segments, *jobj_segment, *jobj1, *jobj2; json_object *jobj_segments, *jobj_segment, *jobj1, *jobj2;
int i, j, flags; int i, j, flags;
uint64_t value; uint64_t value;
skipping to change at line 1717 skipping to change at line 1733
int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr) int LUKS2_hdr_dump(struct crypt_device *cd, struct luks2_hdr *hdr)
{ {
if (!hdr->jobj) if (!hdr->jobj)
return -EINVAL; return -EINVAL;
JSON_DBG(cd, hdr->jobj, NULL); JSON_DBG(cd, hdr->jobj, NULL);
log_std(cd, "LUKS header information\n"); log_std(cd, "LUKS header information\n");
log_std(cd, "Version: \t%u\n", hdr->version); log_std(cd, "Version: \t%u\n", hdr->version);
log_std(cd, "Epoch: \t%" PRIu64 "\n", hdr->seqid); log_std(cd, "Epoch: \t%" PRIu64 "\n", hdr->seqid);
log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size log_std(cd, "Metadata area: \t%" PRIu64 " [bytes]\n", LUKS2_metadata_size
(hdr->jobj)); (hdr));
log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size log_std(cd, "Keyslots area: \t%" PRIu64 " [bytes]\n", LUKS2_keyslots_size
(hdr->jobj)); (hdr));
log_std(cd, "UUID: \t%s\n", *hdr->uuid ? hdr->uuid : "(no UUID)" ); log_std(cd, "UUID: \t%s\n", *hdr->uuid ? hdr->uuid : "(no UUID)" );
log_std(cd, "Label: \t%s\n", *hdr->label ? hdr->label : "(no labe l)"); log_std(cd, "Label: \t%s\n", *hdr->label ? hdr->label : "(no labe l)");
log_std(cd, "Subsystem: \t%s\n", *hdr->subsystem ? hdr->subsystem : " (no subsystem)"); log_std(cd, "Subsystem: \t%s\n", *hdr->subsystem ? hdr->subsystem : " (no subsystem)");
hdr_dump_config(cd, hdr->jobj); hdr_dump_config(cd, hdr->jobj);
hdr_dump_segments(cd, hdr->jobj); hdr_dump_segments(cd, hdr->jobj);
hdr_dump_keyslots(cd, hdr->jobj); hdr_dump_keyslots(cd, hdr->jobj);
hdr_dump_tokens(cd, hdr->jobj); hdr_dump_tokens(cd, hdr->jobj);
hdr_dump_digests(cd, hdr->jobj); hdr_dump_digests(cd, hdr->jobj);
return 0; return 0;
} }
int LUKS2_hdr_dump_json(struct crypt_device *cd, struct luks2_hdr *hdr, const ch
ar **json)
{
const char *json_buf;
json_buf = json_object_to_json_string_ext(hdr->jobj,
JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_NOSLASHESCAPE);
if (!json_buf)
return -EINVAL;
if (json)
*json = json_buf;
else
crypt_log(cd, CRYPT_LOG_NORMAL, json_buf);
return 0;
}
int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic) int LUKS2_get_data_size(struct luks2_hdr *hdr, uint64_t *size, bool *dynamic)
{ {
int sector_size; int sector_size;
json_object *jobj_segments, *jobj_size; json_object *jobj_segments, *jobj_size;
uint64_t tmp = 0; uint64_t tmp = 0;
if (!size || !json_object_object_get_ex(hdr->jobj, "segments", &jobj_segm ents)) if (!size || !json_object_object_get_ex(hdr->jobj, "segments", &jobj_segm ents))
return -EINVAL; return -EINVAL;
json_object_object_foreach(jobj_segments, key, val) { json_object_object_foreach(jobj_segments, key, val) {
skipping to change at line 1777 skipping to change at line 1811
if (dynamic) if (dynamic)
*dynamic = false; *dynamic = false;
return 0; return 0;
} }
uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr) uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr)
{ {
crypt_reencrypt_info ri; crypt_reencrypt_info ri;
json_object *jobj; json_object *jobj;
ri = LUKS2_reenc_status(hdr); ri = LUKS2_reencrypt_status(hdr);
if (ri == CRYPT_REENCRYPT_CLEAN || ri == CRYPT_REENCRYPT_CRASH) { if (ri == CRYPT_REENCRYPT_CLEAN || ri == CRYPT_REENCRYPT_CRASH) {
jobj = LUKS2_get_segment_by_flag(hdr, "backup-final"); jobj = LUKS2_get_segment_by_flag(hdr, "backup-final");
if (jobj) if (jobj)
return json_segment_get_offset(jobj, 1); return json_segment_get_offset(jobj, 1);
} }
return json_segments_get_minimal_offset(LUKS2_get_segments_jobj(hdr), 1); return json_segments_get_minimal_offset(LUKS2_get_segments_jobj(hdr), 1);
} }
const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment) const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment)
skipping to change at line 1805 skipping to change at line 1839
segment = LUKS2_get_default_segment(hdr); segment = LUKS2_get_default_segment(hdr);
jobj_segment = json_segments_get_segment(json_get_segments_jobj(hdr->jobj ), segment); jobj_segment = json_segments_get_segment(json_get_segments_jobj(hdr->jobj ), segment);
if (!jobj_segment) if (!jobj_segment)
return NULL; return NULL;
/* FIXME: default encryption (for other segment types) must be string her e. */ /* FIXME: default encryption (for other segment types) must be string her e. */
return json_segment_get_cipher(jobj_segment) ?: "null"; return json_segment_get_cipher(jobj_segment) ?: "null";
} }
crypt_reencrypt_info LUKS2_reenc_status(struct luks2_hdr *hdr) crypt_reencrypt_info LUKS2_reencrypt_status(struct luks2_hdr *hdr)
{ {
uint32_t reqs; uint32_t reqs;
/* /*
* Any unknown requirement or offline reencryption should abort * Any unknown requirement or offline reencryption should abort
* anything related to online-reencryption handling * anything related to online-reencryption handling
*/ */
if (LUKS2_config_get_requirements(NULL, hdr, &reqs)) if (LUKS2_config_get_requirements(NULL, hdr, &reqs))
return CRYPT_REENCRYPT_INVALID; return CRYPT_REENCRYPT_INVALID;
skipping to change at line 2248 skipping to change at line 2282
/* TODO: We have LUKS2 dependencies now */ /* TODO: We have LUKS2 dependencies now */
if (hdr && single_segment(dmd) && tgt->type == DM_CRYPT && crypt_get_inte grity_tag_size(cd)) if (hdr && single_segment(dmd) && tgt->type == DM_CRYPT && crypt_get_inte grity_tag_size(cd))
namei = device_dm_name(tgt->data_device); namei = device_dm_name(tgt->data_device);
r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps)); r = dm_device_deps(cd, name, deps_uuid_prefix, deps, ARRAY_SIZE(deps));
if (r < 0) if (r < 0)
goto out; goto out;
if (contains_reencryption_helper(deps)) { if (contains_reencryption_helper(deps)) {
r = crypt_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_loc k); r = LUKS2_reencrypt_lock_by_dm_uuid(cd, dmd->uuid, &reencrypt_loc k);
if (r) { if (r) {
if (r == -EBUSY) if (r == -EBUSY)
log_err(cd, _("Reencryption in-progress. Cannot d eactivate device.")); log_err(cd, _("Reencryption in-progress. Cannot d eactivate device."));
else else
log_err(cd, _("Failed to get reencryption lock.") ); log_err(cd, _("Failed to get reencryption lock.") );
goto out; goto out;
} }
} }
dep = deps; dep = deps;
skipping to change at line 2327 skipping to change at line 2361
} }
dm_targets_free(cd, &dmdc); dm_targets_free(cd, &dmdc);
if (r && !ret) if (r && !ret)
ret = r; ret = r;
dep++; dep++;
} }
r = ret; r = ret;
} }
out: out:
crypt_reencrypt_unlock(cd, reencrypt_lock); LUKS2_reencrypt_unlock(cd, reencrypt_lock);
dep = deps; dep = deps;
while (*dep) while (*dep)
free(*dep++); free(*dep++);
return r; return r;
} }
int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uin t32_t reqs_mask, int quiet) int LUKS2_unmet_requirements(struct crypt_device *cd, struct luks2_hdr *hdr, uin t32_t reqs_mask, int quiet)
{ {
uint32_t reqs; uint32_t reqs;
 End of changes. 19 change blocks. 
21 lines changed or deleted 57 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)