"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/luks2/luks2_json_metadata.c" between
cryptsetup-2.4.2.tar.xz and cryptsetup-2.4.3.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.4.2.tar.xz):luks2_json_metadata.c  (cryptsetup-2.4.3.tar.xz)
skipping to change at line 595 skipping to change at line 595
return false; return false;
} }
} }
i++; i++;
} }
return true; return true;
} }
static int reqs_unknown(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_UNKNOWN;
}
static int reqs_reencrypt(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
}
static int reqs_reencrypt_online(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
/*
* Config section requirements object must be valid.
* Also general segments section must be validated first.
*/
static int validate_reencrypt_segments(struct crypt_device *cd, json_object *hdr
_jobj, json_object *jobj_segments, int first_backup, int segments_count)
{
json_object *jobj, *jobj_backup_previous = NULL, *jobj_backup_final = NUL
L;
uint32_t reqs;
int i, r;
struct luks2_hdr dummy = {
.jobj = hdr_jobj
};
r = LUKS2_config_get_requirements(cd, &dummy, &reqs);
if (r)
return 1;
if (reqs_reencrypt_online(reqs)) {
for (i = first_backup; i < segments_count; i++) {
jobj = json_segments_get_segment(jobj_segments, i);
if (!jobj)
return 1;
if (json_segment_contains_flag(jobj, "backup-final", 0))
jobj_backup_final = jobj;
else if (json_segment_contains_flag(jobj, "backup-previou
s", 0))
jobj_backup_previous = jobj;
}
if (!jobj_backup_final || !jobj_backup_previous) {
log_dbg(cd, "Backup segment is missing.");
return 1;
}
for (i = 0; i < first_backup; i++) {
jobj = json_segments_get_segment(jobj_segments, i);
if (!jobj)
return 1;
if (json_segment_contains_flag(jobj, "in-reencryption", 0
)) {
if (!json_segment_cmp(jobj, jobj_backup_final)) {
log_dbg(cd, "Segment in reencryption does
not match backup final segment.");
return 1;
}
continue;
}
if (!json_segment_cmp(jobj, jobj_backup_final) &&
!json_segment_cmp(jobj, jobj_backup_previous)) {
log_dbg(cd, "Segment does not match neither backu
p final or backup previous segment.");
return 1;
}
}
}
return 0;
}
static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj) static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
{ {
json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *job j_type, *jobj_flags, *jobj; json_object *jobj_segments, *jobj_digests, *jobj_offset, *jobj_size, *job j_type, *jobj_flags, *jobj;
uint64_t offset, size; uint64_t offset, size;
int i, r, count, first_backup = -1; int i, r, count, first_backup = -1;
struct interval *intervals = NULL; struct interval *intervals = NULL;
if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) { if (!json_object_object_get_ex(hdr_jobj, "segments", &jobj_segments)) {
log_dbg(cd, "Missing segments section."); log_dbg(cd, "Missing segments section.");
return 1; return 1;
skipping to change at line 721 skipping to change at line 793
if (r) if (r)
return 1; return 1;
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 validate_reencrypt_segments(cd, hdr_jobj, jobj_segments, first_bac kup, count);
} }
static uint64_t LUKS2_metadata_size_jobj(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);
skipping to change at line 844 skipping to change at line 916
if (!validate_keyslots_array(cd, jarr_keys, jobj_keyslots)) if (!validate_keyslots_array(cd, jarr_keys, jobj_keyslots))
return 1; return 1;
if (!validate_segments_array(cd, jarr_segs, jobj_segments)) if (!validate_segments_array(cd, jarr_segs, jobj_segments))
return 1; return 1;
} }
return 0; return 0;
} }
/* requirements being validated in stand-alone routine */
static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj) static int hdr_validate_config(struct crypt_device *cd, json_object *hdr_jobj)
{ {
json_object *jobj_config, *jobj, *jobj1; json_object *jobj_config, *jobj;
int i; int i;
uint64_t keyslots_size, metadata_size, segment_offset; uint64_t keyslots_size, metadata_size, segment_offset;
if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) { if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) {
log_dbg(cd, "Missing config section."); log_dbg(cd, "Missing config section.");
return 1; return 1;
} }
if (!(jobj = json_contains(cd, jobj_config, "section", "Config", "json_si ze", json_type_string)) || if (!(jobj = json_contains(cd, jobj_config, "section", "Config", "json_si ze", json_type_string)) ||
!json_str_to_uint64(jobj, &metadata_size)) !json_str_to_uint64(jobj, &metadata_size))
skipping to change at line 901 skipping to change at line 974
if (json_object_object_get_ex(jobj_config, "flags", &jobj)) { if (json_object_object_get_ex(jobj_config, "flags", &jobj)) {
if (!json_contains(cd, jobj_config, "section", "Config", "flags", json_type_array)) if (!json_contains(cd, jobj_config, "section", "Config", "flags", json_type_array))
return 1; return 1;
/* All array members must be strings */ /* All array members must be strings */
for (i = 0; i < (int) json_object_array_length(jobj); i++) for (i = 0; i < (int) json_object_array_length(jobj); i++)
if (!json_object_is_type(json_object_array_get_idx(jobj, i), json_type_string)) if (!json_object_is_type(json_object_array_get_idx(jobj, i), json_type_string))
return 1; return 1;
} }
return 0;
}
static int hdr_validate_requirements(struct crypt_device *cd, json_object *hdr_j
obj)
{
int i;
json_object *jobj_config, *jobj, *jobj1;
if (!json_object_object_get_ex(hdr_jobj, "config", &jobj_config)) {
log_dbg(cd, "Missing config section.");
return 1;
}
/* Requirements object is optional */ /* Requirements object is optional */
if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) { if (json_object_object_get_ex(jobj_config, "requirements", &jobj)) {
if (!json_contains(cd, jobj_config, "section", "Config", "require ments", json_type_object)) if (!json_contains(cd, jobj_config, "section", "Config", "require ments", json_type_object))
return 1; return 1;
/* Mandatory array is optional */ /* Mandatory array is optional */
if (json_object_object_get_ex(jobj, "mandatory", &jobj1)) { if (json_object_object_get_ex(jobj, "mandatory", &jobj1)) {
if (!json_contains(cd, jobj, "section", "Requirements", " mandatory", json_type_array)) if (!json_contains(cd, jobj, "section", "Requirements", " mandatory", json_type_array))
return 1; return 1;
skipping to change at line 926 skipping to change at line 1012
} }
return 0; return 0;
} }
int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size) int LUKS2_hdr_validate(struct crypt_device *cd, json_object *hdr_jobj, uint64_t json_size)
{ {
struct { struct {
int (*validate)(struct crypt_device *, json_object *); int (*validate)(struct crypt_device *, json_object *);
} checks[] = { } checks[] = {
{ hdr_validate_requirements },
{ hdr_validate_tokens }, { hdr_validate_tokens },
{ hdr_validate_digests }, { hdr_validate_digests },
{ hdr_validate_segments }, { hdr_validate_segments },
{ hdr_validate_keyslots }, { hdr_validate_keyslots },
{ hdr_validate_config }, { hdr_validate_config },
{ hdr_validate_areas }, { hdr_validate_areas },
{ NULL } { NULL }
}; };
int i; int i;
skipping to change at line 1142 skipping to change at line 1229
if (ret < buffer_size) { if (ret < buffer_size) {
log_err(cd, _("Cannot write header backup file %s."), backup_file ); log_err(cd, _("Cannot write header backup file %s."), backup_file );
r = -EIO; r = -EIO;
} else } else
r = 0; r = 0;
crypt_safe_free(buffer); crypt_safe_free(buffer);
return r; return r;
} }
static int reqs_unknown(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_UNKNOWN;
}
static int reqs_reencrypt(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_OFFLINE_REENCRYPT;
}
static int reqs_reencrypt_online(uint32_t reqs)
{
return reqs & CRYPT_REQUIREMENT_ONLINE_REENCRYPT;
}
int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr, int LUKS2_hdr_restore(struct crypt_device *cd, struct luks2_hdr *hdr,
const char *backup_file) const char *backup_file)
{ {
struct device *backup_device, *device = crypt_metadata_device(cd); struct device *backup_device, *device = crypt_metadata_device(cd);
int r, fd, devfd = -1, diff_uuid = 0; int r, fd, devfd = -1, diff_uuid = 0;
ssize_t ret, buffer_size = 0; ssize_t ret, buffer_size = 0;
char *buffer = NULL, msg[1024]; char *buffer = NULL, msg[1024];
struct luks2_hdr hdr_file; struct luks2_hdr hdr_file;
struct luks2_hdr tmp_hdr = {}; struct luks2_hdr tmp_hdr = {};
uint32_t reqs = 0; uint32_t reqs = 0;
skipping to change at line 1392 skipping to change at line 1464
* all other future fields may be added later) * all other future fields may be added later)
* *
* "requirements": { * "requirements": {
* mandatory : [], * mandatory : [],
* optional0 : [], * optional0 : [],
* optional1 : "lala" * optional1 : "lala"
* } * }
*/ */
/* LUKS2 library requirements */ /* LUKS2 library requirements */
static const struct { struct requirement_flag {
uint32_t flag; uint32_t flag;
uint32_t version;
const char *description; const char *description;
} requirements_flags[] = {
{ CRYPT_REQUIREMENT_OFFLINE_REENCRYPT, "offline-reencrypt" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, "online-reencrypt" },
{ 0, NULL }
}; };
static uint32_t get_requirement_by_name(const char *requirement) static const struct requirement_flag unknown_requirement_flag = { CRYPT_REQUIREM
ENT_UNKNOWN, 0, NULL };
static const struct requirement_flag requirements_flags[] = {
{ CRYPT_REQUIREMENT_OFFLINE_REENCRYPT,1, "offline-reencrypt" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
{ CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
{ 0, 0, NULL }
};
static const struct requirement_flag *get_requirement_by_name(const char *requir
ement)
{ {
int i; int i;
for (i = 0; requirements_flags[i].description; i++) for (i = 0; requirements_flags[i].description; i++)
if (!strcmp(requirement, requirements_flags[i].description)) if (!strcmp(requirement, requirements_flags[i].description))
return requirements_flags[i].flag; return requirements_flags + i;
return &unknown_requirement_flag;
}
int LUKS2_config_get_reencrypt_version(struct luks2_hdr *hdr, uint32_t *version)
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
const struct requirement_flag *req;
assert(hdr && version);
if (!hdr || !version)
return -EINVAL;
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
return -EINVAL;
if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_require
ments))
return -ENOENT;
if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mand
atory))
return -ENOENT;
len = (int) json_object_array_length(jobj_mandatory);
if (len <= 0)
return -ENOENT;
for (i = 0; i < len; i++) {
jobj = json_object_array_get_idx(jobj_mandatory, i);
/* search for requirements prefixed with "online-reencrypt" */
if (strncmp(json_object_get_string(jobj), "online-reencrypt", 16)
)
continue;
/* check current library is aware of the requirement */
req = get_requirement_by_name(json_object_get_string(jobj));
if (req->flag == (uint32_t)CRYPT_REQUIREMENT_UNKNOWN)
continue;
*version = req->version;
return 0;
}
return -ENOENT;
}
static const struct requirement_flag *stored_requirement_name_by_id(struct crypt
_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
{
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len;
const struct requirement_flag *req;
assert(hdr);
if (!hdr)
return NULL;
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
return NULL;
if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_require
ments))
return NULL;
if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mand
atory))
return NULL;
len = (int) json_object_array_length(jobj_mandatory);
if (len <= 0)
return 0;
for (i = 0; i < len; i++) {
jobj = json_object_array_get_idx(jobj_mandatory, i);
req = get_requirement_by_name(json_object_get_string(jobj));
if (req->flag == req_id)
return req;
}
return CRYPT_REQUIREMENT_UNKNOWN; return NULL;
} }
/* /*
* returns count of requirements (past cryptsetup 2.0 release) * returns count of requirements (past cryptsetup 2.0 release)
*/ */
int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr , uint32_t *reqs) int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr , uint32_t *reqs)
{ {
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj; json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, len; int i, len;
uint32_t req; const struct requirement_flag *req;
assert(hdr); assert(hdr);
if (!hdr || !reqs) if (!hdr || !reqs)
return -EINVAL; return -EINVAL;
*reqs = 0; *reqs = 0;
if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config)) if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
return 0; return 0;
skipping to change at line 1446 skipping to change at line 1600
len = (int) json_object_array_length(jobj_mandatory); len = (int) json_object_array_length(jobj_mandatory);
if (len <= 0) if (len <= 0)
return 0; return 0;
log_dbg(cd, "LUKS2 requirements detected:"); log_dbg(cd, "LUKS2 requirements detected:");
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
jobj = json_object_array_get_idx(jobj_mandatory, i); jobj = json_object_array_get_idx(jobj_mandatory, i);
req = get_requirement_by_name(json_object_get_string(jobj)); req = get_requirement_by_name(json_object_get_string(jobj));
log_dbg(cd, "%s - %sknown", json_object_get_string(jobj), log_dbg(cd, "%s - %sknown", json_object_get_string(jobj),
reqs_unknown(req) ? "un" : ""); reqs_unknown(req->flag) ? "un" : "");
*reqs |= req; *reqs |= req->flag;
} }
return 0; return 0;
} }
int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr , uint32_t reqs, bool commit) int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr , uint32_t reqs, bool commit)
{ {
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj; json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
int i, r = -EINVAL; int i, r = -EINVAL;
const struct requirement_flag *req;
uint32_t req_id;
if (!hdr) if (!hdr)
return -EINVAL; return -EINVAL;
jobj_mandatory = json_object_new_array(); jobj_mandatory = json_object_new_array();
if (!jobj_mandatory) if (!jobj_mandatory)
return -ENOMEM; return -ENOMEM;
for (i = 0; requirements_flags[i].description; i++) { for (i = 0; requirements_flags[i].description; i++) {
if (reqs & requirements_flags[i].flag) { req_id = reqs & requirements_flags[i].flag;
jobj = json_object_new_string(requirements_flags[i].descr if (req_id) {
iption); /* retain already stored version of requirement flag */
req = stored_requirement_name_by_id(cd, hdr, req_id);
if (req)
jobj = json_object_new_string(req->description);
else
jobj = json_object_new_string(requirements_flags[
i].description);
if (!jobj) { if (!jobj) {
r = -ENOMEM; r = -ENOMEM;
goto err; goto err;
} }
json_object_array_add(jobj_mandatory, jobj); json_object_array_add(jobj_mandatory, jobj);
/* erase processed flag from input set */ /* erase processed flag from input set */
reqs &= ~(requirements_flags[i].flag); reqs &= ~(requirements_flags[i].flag);
} }
} }
 End of changes. 17 change blocks. 
31 lines changed or deleted 208 lines changed or added

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