Coverage Report

Created: 2026-05-30 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptsetup/lib/luks2/luks2_json_format.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * LUKS - Linux Unified Key Setup v2, LUKS2 header format code
4
 *
5
 * Copyright (C) 2015-2025 Red Hat, Inc. All rights reserved.
6
 * Copyright (C) 2015-2025 Milan Broz
7
 */
8
9
#include "luks2_internal.h"
10
#include <uuid/uuid.h>
11
12
struct area {
13
  uint64_t offset;
14
  uint64_t length;
15
};
16
17
static size_t get_area_size(size_t keylength)
18
0
{
19
  /* for now it is AF_split_sectors */
20
0
  return size_round_up(keylength * 4000, 4096);
21
0
}
22
23
static size_t get_min_offset(struct luks2_hdr *hdr)
24
0
{
25
0
  return 2 * hdr->hdr_size;
26
0
}
27
28
static size_t get_max_offset(struct luks2_hdr *hdr)
29
0
{
30
0
  return LUKS2_hdr_and_areas_size(hdr);
31
0
}
32
33
int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
34
      uint64_t *area_offset, uint64_t *area_length)
35
0
{
36
0
  struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX+1] = {};
37
0
  int i, j, k, area_i;
38
0
  size_t valid_offset, offset, length;
39
40
  /* fill area offset + length table */
41
0
  for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
42
0
    if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
43
0
      continue;
44
0
    areas[i].length = 0;
45
0
    areas[i].offset = 0;
46
0
  }
47
48
  /* sort table */
49
0
  k = 0; /* index in sorted table */
50
0
  for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
51
0
    offset = get_max_offset(hdr) ?: UINT64_MAX;
52
0
    area_i = -1;
53
    /* search for the smallest offset in table */
54
0
    for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
55
0
      if (areas[j].offset && areas[j].offset <= offset) {
56
0
        area_i = j;
57
0
        offset = areas[j].offset;
58
0
      }
59
60
0
    if (area_i >= 0) {
61
0
      sorted_areas[k].length = areas[area_i].length;
62
0
      sorted_areas[k].offset = areas[area_i].offset;
63
0
      areas[area_i].length = 0;
64
0
      areas[area_i].offset = 0;
65
0
      k++;
66
0
    }
67
0
  }
68
69
0
  sorted_areas[LUKS2_KEYSLOTS_MAX].offset = get_max_offset(hdr);
70
0
  sorted_areas[LUKS2_KEYSLOTS_MAX].length = 1;
71
72
  /* search for the gap we can use */
73
0
  length = valid_offset = 0;
74
0
  offset = get_min_offset(hdr);
75
0
  for (i = 0; i < LUKS2_KEYSLOTS_MAX+1; i++) {
76
    /* skip empty */
77
0
    if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
78
0
      continue;
79
80
    /* found bigger gap than the last one */
81
0
    if ((offset < sorted_areas[i].offset) && (sorted_areas[i].offset - offset) > length) {
82
0
      length = sorted_areas[i].offset - offset;
83
0
      valid_offset = offset;
84
0
    }
85
86
    /* move beyond allocated area */
87
0
    offset = sorted_areas[i].offset + sorted_areas[i].length;
88
0
  }
89
90
  /* this search 'algorithm' does not work with unaligned areas */
91
0
  assert(length == size_round_up(length, 4096));
92
0
  assert(valid_offset == size_round_up(valid_offset, 4096));
93
94
0
  if (!length) {
95
0
    log_dbg(cd, "Not enough space in header keyslot area.");
96
0
    return -EINVAL;
97
0
  }
98
99
0
  log_dbg(cd, "Found largest free area %zu -> %zu", valid_offset, length + valid_offset);
100
101
0
  *area_offset = valid_offset;
102
0
  *area_length = length;
103
104
0
  return 0;
105
0
}
106
107
int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
108
      size_t keylength, uint64_t *area_offset, uint64_t *area_length)
