2 * LUKS - Linux Unified Key Setup v2, internal segment handling
4 * Copyright (C) 2018-2020, Red Hat, Inc. All rights reserved.
5 * Copyright (C) 2018-2020, Ondrej Kozina
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "luks2_internal.h"
24 /* use only on already validated 'segments' object */
25 uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise)
27 uint64_t tmp, min = blockwise ? UINT64_MAX >> SECTOR_SHIFT : UINT64_MAX;
32 json_object_object_foreach(jobj_segments, key, val) {
35 if (json_segment_is_backup(val))
38 tmp = json_segment_get_offset(val, blockwise);
50 uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise)
55 !json_object_object_get_ex(jobj_segment, "offset", &jobj))
58 return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
61 const char *json_segment_type(json_object *jobj_segment)
66 !json_object_object_get_ex(jobj_segment, "type", &jobj))
69 return json_object_get_string(jobj);
72 uint64_t json_segment_get_iv_offset(json_object *jobj_segment)
77 !json_object_object_get_ex(jobj_segment, "iv_tweak", &jobj))
80 return crypt_jobj_get_uint64(jobj);
83 uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise)
88 !json_object_object_get_ex(jobj_segment, "size", &jobj))
91 return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj);
94 const char *json_segment_get_cipher(json_object *jobj_segment)
98 /* FIXME: Pseudo "null" cipher should be handled elsewhere */
100 !json_object_object_get_ex(jobj_segment, "encryption", &jobj))
103 return json_object_get_string(jobj);
106 int json_segment_get_sector_size(json_object *jobj_segment)
111 !json_object_object_get_ex(jobj_segment, "sector_size", &jobj))
114 return json_object_get_int(jobj);
117 static json_object *json_segment_get_flags(json_object *jobj_segment)
121 if (!jobj_segment || !(json_object_object_get_ex(jobj_segment, "flags", &jobj)))
126 static bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len)
129 json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment);
134 for (i = 0; i < (int)json_object_array_length(jobj_flags); i++) {
135 jobj = json_object_array_get_idx(jobj_flags, i);
137 r = strncmp(json_object_get_string(jobj), flag_str, len);
139 r = strcmp(json_object_get_string(jobj), flag_str);
147 bool json_segment_is_backup(json_object *jobj_segment)
149 return json_segment_contains_flag(jobj_segment, "backup-", 7);
152 json_object *json_segments_get_segment(json_object *jobj_segments, int segment)
155 char segment_name[16];
157 if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1)
160 if (!json_object_object_get_ex(jobj_segments, segment_name, &jobj))
166 unsigned json_segments_count(json_object *jobj_segments)
173 json_object_object_foreach(jobj_segments, slot, val) {
175 if (!json_segment_is_backup(val))
182 static void _get_segment_or_id_by_flag(json_object *jobj_segments, const char *flag, unsigned id, void *retval)
184 json_object *jobj_flags, **jobj_ret = (json_object **)retval;
185 int *ret = (int *)retval;
190 json_object_object_foreach(jobj_segments, key, value) {
191 if (!json_object_object_get_ex(value, "flags", &jobj_flags))
193 if (LUKS2_array_jobj(jobj_flags, flag)) {
203 void json_segment_remove_flag(json_object *jobj_segment, const char *flag)
205 json_object *jobj_flags, *jobj_flags_new;
210 jobj_flags = json_segment_get_flags(jobj_segment);
214 jobj_flags_new = LUKS2_array_remove(jobj_flags, flag);
218 if (json_object_array_length(jobj_flags_new) <= 0) {
219 json_object_put(jobj_flags_new);
220 json_object_object_del(jobj_segment, "flags");
222 json_object_object_add(jobj_segment, "flags", jobj_flags_new);
225 static json_object *_segment_create_generic(const char *type, uint64_t offset, const uint64_t *length)
227 json_object *jobj = json_object_new_object();
231 json_object_object_add(jobj, "type", json_object_new_string(type));
232 json_object_object_add(jobj, "offset", crypt_jobj_new_uint64(offset));
233 json_object_object_add(jobj, "size", length ? crypt_jobj_new_uint64(*length) : json_object_new_string("dynamic"));
238 json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption)
240 json_object *jobj = _segment_create_generic("linear", offset, length);
242 LUKS2_segment_set_flag(jobj, "in-reencryption");
246 json_object *json_segment_create_crypt(uint64_t offset,
247 uint64_t iv_offset, const uint64_t *length,
248 const char *cipher, uint32_t sector_size,
249 unsigned reencryption)
251 json_object *jobj = _segment_create_generic("crypt", offset, length);
255 json_object_object_add(jobj, "iv_tweak", crypt_jobj_new_uint64(iv_offset));
256 json_object_object_add(jobj, "encryption", json_object_new_string(cipher));
257 json_object_object_add(jobj, "sector_size", json_object_new_int(sector_size));
259 LUKS2_segment_set_flag(jobj, "in-reencryption");
264 uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, int segment, unsigned blockwise)
266 return json_segment_get_offset(LUKS2_get_segment_jobj(hdr, segment), blockwise);
269 int json_segments_segment_in_reencrypt(json_object *jobj_segments)
271 json_object *jobj_flags;
273 json_object_object_foreach(jobj_segments, slot, val) {
274 if (!json_object_object_get_ex(val, "flags", &jobj_flags) ||
275 !LUKS2_array_jobj(jobj_flags, "in-reencryption"))
284 uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise)
286 return json_segment_get_size(LUKS2_get_segment_jobj(hdr, segment), blockwise);
289 int LUKS2_segment_is_type(struct luks2_hdr *hdr, int segment, const char *type)
291 return !strcmp(json_segment_type(LUKS2_get_segment_jobj(hdr, segment)) ?: "", type);
294 int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, const char *type)
296 json_object *jobj_segments;
302 if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
305 json_object_object_foreach(jobj_segments, slot, val) {
306 if (json_segment_is_backup(val))
308 if (strcmp(type, json_segment_type(val) ?: ""))
311 if (atoi(slot) > last_found)
312 last_found = atoi(slot);
318 int LUKS2_segment_by_type(struct luks2_hdr *hdr, const char *type)
320 json_object *jobj_segments;
321 int first_found = -1;
326 if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
329 json_object_object_foreach(jobj_segments, slot, val) {
330 if (json_segment_is_backup(val))
332 if (strcmp(type, json_segment_type(val) ?: ""))
336 first_found = atoi(slot);
337 else if (atoi(slot) < first_found)
338 first_found = atoi(slot);
344 int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr)
346 json_object *jobj_segments;
347 int id, last_id = -1;
349 if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments))
352 json_object_object_foreach(jobj_segments, slot, val) {
362 int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag)
364 json_object *jobj_flags;
366 if (!jobj_segment || !flag)
369 if (!json_object_object_get_ex(jobj_segment, "flags", &jobj_flags)) {
370 jobj_flags = json_object_new_array();
373 json_object_object_add(jobj_segment, "flags", jobj_flags);
376 if (LUKS2_array_jobj(jobj_flags, flag))
379 json_object_array_add(jobj_flags, json_object_new_string(flag));
384 int LUKS2_segments_set(struct crypt_device *cd, struct luks2_hdr *hdr,
385 json_object *jobj_segments, int commit)
387 json_object_object_add(hdr->jobj, "segments", jobj_segments);
389 return commit ? LUKS2_hdr_write(cd, hdr) : 0;
392 int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag)
395 json_object *jobj_segments = LUKS2_get_segments_jobj(hdr);
398 _get_segment_or_id_by_flag(jobj_segments, flag, 1, &ret);
403 json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag)
405 json_object *jobj_segment = NULL,
406 *jobj_segments = LUKS2_get_segments_jobj(hdr);
409 _get_segment_or_id_by_flag(jobj_segments, flag, 0, &jobj_segment);