/src/cryptsetup/lib/luks2/luks2_segment.c
Line | Count | Source (jump to first uncovered line) |
1 | | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | | /* |
3 | | * LUKS - Linux Unified Key Setup v2, internal segment handling |
4 | | * |
5 | | * Copyright (C) 2018-2025 Red Hat, Inc. All rights reserved. |
6 | | * Copyright (C) 2018-2025 Ondrej Kozina |
7 | | */ |
8 | | |
9 | | #include "luks2_internal.h" |
10 | | |
11 | | /* use only on already validated 'segments' object */ |
12 | | uint64_t json_segments_get_minimal_offset(json_object *jobj_segments, unsigned blockwise) |
13 | 6.66k | { |
14 | 6.66k | uint64_t tmp, min = blockwise ? UINT64_MAX >> SECTOR_SHIFT : UINT64_MAX; |
15 | | |
16 | 6.66k | if (!jobj_segments) |
17 | 0 | return 0; |
18 | | |
19 | 6.76k | json_object_object_foreach(jobj_segments, key, val) { |
20 | 6.76k | UNUSED(key); |
21 | | |
22 | 6.76k | if (json_segment_is_backup(val)) |
23 | 61 | continue; |
24 | | |
25 | 6.70k | tmp = json_segment_get_offset(val, blockwise); |
26 | | |
27 | 6.70k | if (!tmp) |
28 | 2.93k | return tmp; |
29 | | |
30 | 3.77k | if (tmp < min) |
31 | 3.75k | min = tmp; |
32 | 3.77k | } |
33 | | |
34 | 3.73k | return min; |
35 | 6.66k | } |
36 | | |
37 | | uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise) |
38 | 13.6k | { |
39 | 13.6k | json_object *jobj; |
40 | | |
41 | 13.6k | if (!jobj_segment || |
42 | 13.6k | !json_object_object_get_ex(jobj_segment, "offset", &jobj)) |
43 | 0 | return 0; |
44 | | |
45 | 13.6k | return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj); |
46 | 13.6k | } |
47 | | |
48 | | const char *json_segment_type(json_object *jobj_segment) |
49 | 12 | { |
50 | 12 | json_object *jobj; |
51 | | |
52 | 12 | if (!jobj_segment || |
53 | 12 | !json_object_object_get_ex(jobj_segment, "type", &jobj)) |
54 | 0 | return NULL; |
55 | | |
56 | 12 | return json_object_get_string(jobj); |
57 | 12 | } |
58 | | |
59 | | uint64_t json_segment_get_iv_offset(json_object *jobj_segment) |
60 | 0 | { |
61 | 0 | json_object *jobj; |
62 | |
|
63 | 0 | if (!jobj_segment || |
64 | 0 | !json_object_object_get_ex(jobj_segment, "iv_tweak", &jobj)) |
65 | 0 | return 0; |
66 | | |
67 | 0 | return crypt_jobj_get_uint64(jobj); |
68 | 0 | } |
69 | | |
70 | | uint64_t json_segment_get_size(json_object *jobj_segment, unsigned blockwise) |
71 | 6.89k | { |
72 | 6.89k | json_object *jobj; |
73 | | |
74 | 6.89k | if (!jobj_segment || |
75 | 6.89k | !json_object_object_get_ex(jobj_segment, "size", &jobj)) |
76 | 0 | return 0; |
77 | | |
78 | 6.89k | return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj); |
79 | 6.89k | } |
80 | | |
81 | | static uint64_t json_segment_get_opal_size(json_object *jobj_segment, unsigned blockwise) |
82 | 0 | { |
83 | 0 | json_object *jobj; |
84 | |
|
85 | 0 | if (!jobj_segment || |
86 | 0 | !json_object_object_get_ex(jobj_segment, "opal_segment_size", &jobj)) |
87 | 0 | return 0; |
88 | | |
89 | 0 | return blockwise ? crypt_jobj_get_uint64(jobj) >> SECTOR_SHIFT : crypt_jobj_get_uint64(jobj); |
90 | 0 | } |
91 | | |
92 | | static bool json_segment_set_size(json_object *jobj_segment, const uint64_t *size_bytes) |
93 | 0 | { |
94 | 0 | json_object *jobj; |
95 | |
|
96 | 0 | if (!jobj_segment) |
97 | 0 | return false; |
98 | | |
99 | 0 | jobj = size_bytes ? crypt_jobj_new_uint64(*size_bytes) : json_object_new_string("dynamic"); |
100 | 0 | if (!jobj) |
101 | 0 | return false; |
102 | | |
103 | 0 | json_object_object_add(jobj_segment, "size", jobj); |
104 | |
|
105 | 0 | return true; |
106 | 0 | } |
107 | | |
108 | | const char *json_segment_get_cipher(json_object *jobj_segment) |
109 | 0 | { |
110 | 0 | json_object *jobj; |
111 | | |
112 | | /* FIXME: Pseudo "null" cipher should be handled elsewhere */ |
113 | 0 | if (!jobj_segment || |
114 | 0 | !json_object_object_get_ex(jobj_segment, "encryption", &jobj)) |
115 | 0 | return "null"; |
116 | | |
117 | 0 | return json_object_get_string(jobj); |
118 | 0 | } |
119 | | |
120 | | uint32_t json_segment_get_sector_size(json_object *jobj_segment) |
121 | 2.29k | { |
122 | 2.29k | json_object *jobj; |
123 | 2.29k | int i; |
124 | | |
125 | 2.29k | if (!jobj_segment || |
126 | 2.29k | !json_object_object_get_ex(jobj_segment, "sector_size", &jobj)) |
127 | 1.98k | return SECTOR_SIZE; |
128 | | |
129 | 310 | i = json_object_get_int(jobj); |
130 | 310 | return i < 0 ? SECTOR_SIZE : i; |
131 | 2.29k | } |
132 | | |
133 | | int json_segment_get_opal_segment_id(json_object *jobj_segment, uint32_t *ret_opal_segment_id) |
134 | 0 | { |
135 | 0 | json_object *jobj_segment_id; |
136 | |
|
137 | 0 | assert(ret_opal_segment_id); |
138 | | |
139 | 0 | if (!json_object_object_get_ex(jobj_segment, "opal_segment_number", &jobj_segment_id)) |
140 | 0 | return -EINVAL; |
141 | | |
142 | 0 | *ret_opal_segment_id = json_object_get_int(jobj_segment_id); |
143 | |
|
144 | 0 | return 0; |
145 | 0 | } |
146 | | |
147 | | int json_segment_get_opal_key_size(json_object *jobj_segment, size_t *ret_key_size) |
148 | 0 | { |
149 | 0 | json_object *jobj_key_size; |
150 | |
|
151 | 0 | assert(ret_key_size); |
152 | | |
153 | 0 | if (!jobj_segment) |
154 | 0 | return -EINVAL; |
155 | | |
156 | 0 | if (!json_object_object_get_ex(jobj_segment, "opal_key_size", &jobj_key_size)) |
157 | 0 | return -EINVAL; |
158 | | |
159 | 0 | *ret_key_size = json_object_get_int(jobj_key_size); |
160 | |
|
161 | 0 | return 0; |
162 | 0 | } |
163 | | |
164 | | static json_object *json_segment_get_flags(json_object *jobj_segment) |
165 | 16.6k | { |
166 | 16.6k | json_object *jobj; |
167 | | |
168 | 16.6k | if (!jobj_segment || !(json_object_object_get_ex(jobj_segment, "flags", &jobj))) |
169 | 1.90k | return NULL; |
170 | 14.7k | return jobj; |
171 | 16.6k | } |
172 | | |
173 | | bool json_segment_contains_flag(json_object *jobj_segment, const char *flag_str, size_t len) |
174 | 16.6k | { |
175 | 16.6k | int r, i; |
176 | 16.6k | json_object *jobj, *jobj_flags = json_segment_get_flags(jobj_segment); |
177 | | |
178 | 16.6k | if (!jobj_flags) |
179 | 1.90k | return false; |
180 | | |
181 | 44.4k | for (i = 0; i < (int)json_object_array_length(jobj_flags); i++) { |
182 | 30.2k | jobj = json_object_array_get_idx(jobj_flags, i); |
183 | 30.2k | if (len) |
184 | 29.3k | r = strncmp(json_object_get_string(jobj), flag_str, len); |
185 | 858 | else |
186 | 858 | r = strcmp(json_object_get_string(jobj), flag_str); |
187 | 30.2k | if (!r) |
188 | 539 | return true; |
189 | 30.2k | } |
190 | | |
191 | 14.2k | return false; |
192 | 14.7k | } |
193 | | |
194 | | bool json_segment_is_backup(json_object *jobj_segment) |
195 | 16.6k | { |
196 | 16.6k | return json_segment_contains_flag(jobj_segment, "backup-", 7); |
197 | 16.6k | } |
198 | | |
199 | | json_object *json_segments_get_segment(json_object *jobj_segments, int segment) |
200 | 9.37k | { |
201 | 9.37k | json_object *jobj; |
202 | 9.37k | char segment_name[16]; |
203 | | |
204 | 9.37k | if (snprintf(segment_name, sizeof(segment_name), "%u", segment) < 1) |
205 | 0 | return NULL; |
206 | | |
207 | 9.37k | if (!json_object_object_get_ex(jobj_segments, segment_name, &jobj)) |
208 | 30 | return NULL; |
209 | | |
210 | 9.34k | return jobj; |
211 | 9.37k | } |
212 | | |
213 | | unsigned json_segments_count(json_object *jobj_segments) |
214 | 2.29k | { |
215 | 2.29k | unsigned count = 0; |
216 | | |
217 | 2.29k | if (!jobj_segments) |
218 | 0 | return 0; |
219 | | |
220 | 2.32k | json_object_object_foreach(jobj_segments, slot, val) { |
221 | 2.32k | UNUSED(slot); |
222 | 2.32k | if (!json_segment_is_backup(val)) |
223 | 2.30k | count++; |
224 | 2.32k | } |
225 | | |
226 | 2.29k | return count; |
227 | 2.29k | } |
228 | | |
229 | | void json_segment_remove_flag(json_object *jobj_segment, const char *flag) |
230 | 0 | { |
231 | 0 | json_object *jobj_flags, *jobj_flags_new; |
232 | |
|
233 | 0 | if (!jobj_segment) |
234 | 0 | return; |
235 | | |
236 | 0 | jobj_flags = json_segment_get_flags(jobj_segment); |
237 | 0 | if (!jobj_flags) |
238 | 0 | return; |
239 | | |
240 | 0 | jobj_flags_new = LUKS2_array_remove(jobj_flags, flag); |
241 | 0 | if (!jobj_flags_new) |
242 | 0 | return; |
243 | | |
244 | 0 | if (json_object_array_length(jobj_flags_new) <= 0) { |
245 | 0 | json_object_put(jobj_flags_new); |
246 | 0 | json_object_object_del(jobj_segment, "flags"); |
247 | 0 | } else |
248 | 0 | json_object_object_add(jobj_segment, "flags", jobj_flags_new); |
249 | 0 | } |
250 | | |
251 | | static json_object *_segment_create_generic(const char *type, uint64_t offset, const uint64_t *length) |
252 | 0 | { |
253 | 0 | json_object *jobj = json_object_new_object(); |
254 | 0 | if (!jobj) |
255 | 0 | return NULL; |
256 | | |
257 | 0 | json_object_object_add(jobj, "type", json_object_new_string(type)); |
258 | 0 | json_object_object_add(jobj, "offset", crypt_jobj_new_uint64(offset)); |
259 | 0 | json_object_object_add(jobj, "size", length ? crypt_jobj_new_uint64(*length) : json_object_new_string("dynamic")); |
260 | |
|
261 | 0 | return jobj; |
262 | 0 | } |
263 | | |
264 | | json_object *json_segment_create_linear(uint64_t offset, const uint64_t *length, unsigned reencryption) |
265 | 0 | { |
266 | 0 | json_object *jobj = _segment_create_generic("linear", offset, length); |
267 | 0 | if (reencryption) |
268 | 0 | LUKS2_segment_set_flag(jobj, "in-reencryption"); |
269 | 0 | return jobj; |
270 | 0 | } |
271 | | |
272 | | static bool json_add_crypt_fields(json_object *jobj_segment, uint64_t iv_offset, |
273 | | const char *cipher, const char *integrity, uint32_t integrity_key_size, |
274 | | uint32_t sector_size, unsigned reencryption) |
275 | 0 | { |
276 | 0 | json_object *jobj_integrity; |
277 | |
|
278 | 0 | assert(cipher); |
279 | | |
280 | 0 | json_object_object_add(jobj_segment, "iv_tweak", crypt_jobj_new_uint64(iv_offset)); |
281 | 0 | json_object_object_add(jobj_segment, "encryption", json_object_new_string(cipher)); |
282 | 0 | json_object_object_add(jobj_segment, "sector_size", json_object_new_int(sector_size)); |
283 | |
|
284 | 0 | if (integrity) { |
285 | 0 | jobj_integrity = json_object_new_object(); |
286 | 0 | if (!jobj_integrity) |
287 | 0 | return false; |
288 | | |
289 | 0 | json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity)); |
290 | 0 | json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none")); |
291 | 0 | json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none")); |
292 | 0 | if (integrity_key_size) |
293 | 0 | json_object_object_add(jobj_integrity, "key_size", json_object_new_int(integrity_key_size)); |
294 | 0 | json_object_object_add(jobj_segment, "integrity", jobj_integrity); |
295 | 0 | } |
296 | | |
297 | 0 | if (reencryption) |
298 | 0 | LUKS2_segment_set_flag(jobj_segment, "in-reencryption"); |
299 | |
|
300 | 0 | return true; |
301 | 0 | } |
302 | | |
303 | | json_object *json_segment_create_crypt(uint64_t offset, |
304 | | uint64_t iv_offset, const uint64_t *length, |
305 | | const char *cipher, const char *integrity, uint32_t integrity_key_size, |
306 | | uint32_t sector_size, unsigned reencryption) |
307 | 0 | { |
308 | 0 | json_object *jobj = _segment_create_generic("crypt", offset, length); |
309 | |
|
310 | 0 | if (!jobj) |
311 | 0 | return NULL; |
312 | | |
313 | 0 | if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, integrity_key_size, sector_size, reencryption)) |
314 | 0 | return jobj; |
315 | | |
316 | 0 | json_object_put(jobj); |
317 | 0 | return NULL; |
318 | 0 | } |
319 | | |
320 | | static void json_add_opal_fields(json_object *jobj_segment, const uint64_t *length, |
321 | | uint32_t segment_number, uint32_t key_size) |
322 | 0 | { |
323 | 0 | assert(jobj_segment); |
324 | 0 | assert(length); |
325 | | |
326 | 0 | json_object_object_add(jobj_segment, "opal_segment_number", json_object_new_int(segment_number)); |
327 | 0 | json_object_object_add(jobj_segment, "opal_key_size", json_object_new_int(key_size)); |
328 | 0 | json_object_object_add(jobj_segment, "opal_segment_size", crypt_jobj_new_uint64(*length)); |
329 | 0 | } |
330 | | |
331 | | json_object *json_segment_create_opal(uint64_t offset, const uint64_t *length, |
332 | | uint32_t segment_number, uint32_t key_size) |
333 | 0 | { |
334 | 0 | json_object *jobj = _segment_create_generic("hw-opal", offset, length); |
335 | 0 | if (!jobj) |
336 | 0 | return NULL; |
337 | | |
338 | 0 | json_add_opal_fields(jobj, length, segment_number, key_size); |
339 | |
|
340 | 0 | return jobj; |
341 | 0 | } |
342 | | |
343 | | json_object *json_segment_create_opal_crypt(uint64_t offset, const uint64_t *length, |
344 | | uint32_t segment_number, uint32_t key_size, |
345 | | uint64_t iv_offset, const char *cipher, |
346 | | const char *integrity, uint32_t sector_size, |
347 | | unsigned reencryption) |
348 | 0 | { |
349 | 0 | json_object *jobj = _segment_create_generic("hw-opal-crypt", offset, length); |
350 | 0 | if (!jobj) |
351 | 0 | return NULL; |
352 | | |
353 | 0 | json_add_opal_fields(jobj, length, segment_number, key_size); |
354 | |
|
355 | 0 | if (json_add_crypt_fields(jobj, iv_offset, cipher, integrity, 0, sector_size, reencryption)) |
356 | 0 | return jobj; |
357 | | |
358 | 0 | json_object_put(jobj); |
359 | 0 | return NULL; |
360 | 0 | } |
361 | | |
362 | | uint64_t LUKS2_segment_offset(struct luks2_hdr *hdr, int segment, unsigned blockwise) |
363 | 0 | { |
364 | 0 | return json_segment_get_offset(LUKS2_get_segment_jobj(hdr, segment), blockwise); |
365 | 0 | } |
366 | | |
367 | | int json_segments_segment_in_reencrypt(json_object *jobj_segments) |
368 | 0 | { |
369 | 0 | json_object *jobj_flags; |
370 | |
|
371 | 0 | json_object_object_foreach(jobj_segments, slot, val) { |
372 | 0 | if (!json_object_object_get_ex(val, "flags", &jobj_flags) || |
373 | 0 | !LUKS2_array_jobj(jobj_flags, "in-reencryption")) |
374 | 0 | continue; |
375 | | |
376 | 0 | return atoi(slot); |
377 | 0 | } |
378 | | |
379 | 0 | return -1; |
380 | 0 | } |
381 | | |
382 | | uint64_t LUKS2_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise) |
383 | 0 | { |
384 | 0 | return json_segment_get_size(LUKS2_get_segment_jobj(hdr, segment), blockwise); |
385 | 0 | } |
386 | | |
387 | | uint64_t LUKS2_opal_segment_size(struct luks2_hdr *hdr, int segment, unsigned blockwise) |
388 | 0 | { |
389 | 0 | return json_segment_get_opal_size(LUKS2_get_segment_jobj(hdr, segment), blockwise); |
390 | 0 | } |
391 | | |
392 | | bool LUKS2_segment_set_size(struct luks2_hdr *hdr, int segment, const uint64_t *segment_size_bytes) |
393 | 0 | { |
394 | 0 | return json_segment_set_size(LUKS2_get_segment_jobj(hdr, segment), segment_size_bytes); |
395 | 0 | } |
396 | | |
397 | | int LUKS2_segment_is_type(struct luks2_hdr *hdr, int segment, const char *type) |
398 | 0 | { |
399 | 0 | return !strcmp(json_segment_type(LUKS2_get_segment_jobj(hdr, segment)) ?: "", type); |
400 | 0 | } |
401 | | |
402 | | static bool json_segment_is_hw_opal_only(json_object *jobj_segment) |
403 | 0 | { |
404 | 0 | const char *type = json_segment_type(jobj_segment); |
405 | |
|
406 | 0 | if (!type) |
407 | 0 | return false; |
408 | | |
409 | 0 | return !strcmp(type, "hw-opal"); |
410 | 0 | } |
411 | | |
412 | | static bool json_segment_is_hw_opal_crypt(json_object *jobj_segment) |
413 | 0 | { |
414 | 0 | const char *type = json_segment_type(jobj_segment); |
415 | |
|
416 | 0 | if (!type) |
417 | 0 | return false; |
418 | | |
419 | 0 | return !strcmp(type, "hw-opal-crypt"); |
420 | 0 | } |
421 | | |
422 | | static bool json_segment_is_hw_opal(json_object *jobj_segment) |
423 | 0 | { |
424 | 0 | return json_segment_is_hw_opal_crypt(jobj_segment) || |
425 | 0 | json_segment_is_hw_opal_only(jobj_segment); |
426 | 0 | } |
427 | | |
428 | | bool LUKS2_segment_is_hw_opal_only(struct luks2_hdr *hdr, int segment) |
429 | 0 | { |
430 | 0 | return json_segment_is_hw_opal_only(LUKS2_get_segment_jobj(hdr, segment)); |
431 | 0 | } |
432 | | |
433 | | bool LUKS2_segment_is_hw_opal_crypt(struct luks2_hdr *hdr, int segment) |
434 | 0 | { |
435 | 0 | return json_segment_is_hw_opal_crypt(LUKS2_get_segment_jobj(hdr, segment)); |
436 | 0 | } |
437 | | |
438 | | bool LUKS2_segment_is_hw_opal(struct luks2_hdr *hdr, int segment) |
439 | 0 | { |
440 | 0 | return json_segment_is_hw_opal(LUKS2_get_segment_jobj(hdr, segment)); |
441 | 0 | } |
442 | | |
443 | | int LUKS2_get_opal_segment_number(struct luks2_hdr *hdr, int segment, uint32_t *ret_opal_segment_number) |
444 | 0 | { |
445 | 0 | json_object *jobj_segment = LUKS2_get_segment_jobj(hdr, segment); |
446 | |
|
447 | 0 | assert(ret_opal_segment_number); |
448 | | |
449 | 0 | if (!json_segment_is_hw_opal(jobj_segment)) |
450 | 0 | return -ENOENT; |
451 | | |
452 | 0 | return json_segment_get_opal_segment_id(jobj_segment, ret_opal_segment_number); |
453 | 0 | } |
454 | | |
455 | | int LUKS2_get_opal_key_size(struct luks2_hdr *hdr, int segment) |
456 | 0 | { |
457 | 0 | size_t key_size = 0; |
458 | 0 | json_object *jobj_segment = LUKS2_get_segment_jobj(hdr, segment); |
459 | |
|
460 | 0 | if (json_segment_get_opal_key_size(jobj_segment, &key_size) < 0) |
461 | 0 | return 0; |
462 | | |
463 | 0 | return key_size; |
464 | 0 | } |
465 | | |
466 | | int LUKS2_last_segment_by_type(struct luks2_hdr *hdr, const char *type) |
467 | 0 | { |
468 | 0 | json_object *jobj_segments; |
469 | 0 | int last_found = -1; |
470 | |
|
471 | 0 | if (!type) |
472 | 0 | return -1; |
473 | | |
474 | 0 | if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) |
475 | 0 | return -1; |
476 | | |
477 | 0 | json_object_object_foreach(jobj_segments, slot, val) { |
478 | 0 | if (json_segment_is_backup(val)) |
479 | 0 | continue; |
480 | 0 | if (strcmp(type, json_segment_type(val) ?: "")) |
481 | 0 | continue; |
482 | | |
483 | 0 | if (atoi(slot) > last_found) |
484 | 0 | last_found = atoi(slot); |
485 | 0 | } |
486 | |
|
487 | 0 | return last_found; |
488 | 0 | } |
489 | | |
490 | | int LUKS2_segment_by_type(struct luks2_hdr *hdr, const char *type) |
491 | 0 | { |
492 | 0 | json_object *jobj_segments; |
493 | 0 | int first_found = -1; |
494 | |
|
495 | 0 | if (!type) |
496 | 0 | return -EINVAL; |
497 | | |
498 | 0 | if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) |
499 | 0 | return -EINVAL; |
500 | | |
501 | 0 | json_object_object_foreach(jobj_segments, slot, val) { |
502 | 0 | if (json_segment_is_backup(val)) |
503 | 0 | continue; |
504 | 0 | if (strcmp(type, json_segment_type(val) ?: "")) |
505 | 0 | continue; |
506 | | |
507 | 0 | if (first_found < 0) |
508 | 0 | first_found = atoi(slot); |
509 | 0 | else if (atoi(slot) < first_found) |
510 | 0 | first_found = atoi(slot); |
511 | 0 | } |
512 | |
|
513 | 0 | return first_found; |
514 | 0 | } |
515 | | |
516 | | int LUKS2_segment_first_unused_id(struct luks2_hdr *hdr) |
517 | 0 | { |
518 | 0 | json_object *jobj_segments; |
519 | |
|
520 | 0 | if (!json_object_object_get_ex(hdr->jobj, "segments", &jobj_segments)) |
521 | 0 | return -EINVAL; |
522 | | |
523 | 0 | return json_object_object_length(jobj_segments); |
524 | 0 | } |
525 | | |
526 | | int LUKS2_segment_set_flag(json_object *jobj_segment, const char *flag) |
527 | 0 | { |
528 | 0 | json_object *jobj_flags; |
529 | |
|
530 | 0 | if (!jobj_segment || !flag) |
531 | 0 | return -EINVAL; |
532 | | |
533 | 0 | if (!json_object_object_get_ex(jobj_segment, "flags", &jobj_flags)) { |
534 | 0 | jobj_flags = json_object_new_array(); |
535 | 0 | if (!jobj_flags) |
536 | 0 | return -ENOMEM; |
537 | 0 | json_object_object_add(jobj_segment, "flags", jobj_flags); |
538 | 0 | } |
539 | | |
540 | 0 | if (LUKS2_array_jobj(jobj_flags, flag)) |
541 | 0 | return 0; |
542 | | |
543 | 0 | json_object_array_add(jobj_flags, json_object_new_string(flag)); |
544 | |
|
545 | 0 | return 0; |
546 | 0 | } |
547 | | |
548 | | int LUKS2_segments_set(struct crypt_device *cd, struct luks2_hdr *hdr, |
549 | | json_object *jobj_segments, int commit) |
550 | 0 | { |
551 | 0 | json_object_object_add(hdr->jobj, "segments", jobj_segments); |
552 | |
|
553 | 0 | return commit ? LUKS2_hdr_write(cd, hdr) : 0; |
554 | 0 | } |
555 | | |
556 | | int LUKS2_get_segment_id_by_flag(struct luks2_hdr *hdr, const char *flag) |
557 | 2.29k | { |
558 | 2.29k | json_object *jobj_flags, *jobj_segments = LUKS2_get_segments_jobj(hdr); |
559 | | |
560 | 2.29k | if (!flag || !jobj_segments) |
561 | 0 | return -ENOENT; |
562 | | |
563 | 2.33k | json_object_object_foreach(jobj_segments, key, value) { |
564 | 2.33k | if (!json_object_object_get_ex(value, "flags", &jobj_flags)) |
565 | 334 | continue; |
566 | 1.99k | if (LUKS2_array_jobj(jobj_flags, flag)) |
567 | 1 | return atoi(key); |
568 | 1.99k | } |
569 | | |
570 | 2.29k | return -ENOENT; |
571 | 2.29k | } |
572 | | |
573 | | json_object *LUKS2_get_segment_by_flag(struct luks2_hdr *hdr, const char *flag) |
574 | 0 | { |
575 | 0 | json_object *jobj_flags, *jobj_segments = LUKS2_get_segments_jobj(hdr); |
576 | |
|
577 | 0 | if (!flag || !jobj_segments) |
578 | 0 | return NULL; |
579 | | |
580 | 0 | json_object_object_foreach(jobj_segments, key, value) { |
581 | 0 | UNUSED(key); |
582 | 0 | if (!json_object_object_get_ex(value, "flags", &jobj_flags)) |
583 | 0 | continue; |
584 | 0 | if (LUKS2_array_jobj(jobj_flags, flag)) |
585 | 0 | return value; |
586 | 0 | } |
587 | | |
588 | 0 | return NULL; |
589 | 0 | } |
590 | | |
591 | | /* compares key characteristics of both segments */ |
592 | | bool json_segment_cmp(json_object *jobj_segment_1, json_object *jobj_segment_2) |
593 | 6 | { |
594 | 6 | const char *type = json_segment_type(jobj_segment_1); |
595 | 6 | const char *type2 = json_segment_type(jobj_segment_2); |
596 | | |
597 | 6 | if (!type || !type2) |
598 | 0 | return false; |
599 | | |
600 | 6 | if (strcmp(type, type2)) |
601 | 6 | return false; |
602 | | |
603 | 0 | if (!strcmp(type, "crypt")) |
604 | 0 | return (json_segment_get_sector_size(jobj_segment_1) == json_segment_get_sector_size(jobj_segment_2) && |
605 | 0 | !strcmp(json_segment_get_cipher(jobj_segment_1), |
606 | 0 | json_segment_get_cipher(jobj_segment_2))); |
607 | | |
608 | 0 | return true; |
609 | 0 | } |
610 | | |
611 | | bool LUKS2_segments_dynamic_size(struct luks2_hdr *hdr) |
612 | 0 | { |
613 | 0 | json_object *jobj_segments, *jobj_size; |
614 | |
|
615 | 0 | assert(hdr); |
616 | | |
617 | 0 | jobj_segments = LUKS2_get_segments_jobj(hdr); |
618 | 0 | if (!jobj_segments) |
619 | 0 | return false; |
620 | | |
621 | 0 | json_object_object_foreach(jobj_segments, key, val) { |
622 | 0 | UNUSED(key); |
623 | |
|
624 | 0 | if (json_segment_is_backup(val)) |
625 | 0 | continue; |
626 | | |
627 | 0 | if (json_object_object_get_ex(val, "size", &jobj_size) && |
628 | 0 | !strcmp(json_object_get_string(jobj_size), "dynamic")) |
629 | 0 | return true; |
630 | 0 | } |
631 | | |
632 | 0 | return false; |
633 | 0 | } |