109
0
{
110
0
  struct area areas[LUKS2_KEYSLOTS_MAX], sorted_areas[LUKS2_KEYSLOTS_MAX] = {};
111
0
  int i, j, k, area_i;
112
0
  size_t offset, length;
113
114
  /* fill area offset + length table */
115
0
  for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
116
0
    if (!LUKS2_keyslot_area(hdr, i, &areas[i].offset, &areas[i].length))
117
0
      continue;
118
0
    areas[i].length = 0;
119
0
    areas[i].offset = 0;
120
0
  }
121
122
  /* sort table */
123
0
  k = 0; /* index in sorted table */
124
0
  for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
125
0
    offset = get_max_offset(hdr) ?: UINT64_MAX;
126
0
    area_i = -1;
127
    /* search for the smallest offset in table */
128
0
    for (j = 0; j < LUKS2_KEYSLOTS_MAX; j++)
129
0
      if (areas[j].offset && areas[j].offset <= offset) {
130
0
        area_i = j;
131
0
        offset = areas[j].offset;
132
0
      }
133
134
0
    if (area_i >= 0) {
135
0
      sorted_areas[k].length = areas[area_i].length;
136
0
      sorted_areas[k].offset = areas[area_i].offset;
137
0
      areas[area_i].length = 0;
138
0
      areas[area_i].offset = 0;
139
0
      k++;
140
0
    }
141
0
  }
142
143
  /* search for the gap we can use */
144
0
  offset = get_min_offset(hdr);
145
0
  length = get_area_size(keylength);
146
0
  for (i = 0; i < LUKS2_KEYSLOTS_MAX; i++) {
147
    /* skip empty */
148
0
    if (sorted_areas[i].offset == 0 || sorted_areas[i].length == 0)
149
0
      continue;
150
151
    /* enough space before the used area */
152
0
    if ((offset < sorted_areas[i].offset) && ((offset + length) <= sorted_areas[i].offset))
153
0
      break;
154
155
    /* both offset and length are already aligned to 4096 bytes */
156
0
    offset = sorted_areas[i].offset + sorted_areas[i].length;
157
0
  }
158
159
0
  if ((offset + length) > get_max_offset(hdr)) {
160
0
    log_dbg(cd, "Not enough space in header keyslot area.");
161
0
    return -EINVAL;
162
0
  }
163
164
0
  log_dbg(cd, "Found area %zu -> %zu", offset, length + offset);
165
166
0
  if (area_offset)
167
0
    *area_offset = offset;
168
0
  if (area_length)
169
0
    *area_length = length;
170
171
0
  return 0;
172
0
}
173
174
int LUKS2_check_metadata_area_size(uint64_t metadata_size)
175
5.29k
{
176
  /* see LUKS2_HDR2_OFFSETS */
177
5.29k
  return (metadata_size != 0x004000 &&
178
5.29k
    metadata_size != 0x008000 && metadata_size != 0x010000 &&
179
30
    metadata_size != 0x020000 && metadata_size != 0x040000 &&
180
30
    metadata_size != 0x080000 && metadata_size != 0x100000 &&
181
30
    metadata_size != 0x200000 && metadata_size != 0x400000);
182
5.29k
}
183
184
int LUKS2_check_keyslots_area_size(uint64_t keyslots_size)
185
5.26k
{
186
5.26k
  return (MISALIGNED_4K(keyslots_size) ||
187
5.26k
    keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE);
188
5.26k
}
189
190
int LUKS2_generate_hdr(
191
  struct crypt_device *cd,
192
  struct luks2_hdr *hdr,
193
  const struct volume_key *vk,
194
  const char *cipher_spec,
195
  const char *integrity,
196
  uint32_t integrity_key_size, /* in bytes, only if separate (HMAC) */
197
  const char *uuid,
198
  unsigned int sector_size,  /* in bytes */
199
  uint64_t data_offset,      /* in bytes */
200
  uint64_t metadata_size_bytes,
201
  uint64_t keyslots_size_bytes,
202
  uint64_t device_size_bytes,
203
  uint32_t opal_segment_number,
204
  uint32_t opal_key_size)
205
0
{
206
0
  json_object *jobj_segment, *jobj_keyslots, *jobj_segments, *jobj_config;
207
0
  uuid_t partitionUuid;
208
0
  int r, digest;
209
210
0
  assert(cipher_spec || (opal_key_size > 0 && device_size_bytes));
211
212
0
  hdr->hdr_size = metadata_size_bytes;
213
214
0
  log_dbg(cd, "Formatting LUKS2 with JSON metadata area %" PRIu64
215
0
    " bytes and keyslots area %" PRIu64 " bytes.",
216
0
    metadata_size_bytes - LUKS2_HDR_BIN_LEN, keyslots_size_bytes);
217
218
0
  if (keyslots_size_bytes < (LUKS2_HDR_OFFSET_MAX - 2*LUKS2_HDR_16K_LEN))
219
0
    log_std(cd, _("WARNING: keyslots area (%" PRIu64 " bytes) is very small,"
220
0
      " available LUKS2 keyslot count is very limited.\n"),
221
0
      keyslots_size_bytes);
222
223
0
  hdr->seqid = 1;
224
0
  hdr->version = 2;
225
0
  memset(hdr->label, 0, LUKS2_LABEL_L);
226
0
  strcpy(hdr->checksum_alg, "sha256");
227
0
  crypt_random_get(cd, (char*)hdr->salt1, LUKS2_SALT_L, CRYPT_RND_SALT);
228
0
  crypt_random_get(cd, (char*)hdr->salt2, LUKS2_SALT_L, CRYPT_RND_SALT);
229
230
0
  if (uuid && uuid_parse(uuid, partitionUuid) == -1) {
231
0
    log_err(cd, _("Wrong LUKS UUID format provided."));
232
0
    return -EINVAL;
233
0
  }
234
0
  if (!uuid)
235
0
    uuid_generate(partitionUuid);
236
237
0
  uuid_unparse(partitionUuid, hdr->uuid);
238
239
0
  hdr->jobj = json_object_new_object();
240
0
  if (!hdr->jobj) {
241
0
    r = -ENOMEM;
242
0
    goto err;
243
0
  }
244
245
0
  jobj_keyslots = json_object_new_object();
246
0
  if (!jobj_keyslots) {
247
0
    r = -ENOMEM;
248
0
    goto err;
249
0
  }
250
251
0
  json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots);
252
0
  json_object_object_add(hdr->jobj, "tokens", json_object_new_object());
253
0
  jobj_segments = json_object_new_object();
254
0
  if (!jobj_segments) {
255
0
    r = -ENOMEM;
256
0
    goto err;
257
0
  }
258
259
0
  json_object_object_add(hdr->jobj, "segments", jobj_segments);
260
0
  json_object_object_add(hdr->jobj, "digests", json_object_new_object());
261
0
  jobj_config = json_object_new_object();
262
0
  if (!jobj_config) {
263
0
    r = -ENOMEM;
264
0
    goto err;
265
0
  }
266
267
0
  json_object_object_add(hdr->jobj, "config", jobj_config);
268
269
0
  digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk);
270
0
  if (digest < 0) {
271
0
    r = -EINVAL;
272
0
    goto err;
273
0
  }
274
275
0
  if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0) {
276
0
    r = -EINVAL;
277
0
    goto err;
278
0
  }
279
280
0
  if (!opal_key_size)
281
0
    jobj_segment = json_segment_create_crypt(data_offset, 0,
282
0
               NULL, cipher_spec,
283
0
               integrity, integrity_key_size,
284
0
               sector_size, 0);
285
0
  else if (opal_key_size && cipher_spec)
286
0
    jobj_segment = json_segment_create_opal_crypt(data_offset, &device_size_bytes,
287
0
                    opal_segment_number, opal_key_size, 0,
288
0
                    cipher_spec, integrity,
289
0
                    sector_size, 0);
290
0
  else
291
0
    jobj_segment = json_segment_create_opal(data_offset, &device_size_bytes,
292
0
              opal_segment_number, opal_key_size);
293
294
0
  if (!jobj_segment) {
295
0
    r = -EINVAL;
296
0
    goto err;
297
0
  }
298
299
0
  if (json_object_object_add_by_uint(jobj_segments, 0, jobj_segment)) {
300
0
    json_object_put(jobj_segment);
301
0
    r = -ENOMEM;
302
0
    goto err;
303
0
  }
304
305
0
  json_object_object_add(jobj_config, "json_size", crypt_jobj_new_uint64(metadata_size_bytes - LUKS2_HDR_BIN_LEN));
306
0
  json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size_bytes));
307
308
0
  JSON_DBG(cd, hdr->jobj, "Header JSON:");
309
0
  return 0;
310
0
err:
311
0
  json_object_put(hdr->jobj);
312
0
  hdr->jobj = NULL;
313
0
  return r;
314
0
}
315
316
int LUKS2_wipe_header_areas(struct crypt_device *cd,
317
  struct luks2_hdr *hdr)
318
0
{
319
0
  int r;
320
0
  uint64_t device_size_bytes, length, offset;
321
0
  size_t wipe_block = 1024 * 1024;
322
323
0
  if (!hdr || LUKS2_hdr_validate(cd, hdr->jobj, hdr->hdr_size - LUKS2_HDR_BIN_LEN))
324
0
    return -EINVAL;
325
326
0
  r = device_size(crypt_metadata_device(cd), &device_size_bytes);
327
0
  if (r < 0)
328
0
    return -EINVAL;
329
330
  /* Wipe up to maximal allowed metadata size, but do not write beyond data offset. */
331
0
  length = LUKS2_get_data_offset(hdr) * SECTOR_SIZE;
332
0
  if (!length || length > LUKS2_HDR_MAX_MDA_SIZE)
333
0
    length = LUKS2_HDR_MAX_MDA_SIZE;
334
335
  /* Also do not extend the device size yet (file backends) */
336
0
  if (length > device_size_bytes)
337
0
    length = device_size_bytes;
338
339
0
  log_dbg(cd, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
340
0
    0ULL, length);
341
342
0
  r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0,
343
0
            length, wipe_block, NULL, NULL);
344
0
  if (r < 0)
345
0
    return r;
346
347
  /* Allocate at least actual LUKS2 metadata size */
348
0
  r = device_check_size(cd, crypt_metadata_device(cd),
349
0
            LUKS2_hdr_and_areas_size(hdr), 1);
350
0
  if (r)
351
0
    return r;
352
353
  /* Wipe keyslot area */
354
0
  offset = get_min_offset(hdr);
355
0
  length = LUKS2_keyslots_size(hdr);
356
357
  /*
358
   * Skip keyslots area wipe in case it is not defined.
359
   * Otherwise we would wipe whole data device (length == 0)
360
   * starting at offset get_min_offset(hdr).
361
   */
362
0
  if (!length)
363
0
    return 0;
364
365
0
  log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
366
0
    offset, length + offset);
367
368
0
  return crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_RANDOM,
369
0
         offset, length, wipe_block, NULL, NULL);
370
0
}
371
372
int LUKS2_set_keyslots_size(struct luks2_hdr *hdr, uint64_t data_offset)
373
0
{
374
0
  json_object *jobj_config;
375
0
  uint64_t keyslots_size;
376
377
0
  if (data_offset < get_min_offset(hdr))
378
0
    return 1;
379
380
0
  keyslots_size = data_offset - get_min_offset(hdr);
381
382
  /* keep keyslots_size reasonable for custom data alignments */
383
0
  if (keyslots_size > LUKS2_MAX_KEYSLOTS_SIZE)
384
0
    keyslots_size = LUKS2_MAX_KEYSLOTS_SIZE;
385
386
  /* keyslots size has to be 4 KiB aligned */
387
0
  keyslots_size -= (keyslots_size % 4096);
388
389
0
  if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
390
0
    return 1;
391
392
0
  json_object_object_add(jobj_config, "keyslots_size", crypt_jobj_new_uint64(keyslots_size));
393
0
  return 0;
394
0
}
395
396
int LUKS2_hdr_get_storage_params(struct crypt_device *cd,
397
          uint64_t alignment_offset_bytes,
398
          uint64_t alignment_bytes,
399
          uint64_t *ret_metadata_size_bytes,
400
          uint64_t *ret_keyslots_size_bytes,
401
          uint64_t *ret_data_offset_bytes)
402
0
{
403
0
  uint64_t data_offset_bytes, keyslots_size_bytes, metadata_size_bytes, mdev_size_bytes;
404
405
0
  assert(cd);
406
0
  assert(ret_metadata_size_bytes);
407
0
  assert(ret_keyslots_size_bytes);
408
0
  assert(ret_data_offset_bytes);
409
410
0
  metadata_size_bytes = crypt_get_metadata_size_bytes(cd);
411
0
  keyslots_size_bytes = crypt_get_keyslots_size_bytes(cd);
412
0
  data_offset_bytes = crypt_get_data_offset_sectors(cd) * SECTOR_SIZE;
413
414
0
  if (!metadata_size_bytes)
415
0
    metadata_size_bytes = LUKS2_HDR_16K_LEN;
416
417
0
  if (data_offset_bytes && data_offset_bytes < 2 * metadata_size_bytes) {
418
0
    log_err(cd, _("Requested data offset is too small."));
419
0
    return -EINVAL;
420
0
  }
421
422
  /* Increase keyslot size according to data offset */
423
0
  if (!keyslots_size_bytes && data_offset_bytes)
424
0
    keyslots_size_bytes = data_offset_bytes - 2 * metadata_size_bytes;
425
426
  /* keyslots size has to be 4 KiB aligned */
427
0
  keyslots_size_bytes -= (keyslots_size_bytes % 4096);
428
429
0
  if (keyslots_size_bytes > LUKS2_MAX_KEYSLOTS_SIZE)
430
0
    keyslots_size_bytes = LUKS2_MAX_KEYSLOTS_SIZE;
431
432
0
  if (!keyslots_size_bytes) {
433
0
    assert(LUKS2_DEFAULT_HDR_SIZE > 2 * LUKS2_HDR_OFFSET_MAX);
434
0
    keyslots_size_bytes = LUKS2_DEFAULT_HDR_SIZE - 2 * metadata_size_bytes;
435
    /* Decrease keyslots_size due to metadata device being too small */
436
0
    if (!device_size(crypt_metadata_device(cd), &mdev_size_bytes) &&
437
0
        ((keyslots_size_bytes + 2 * metadata_size_bytes) > mdev_size_bytes) &&
438
0
        device_fallocate(crypt_metadata_device(cd), keyslots_size_bytes + 2 * metadata_size_bytes) &&
439
0
        ((2 * metadata_size_bytes) <= mdev_size_bytes))
440
0
      keyslots_size_bytes = mdev_size_bytes - 2 * metadata_size_bytes;
441
0
  }
442
443
  /* Decrease keyslots_size if we have smaller data_offset */
444
0
  if (data_offset_bytes && (keyslots_size_bytes + 2 * metadata_size_bytes) > data_offset_bytes) {
445
0
    keyslots_size_bytes = data_offset_bytes - 2 * metadata_size_bytes;
446
0
    log_dbg(cd, "Decreasing keyslot area size to %" PRIu64
447
0
      " bytes due to the requested data offset %"
448
0
      PRIu64 " bytes.", keyslots_size_bytes, data_offset_bytes);
449
0
  }
450
451
  /* Data offset has priority */
452
0
  if (!data_offset_bytes && alignment_bytes) {
453
0
    data_offset_bytes = size_round_up(2 * metadata_size_bytes + keyslots_size_bytes,
454
0
              (size_t)alignment_bytes);
455
0
    data_offset_bytes += alignment_offset_bytes;
456
0
  }
457
458
0
  if (crypt_get_metadata_size_bytes(cd) && (crypt_get_metadata_size_bytes(cd) != metadata_size_bytes))
459
0
    log_std(cd, _("WARNING: LUKS2 metadata size changed to %" PRIu64 " bytes.\n"),
460
0
      metadata_size_bytes);
461
462
0
  if (crypt_get_keyslots_size_bytes(cd) && (crypt_get_keyslots_size_bytes(cd) != keyslots_size_bytes))
463
0
    log_std(cd, _("WARNING: LUKS2 keyslots area size changed to %" PRIu64 " bytes.\n"),
464
0
      keyslots_size_bytes);
465
466
0
  *ret_metadata_size_bytes = metadata_size_bytes;
467
0
  *ret_keyslots_size_bytes = keyslots_size_bytes;
468
0
  *ret_data_offset_bytes = data_offset_bytes;
469
470
0
  return 0;
471
0
}