Coverage Report

Created: 2026-02-11 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptsetup/lib/fvault2/fvault2.c
Line
Count
Source
1
// SPDX-License-Identifier: LGPL-2.1-or-later
2
/*
3
 * FVAULT2 (FileVault2-compatible) volume handling
4
 *
5
 * Copyright (C) 2021-2022 Pavel Tobias
6
 */
7
8
#include <errno.h>
9
#include <regex.h>
10
#include <stdio.h>
11
#include <uuid/uuid.h>
12
13
#include "internal.h"
14
#include "fvault2.h"
15
16
/* Core Storage signature/magic; "CS" big-endian */
17
160
#define FVAULT2_CORE_STORAGE_MAGIC 0x4353
18
19
/* size of the physical volume header in bytes */
20
5.64k
#define FVAULT2_VOL_HEADER_SIZE 512
21
22
/* size of a single metadata block in bytes */
23
637
#define FVAULT2_MD_BLOCK_SIZE 8192
24
25
/* maximal offset to read metadata block */
26
248
#define FVAULT2_MAX_OFF 1024*1024*1024
27
28
/* encrypted metadata parsing progress flags (see _read_encrypted_metadata) */
29
0
#define FVAULT2_ENC_MD_PARSED_0x0019 0b001
30
0
#define FVAULT2_ENC_MD_PARSED_0x001A 0b010
31
0
#define FVAULT2_ENC_MD_PARSED_0x0305 0b100
32
34
#define FVAULT2_ENC_MD_PARSED_NONE 0b000
33
4
#define FVAULT2_ENC_MD_PARSED_ALL 0b111
34
35
/* sizes of decoded PassphraseWrappedKEKStruct and KEKWrappedVolumeKeyStruct */
36
0
#define FVAULT2_PWK_SIZE 284
37
0
#define FVAULT2_KWVK_SIZE 256
38
39
/* size of an AES-128 key */
40
784
#define FVAULT2_AES_KEY_SIZE 16
41
42
/* size of the volume key and the encrypted metadata decryption key */
43
183
#define FVAULT2_XTS_KEY_SIZE (FVAULT2_AES_KEY_SIZE * 2)
44
45
/* size of an XTS tweak value */
46
57
#define FVAULT2_XTS_TWEAK_SIZE 16
47
48
/* size of a binary representation of a UUID */
49
0
#define FVAULT2_UUID_BIN_SIZE 16
50
51
struct crc32_checksum {
52
  uint32_t value;
53
  uint32_t seed;
54
} __attribute__((packed));
55
56
struct volume_header {
57
  struct crc32_checksum checksum;
58
  uint16_t version;
59
  uint16_t block_type;
60
  uint8_t unknown1[52];
61
  uint64_t ph_vol_size;
62
  uint8_t unknown2[16];
63
  uint16_t magic;
64
  uint32_t checksum_algo;
65
  uint8_t unknown3[2];
66
  uint32_t block_size;
67
  uint32_t metadata_size;
68
  uint64_t disklbl_blkoff;
69
  uint64_t other_md_blkoffs[3];
70
  uint8_t unknown4[32];
71
  uint32_t key_data_size;
72
  uint32_t cipher;
73
  uint8_t key_data[FVAULT2_AES_KEY_SIZE];
74
  uint8_t unknown5[112];
75
  uint8_t ph_vol_uuid[FVAULT2_UUID_BIN_SIZE];
76
  uint8_t unknown6[192];
77
} __attribute__((packed));
78
79
struct volume_groups_descriptor {
80
  uint8_t unknown1[8];
81
  uint64_t enc_md_blocks_n;
82
  uint8_t unknown2[16];
83
  uint64_t enc_md_blkoff;
84
} __attribute__((packed));
85
86
struct metadata_block_header {
87
  struct crc32_checksum checksum;
88
  uint16_t version;
89
  uint16_t block_type;
90
  uint8_t unknown1[20];
91
  uint64_t block_num;
92
  uint8_t unknown2[8];
93
  uint32_t block_size;
94
  uint8_t unknown3[12];
95
} __attribute__((packed));
96
97
struct metadata_block_0x0011 {
98
  struct metadata_block_header header;
99
  uint32_t md_size;
100
  uint8_t unknown1[4];
101
  struct crc32_checksum checksum;
102
  uint8_t unknown2[140];
103
  uint32_t vol_gr_des_off;
104
} __attribute__((packed));
105
106
struct metadata_block_0x0019 {
107
  struct metadata_block_header header;
108
  uint8_t unknown1[40];
109
  uint32_t xml_comp_size;
110
  uint32_t xml_uncomp_size;
111
  uint32_t xml_off;
112
  uint32_t xml_size;
113
} __attribute__((packed));
114
115
struct metadata_block_0x001a {
116
  struct metadata_block_header header;
117
  uint8_t unknown1[64];
118
  uint32_t xml_off;
119
  uint32_t xml_size;
120
} __attribute__((packed));
121
122
struct metadata_block_0x0305 {
123
  struct metadata_block_header header;
124
  uint32_t entries_n;
125
  uint8_t unknown1[36];
126
  uint32_t log_vol_blkoff;
127
} __attribute__((packed));
128
129
struct passphrase_wrapped_kek {
130
  uint32_t pbkdf2_salt_type;
131
  uint32_t pbkdf2_salt_size;
132
  uint8_t pbkdf2_salt[FVAULT2_PBKDF2_SALT_SIZE];
133
  uint32_t wrapped_kek_type;
134
  uint32_t wrapped_kek_size;
135
  uint8_t wrapped_kek[FVAULT2_WRAPPED_KEY_SIZE];
136
  uint8_t unknown1[112];
137
  uint32_t pbkdf2_iters;
138
} __attribute__((packed));
139
140
struct kek_wrapped_volume_key {
141
  uint32_t wrapped_vk_type;
142
  uint32_t wrapped_vk_size;
143
  uint8_t wrapped_vk[FVAULT2_WRAPPED_KEY_SIZE];
144
} __attribute__((packed));
145
146
/**
147
 * Test whether all bytes of a chunk of memory are equal to a constant value.
148
 * @param[in] value the value all bytes should be equal to
149
 * @param[in] data the tested chunk of memory
150
 * @param[in] data_size byte-size of the chunk of memory
151
 */
152
static bool _filled_with(
153
  uint8_t value,
154
  const void *data,
155
  size_t data_size)
156
23
{
157
23
  const uint8_t *data_bytes = data;
158
23
  size_t i;
159
160
24
  for (i = 0; i < data_size; i++)
161
24
    if (data_bytes[i] != value)
162
23
      return false;
163
164
0
  return true;
165
23
}
166
167
/**
168
 * Assert the validity of the CRC checksum of a chunk of memory.
169
 * @param[in] data a chunk of memory starting with a crc32_checksum struct
170
 * @param[in] data_size the size of the chunk of memory in bytes
171
 */
172
static int _check_crc(
173
  const void *data,
174
  size_t data_size)
175
1.57k
{
176
1.57k
  const size_t crc_size = sizeof(struct crc32_checksum);
177
1.57k
  uint32_t seed;
178
1.57k
  uint32_t value;
179
180
1.57k
  assert(data_size >= crc_size);
181
182
1.57k
  value = le32_to_cpu(((const struct crc32_checksum *)data)->value);
183
1.57k
  seed = le32_to_cpu(((const struct crc32_checksum *)data)->seed);
184
1.57k
  if (seed != 0xffffffff)
185
1.27k
    return -EINVAL;
186
187
296
  if (crypt_crc32c(seed, (const uint8_t *)data + crc_size,
188
296
      data_size - crc_size) != value)
189
77
    return -EINVAL;
190
191
219
  return 0;
192
296
}
193
194
/**
195
 * Unwrap an AES-wrapped key.
196
 * @param[in] kek the KEK with which the key has been wrapped
197
 * @param[in] kek_size the size of the KEK in bytes
198
 * @param[in] key_wrapped the wrapped key
199
 * @param[in] key_wrapped_size the size of the wrapped key in bytes
200
 * @param[out] key_buf key an output buffer for the unwrapped key
201
 * @param[in] key_buf_size the size of the output buffer in bytes
202
 */
203
static int _unwrap_key(
204
  const void *kek,
205
  size_t kek_size,
206
  const void *key_wrapped,
207
  size_t key_wrapped_size,
208
  void *key_buf,
209
  size_t key_buf_size)
210
0
{
211
  /* Algorithm and notation taken from NIST Special Publication 800-38F:
212
  https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
213
214
  This implementation supports only 128-bit KEKs and wrapped keys. */
215
216
0
  int r = 0;
217
0
  struct crypt_cipher *cipher = NULL;
218
0
  void *cipher_in = NULL;
219
0
  void *cipher_out = NULL;
220
0
  uint64_t a;
221
0
  uint64_t r2;
222
0
  uint64_t r3;
223
0
  uint64_t t;
224
0
  uint64_t r2_prev;
225
226
0
  assert(kek_size == 16 && key_wrapped_size == 24 && key_buf_size == 16);
227
228
0
  r = crypt_cipher_init(&cipher, "aes", "ecb", kek, kek_size);
229
0
  if (r < 0)
230
0
    goto out;
231
232
0
  cipher_in = malloc(16);
233
0
  if (cipher_in == NULL) {
234
0
    r = -ENOMEM;
235
0
    goto out;
236
0
  }
237
238
0
  cipher_out = malloc(16);
239
0
  if (cipher_out == NULL) {
240
0
    r = -ENOMEM;
241
0
    goto out;
242
0
  }
243
244
  /* CHAPTER 6.1, ALGORITHM 2: W^-1(C) */
245
246
  /* initialize variables */
247
0
  a = ((const uint64_t *)key_wrapped)[0]; /* A = C_1 (see step 1c) */
248
0
  r2 = ((const uint64_t *)key_wrapped)[1]; /* R_1 = C_2 (see step 1d) */
249
0
  r3 = ((const uint64_t *)key_wrapped)[2]; /* R_2 = C_3 (see step 1d) */
250
251
  /* calculate intermediate values for each t = s, ..., 1 (see step 2),
252
  where s = 6 * (n - 1) (see step 1a) */
253
0
  for (t = 6 * (3 - 1); t > 0; t--) {
254
    /* store current R2 for later assignment (see step 2c) */
255
0
    r2_prev = r2;
256
257
    /* prepare input for CIPH^{-1}_K (see steps 2a, 2b) */
258
0
    ((uint64_t *)cipher_in)[0] = a ^ cpu_to_be64(t);
259
0
    ((uint64_t *)cipher_in)[1] = r3;
260
261
    /* A||R2 = CIPH^{-1}_K(...) (see steps 2a, 2b) */
262
0
    r = crypt_cipher_decrypt(cipher, cipher_in, cipher_out, 16, NULL, 0);
263
0
    if (r < 0)
264
0
      goto out;
265
0
    a = ((uint64_t *)cipher_out)[0];
266
0
    r2 = ((uint64_t *)cipher_out)[1];
267
268
    /* assign previous R2 (see step 2c) */
269
0
    r3 = r2_prev;
270
0
  }
271
272
  /* note that A||R_1||R_2 holds the result S (see step 3) */
273
274
  /* CHAPTER 6.2, ALGORITHM 4: KW-AD(C) */
275
276
  /* check whether MSB_{64}(S) (= A) matches ICV1 (see step 3) */
277
0
  if (a != 0xA6A6A6A6A6A6A6A6) {
278
0
    r = -EPERM;
279
0
    goto out;
280
0
  }
281
282
  /* return LSB_{128}(S) (= R_1||R_2) (see step 4) */
283
0
  ((uint64_t *)key_buf)[0] = r2;
284
0
  ((uint64_t *)key_buf)[1] = r3;
285
0
out:
286
0
  free(cipher_in);
287
0
  free(cipher_out);
288
0
  if (cipher != NULL)
289
0
    crypt_cipher_destroy(cipher);
290
0
  return r;
291
0
}
292
293
/**
294
 * Search XML plist data for a property and return its value.
295
 * @param[in] xml a 0-terminated string containing the XML plist data
296
 * @param[in] prop_key a 0-terminated string with the seeked property's key
297
 * @param[in] prop_type a 0-terminated string with the seeked property's type
298
 * @param[out] value a 0-terminated string with the found property's value
299
 */
300
static int _search_xml(
301
  const char *xml,
302
  const char *prop_key,
303
  const char *prop_type,
304
  char **value)
305
0
{
306
0
  int r = 0;
307
0
  char *pattern = NULL;
308
0
  bool regex_ready = false;
309
0
  regex_t regex;
310
0
  regmatch_t match[2];
311
0
  const char *value_start;
312
0
  size_t value_len;
313
314
0
  if (asprintf(&pattern, "<key>%s</key><%s[^>]*>([^<]+)</%s>",
315
0
      prop_key, prop_type, prop_type) < 0) {
316
0
    r = -ENOMEM;
317
0
    goto out;
318
0
  }
319
320
0
  if (regcomp(&regex, pattern, REG_EXTENDED) != 0) {
321
0
    r = -EINVAL;
322
0
    goto out;
323
0
  }
324
325
0
  regex_ready = true;
326
327
0
  if (regexec(&regex, xml, 2, match, 0) != 0) {
328
0
    r = -EINVAL;
329
0
    goto out;
330
0
  }
331
332
0
  value_start = xml + match[1].rm_so;
333
0
  value_len = match[1].rm_eo - match[1].rm_so;
334
335
0
  *value = calloc(value_len + 1, 1);
336
0
  if (*value == NULL) {
337
0
    r = -ENOMEM;
338
0
    goto out;
339
0
  }
340
341
0
  memcpy(*value, value_start, value_len);
342
0
out:
343
0
  free(pattern);
344
0
  if (regex_ready)
345
0
    regfree(&regex);
346
0
  return r;
347
0
}
348
349
/**
350
 * Extract relevant info from a metadata block of type 0x0019.
351
 * @param[in] md_block the pre-read and decrypted metadata block
352
 * @param[out] pbkdf2_iters number of PBKDF2 iterations
353
 * @param[out] pbkdf2_salt PBKDF2 salt (intermt. key derivation from passphrase)
354
 * @param[out] wrapped_kek KEK AES-wrapped with passphrase-derived key
355
 * @param[out] wrapped_vk volume key AES-wrapped with KEK
356
 */
357
static int _parse_metadata_block_0x0019(
358
  const struct metadata_block_0x0019 *md_block,
359
  uint32_t *pbkdf2_iters,
360
  uint8_t *pbkdf2_salt,
361
  uint8_t *wrapped_kek,
362
  uint8_t *wrapped_vk)
363
0
{
364
0
  int r = 0;
365
0
  char *xml = NULL;
366
0
  char *pwk_base64 = NULL;
367
0
  char *kwvk_base64 = NULL;
368
0
  struct passphrase_wrapped_kek *pwk = NULL;
369
0
  struct kek_wrapped_volume_key *kwvk = NULL;
370
0
  size_t decoded_size;
371
0
  uint32_t xml_off = le32_to_cpu(md_block->xml_off);
372
0
  uint32_t xml_size = le32_to_cpu(md_block->xml_size);
373
374
0
  if (xml_off + xml_size > FVAULT2_MD_BLOCK_SIZE)
375
0
    return -EINVAL;
376
377
0
  xml = strndup((const char *)md_block + xml_off, xml_size);
378
0
  if (xml == NULL)
379
0
    return -ENOMEM;
380
381
0
  r = _search_xml(xml, "PassphraseWrappedKEKStruct", "data", &pwk_base64);
382
0
  if (r < 0)
383
0
    goto out;
384
0
  r = crypt_base64_decode((char **)&pwk, &decoded_size, pwk_base64, strlen(pwk_base64));
385
0
  if (r < 0)
386
0
    goto out;
387
0
  if (decoded_size != FVAULT2_PWK_SIZE) {
388
0
    r = -EINVAL;
389
0
    goto out;
390
0
  }
391
392
0
  r = _search_xml(xml, "KEKWrappedVolumeKeyStruct", "data", &kwvk_base64);
393
0
  if (r < 0)
394
0
    goto out;
395
0
  r = crypt_base64_decode((char **)&kwvk, &decoded_size, kwvk_base64, strlen(kwvk_base64));
396
0
  if (r < 0)
397
0
    goto out;
398
0
  if (decoded_size != FVAULT2_KWVK_SIZE) {
399
0
    r = -EINVAL;
400
0
    goto out;
401
0
  }
402
403
0
  *pbkdf2_iters = le32_to_cpu(pwk->pbkdf2_iters);
404
0
  memcpy(pbkdf2_salt, pwk->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE);
405
0
  memcpy(wrapped_kek, pwk->wrapped_kek, FVAULT2_WRAPPED_KEY_SIZE);
406
0
  memcpy(wrapped_vk, kwvk->wrapped_vk, FVAULT2_WRAPPED_KEY_SIZE);
407
0
out:
408
0
  free(xml);
409
0
  free(pwk_base64);
410
0
  free(kwvk_base64);
411
0
  free(pwk);
412
0
  free(kwvk);
413
0
  return r;
414
0
}
415
416
/**
417
 * Validate a UUID string and reformat it to match system defaults.
418
 * @param[in] uuid_in the original UUID string
419
 * @param[out] uuid_out the reformatted UUID string
420
 */
421
static int _reformat_uuid(
422
  const char *uuid_in,
423
  char *uuid_out)
424
0
{
425
0
  uint8_t uuid_bin[FVAULT2_UUID_LEN];
426
0
  int r;
427
428
0
  r = uuid_parse(uuid_in, uuid_bin);
429
0
  if (r < 0)
430
0
    return -EINVAL;
431
432
0
  uuid_unparse(uuid_bin, uuid_out);
433
0
  return 0;
434
0
}
435
436
/**
437
 * Extract relevant info from a metadata block of type 0x001A.
438
 * @param[in] md_block the pre-read and decrypted metadata block
439
 * @param[out] log_vol_size encrypted logical volume size in bytes
440
 * @param[out] family_uuid logical volume family UUID
441
 */
442
static int _parse_metadata_block_0x001a(
443
  const struct metadata_block_0x001a *md_block,
444
  uint64_t *log_vol_size,
445
  char *family_uuid)
446
0
{
447
0
  int r = 0;
448
0
  char *xml = NULL;
449
0
  char *log_vol_size_str = NULL;
450
0
  char *family_uuid_str = NULL;
451
0
  uint32_t xml_off = le32_to_cpu(md_block->xml_off);
452
0
  uint32_t xml_size = le32_to_cpu(md_block->xml_size);
453
454
0
  if (xml_off + xml_size > FVAULT2_MD_BLOCK_SIZE)
455
0
    return -EINVAL;
456
457
0
  xml = strndup((const char *)md_block + xml_off, xml_size);
458
0
  if (xml == NULL)
459
0
    return -ENOMEM;
460
461
0
  r = _search_xml(xml, "com.apple.corestorage.lv.size", "integer", &log_vol_size_str);
462
0
  if (r < 0)
463
0
    goto out;
464
0
  *log_vol_size = strtoull(log_vol_size_str, NULL, 16);
465
0
  if (*log_vol_size == 0 || *log_vol_size == ULLONG_MAX) {
466
0
    r = -EINVAL;
467
0
    goto out;
468
0
  }
469
470
0
  r = _search_xml(xml, "com.apple.corestorage.lv.familyUUID", "string", &family_uuid_str);
471
0
  if (r < 0)
472
0
    goto out;
473
0
  r = _reformat_uuid(family_uuid_str, family_uuid);
474
0
  if (r < 0)
475
0
    goto out;
476
0
out:
477
0
  free(xml);
478
0
  free(log_vol_size_str);
479
0
  free(family_uuid_str);
480
0
  return r;
481
0
}
482
483
/**
484
 * Extract relevant info from a metadata block of type 0x0305.
485
 * @param[in] md_block the pre-read and decrypted metadata block
486
 * @param[out] log_vol_blkoff block-offset of the encrypted logical volume
487
 */
488
static int _parse_metadata_block_0x0305(
489
  const struct metadata_block_0x0305 *md_block,
490
  uint32_t *log_vol_blkoff)
491
0
{
492
0
  *log_vol_blkoff = le32_to_cpu(md_block->log_vol_blkoff);
493
0
  return 0;
494
0
}
495
496
/**
497
 * Extract relevant info from the physical volume header.
498
 * @param[in] devfd opened device file descriptor
499
 * @param[in] cd crypt_device passed into FVAULT2_read_metadata
500
 * @param[out] block_size used to compute byte-offsets from block-offsets
501
 * @param[out] disklbl_blkoff block-offset of the disk label block
502
 * @param[out] ph_vol_uuid physical volume UUID
503
 * @param[out] enc_md_key AES-XTS key used to decrypt the encrypted metadata
504
 */
505
static int _read_volume_header(
506
  int devfd,
507
  struct crypt_device *cd,
508
  uint64_t *block_size,
509
  uint64_t *disklbl_blkoff,
510
  char *ph_vol_uuid,
511
  struct volume_key **enc_md_key)
512
1.41k
{
513
1.41k
  int r = 0;
514
1.41k
  struct device *dev = crypt_metadata_device(cd);
515
1.41k
  struct volume_header *vol_header = NULL;
516
1.41k
  void *enc_key = NULL;
517
518
1.41k
  assert(sizeof(*vol_header) == FVAULT2_VOL_HEADER_SIZE);
519
520
1.41k
  vol_header = malloc(FVAULT2_VOL_HEADER_SIZE);
521
1.41k
  if (vol_header == NULL) {
522
0
    r = -ENOMEM;
523
0
    goto out;
524
0
  }
525
526
1.41k
  log_dbg(cd, "Reading FVAULT2 volume header of size %u bytes.", FVAULT2_VOL_HEADER_SIZE);
527
1.41k
  if (read_blockwise(devfd, device_block_size(cd, dev),
528
1.41k
      device_alignment(dev), vol_header,
529
1.41k
      FVAULT2_VOL_HEADER_SIZE) != FVAULT2_VOL_HEADER_SIZE) {
530
0
    log_err(cd, _("Could not read %u bytes of volume header."), FVAULT2_VOL_HEADER_SIZE);
531
0
    r = -EIO;
532
0
    goto out;
533
0
  }
534
535
1.41k
  r = _check_crc(vol_header, FVAULT2_VOL_HEADER_SIZE);
536
1.41k
  if (r < 0) {
537
1.24k
    log_dbg(cd, "CRC mismatch.");
538
1.24k
    goto out;
539
1.24k
  }
540
541
170
  if (le16_to_cpu(vol_header->version) != 1) {
542
10
    log_err(cd, _("Unsupported FVAULT2 version %" PRIu16 "."),
543
10
      le16_to_cpu(vol_header->version));
544
10
    r = -EINVAL;
545
10
    goto out;
546
10
  }
547
548
160
  if (be16_to_cpu(vol_header->magic) != FVAULT2_CORE_STORAGE_MAGIC) {
549
6
    log_dbg(cd, "Invalid Core Storage magic bytes.");
550
6
    r = -EINVAL;
551
6
    goto out;
552
6
  }
553
554
154
  if (le32_to_cpu(vol_header->key_data_size) != FVAULT2_AES_KEY_SIZE) {
555
5
    log_dbg(cd, "Unsupported AES key size: %" PRIu32 " bytes.",
556
5
      le32_to_cpu(vol_header->key_data_size));
557
5
    r = -EINVAL;
558
5
    goto out;
559
5
  }
560
561
149
  enc_key = crypt_safe_alloc(FVAULT2_XTS_KEY_SIZE);
562
149
  if (!enc_key) {
563
0
    r = -ENOMEM;
564
0
    goto out;
565
0
  }
566
567
149
  *block_size = le32_to_cpu(vol_header->block_size);
568
149
  *disklbl_blkoff = le64_to_cpu(vol_header->disklbl_blkoff);
569
149
  uuid_unparse(vol_header->ph_vol_uuid, ph_vol_uuid);
570
149
  crypt_safe_memcpy(enc_key, vol_header->key_data, FVAULT2_AES_KEY_SIZE);
571
149
  crypt_safe_memcpy((char *)enc_key + FVAULT2_AES_KEY_SIZE,
572
149
    vol_header->ph_vol_uuid, FVAULT2_AES_KEY_SIZE);
573
574
149
  *enc_md_key = crypt_alloc_volume_key_by_safe_alloc(&enc_key);
575
149
  if (*enc_md_key == NULL) {
576
0
    crypt_safe_free(enc_key);
577
0
    r = -ENOMEM;
578
0
  }
579
1.41k
out:
580
1.41k
  free(vol_header);
581
1.41k
  return r;
582
149
}
583
584
/**
585
 * Extract info from the disk label block and the volume groups descriptor.
586
 * @param[in] devfd opened device file descriptor
587
 * @param[in] cd crypt_device passed into FVAULT2_read_metadata
588
 * @param[in] block_size used to compute byte-offsets from block-offsets
589
 * @param[in] disklbl_blkoff block-offset of the disk label block
590
 * @param[out] enc_md_blkoff block-offset of the encrypted metadata
591
 * @param[out] enc_md_blocks_n total count of encrypted metadata blocks
592
 */
593
static int _read_disklabel(
594
  int devfd,
595
  struct crypt_device *cd,
596
  uint64_t block_size,
597
  uint64_t disklbl_blkoff,
598
  uint64_t *enc_md_blkoff,
599
  uint64_t *enc_md_blocks_n)
600
149
{
601
149
  int r = 0;
602
149
  uint64_t off;
603
149
  ssize_t size;
604
149
  void *md_block = NULL;
605
149
  struct metadata_block_0x0011 *md_block_11;
606
149
  struct volume_groups_descriptor *vol_gr_des = NULL;
607
149
  struct device *dev = crypt_metadata_device(cd);
608
609
149
  md_block = malloc(FVAULT2_MD_BLOCK_SIZE);
610
149
  if (md_block == NULL) {
611
0
    r = -ENOMEM;
612
0
    goto out;
613
0
  }
614
615
149
  if (uint64_mult_overflow(&off, disklbl_blkoff, block_size) ||
616
145
      off > FVAULT2_MAX_OFF) {
617
8
    log_dbg(cd, "Device offset overflow.");
618
8
    r = -EINVAL;
619
8
    goto out;
620
8
  }
621
141
  size = FVAULT2_MD_BLOCK_SIZE;
622
141
  log_dbg(cd, "Reading FVAULT2 disk label header of size %zu bytes.", size);
623
141
  if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
624
141
      device_alignment(dev), md_block, size, off) != size) {
625
3
    r = -EIO;
626
3
    goto out;
627
3
  }
628
629
138
  r = _check_crc(md_block, FVAULT2_MD_BLOCK_SIZE);
630
138
  if (r < 0) {
631
89
    log_dbg(cd, "CRC mismatch.");
632
89
    goto out;
633
89
  }
634
635
49
  vol_gr_des = malloc(sizeof(*vol_gr_des));
636
49
  if (vol_gr_des == NULL) {
637
0
    r = -ENOMEM;
638
0
    goto out;
639
0
  }
640
641
49
  md_block_11 = md_block;
642
49
  off += le32_to_cpu(md_block_11->vol_gr_des_off);
643
49
  if (off > FVAULT2_MAX_OFF) {
644
10
    log_dbg(cd, "Device offset overflow.");
645
10
    r = -EINVAL;
646
10
    goto out;
647
10
  }
648
39
  size = sizeof(struct volume_groups_descriptor);
649
39
  log_dbg(cd, "Reading FVAULT2 volume groups descriptor of size %zu bytes.", size);
650
39
  if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
651
39
      device_alignment(dev), vol_gr_des, size, off) != size) {
652
5
    r = -EIO;
653
5
    goto out;
654
5
  }
655
656
34
  *enc_md_blkoff = le64_to_cpu(vol_gr_des->enc_md_blkoff);
657
34
  *enc_md_blocks_n = le64_to_cpu(vol_gr_des->enc_md_blocks_n);
658
149
out:
659
149
  free(md_block);
660
149
  free(vol_gr_des);
661
149
  return r;
662
34
}
663
664
/**
665
 * Extract info from relevant encrypted metadata blocks.
666
 * @param[in] devfd opened device file descriptor
667
 * @param[in] cd crypt_device passed into FVAULT2_read_metadata
668
 * @param[in] block_size used to compute byte-offsets from block-offsets
669
 * @param[in] start_blkoff block-offset of the start of the encrypted metadata
670
 * @param[in] blocks_n total count of encrypted metadata blocks
671
 * @param[in] key AES-XTS key for decryption
672
 * @param[out] params decryption parameters struct to fill
673
 */
674
static int _read_encrypted_metadata(
675
  int devfd,
676
  struct crypt_device *cd,
677
  uint64_t block_size,
678
  uint64_t start_blkoff,
679
  uint64_t blocks_n,
680
  const struct volume_key *key,
681
  struct fvault2_params *params)
682
34
{
683
34
  int r = 0;
684
34
  int status = FVAULT2_ENC_MD_PARSED_NONE;
685
34
  struct device *dev = crypt_metadata_device(cd);
686
34
  struct crypt_cipher *cipher = NULL;
687
34
  void *tweak;
688
34
  void *md_block_enc = NULL;
689
34
  void *md_block = NULL;
690
34
  struct metadata_block_header *md_block_header;
691
34
  uint32_t log_vol_blkoff;
692
34
  uint64_t i, start_off;
693
34
  off_t off;
694
34
  unsigned int block_type;
695
696
34
  tweak = calloc(FVAULT2_XTS_TWEAK_SIZE, 1);
697
34
  if (tweak == NULL) {
698
0
    r = -ENOMEM;
699
0
    goto out;
700
0
  }
701
702
34
  md_block_enc = malloc(FVAULT2_MD_BLOCK_SIZE);
703
34
  if (md_block_enc == NULL) {
704
0
    r = -ENOMEM;
705
0
    goto out;
706
0
  }
707
708
34
  md_block = malloc(FVAULT2_MD_BLOCK_SIZE);
709
34
  if (md_block == NULL) {
710
0
    r = -ENOMEM;
711
0
    goto out;
712
0
  }
713
714
34
  r = crypt_cipher_init(&cipher, "aes", "xts", crypt_volume_key_get_key(key), FVAULT2_XTS_KEY_SIZE);
715
34
  if (r < 0)
716
0
    goto out;
717
718
34
  if (uint64_mult_overflow(&start_off, start_blkoff, block_size) ||
719
30
      start_off > FVAULT2_MAX_OFF) {
720
6
    log_dbg(cd, "Device offset overflow.");
721
6
    r = -EINVAL;
722
6
    goto out;
723
6
  }
724
725
28
  log_dbg(cd, "Reading FVAULT2 encrypted metadata blocks.");
726
28
  for (i = 0; i < blocks_n; i++) {
727
24
    off = start_off + i * FVAULT2_MD_BLOCK_SIZE;
728
24
    if (off > FVAULT2_MAX_OFF) {
729
0
      log_dbg(cd, "Device offset overflow.");
730
0
      r = -EINVAL;
731
0
      goto out;
732
0
    }
733
24
    if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
734
24
        device_alignment(dev), md_block_enc,
735
24
        FVAULT2_MD_BLOCK_SIZE, off)
736
24
        != FVAULT2_MD_BLOCK_SIZE) {
737
1
      r = -EIO;
738
1
      goto out;
739
1
    }
740
741
23
    if (_filled_with(0, md_block_enc, FVAULT2_MD_BLOCK_SIZE))
742
0
      break;
743
744
23
    *(uint64_t *)tweak = cpu_to_le64(i);
745
23
    r = crypt_cipher_decrypt(cipher, md_block_enc, md_block,
746
23
      FVAULT2_MD_BLOCK_SIZE, tweak, FVAULT2_XTS_TWEAK_SIZE);
747
23
    if (r < 0)
748
0
      goto out;
749
750
23
    r = _check_crc(md_block, FVAULT2_MD_BLOCK_SIZE);
751
23
    if (r < 0) {
752
23
      log_dbg(cd, "CRC mismatch.");
753
23
      goto out;
754
23
    }
755
756
0
    md_block_header = md_block;
757
0
    block_type = le16_to_cpu(md_block_header->block_type);
758
0
    switch (block_type) {
759
0
    case 0x0019:
760
0
      log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x0019.", i);
761
0
      r = _parse_metadata_block_0x0019(md_block,
762
0
        &params->pbkdf2_iters,
763
0
        (uint8_t *)params->pbkdf2_salt,
764
0
        (uint8_t *)params->wrapped_kek,
765
0
        (uint8_t *)params->wrapped_vk);
766
0
      if (r < 0)
767
0
        goto out;
768
0
      status |= FVAULT2_ENC_MD_PARSED_0x0019;
769
0
      break;
770
771
0
    case 0x001A:
772
0
      log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x001A.", i);
773
0
      r = _parse_metadata_block_0x001a(md_block,
774
0
        &params->log_vol_size,
775
0
        params->family_uuid);
776
0
      if (r < 0)
777
0
        goto out;
778
0
      status |= FVAULT2_ENC_MD_PARSED_0x001A;
779
0
      break;
780
781
0
    case 0x0305:
782
0
      log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x0305.", i);
783
0
      r = _parse_metadata_block_0x0305(md_block,
784
0
        &log_vol_blkoff);
785
0
      if (r < 0)
786
0
        goto out;
787
0
      if (uint64_mult_overflow(&params->log_vol_off,
788
0
          log_vol_blkoff, block_size)) {
789
0
        log_dbg(cd, "Device offset overflow.");
790
0
        r = -EINVAL;
791
0
        goto out;
792
0
      }
793
0
      status |= FVAULT2_ENC_MD_PARSED_0x0305;
794
0
      break;
795
0
    }
796
0
  }
797
798
4
  if (status != FVAULT2_ENC_MD_PARSED_ALL) {
799
4
    log_dbg(cd, "Necessary FVAULT2 metadata blocks not found.");
800
4
    r = -EINVAL;
801
4
    goto out;
802
4
  }
803
34
out:
804
34
  free(tweak);
805
34
  free(md_block_enc);
806
34
  free(md_block);
807
34
  if (cipher != NULL)
808
34
    crypt_cipher_destroy(cipher);
809
34
  return r;
810
4
}
811
812
/**
813
 * Activate device.
814
 * @param[in] cd crypt_device struct passed into FVAULT2_activate_by_*
815
 * @param[in] name name of the mapped device
816
 * @param[in] vol_key the pre-derived AES-XTS volume key
817
 * @param[in] params logical volume decryption parameters
818
 * @param[in] flags flags assigned to the crypt_dm_active_device struct
819
 */
820
static int _activate(
821
  struct crypt_device *cd,
822
  const char *name,
823
  struct volume_key *vol_key,
824
  const struct fvault2_params *params,
825
  uint32_t flags)
826
0
{
827
0
  int r = 0;
828
0
  char *cipher = NULL;
829
0
  struct crypt_dm_active_device dm_dev = {
830
0
    .flags = flags,
831
0
    .size = params->log_vol_size / SECTOR_SIZE
832
0
  };
833
834
0
  r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL,
835
0
    crypt_get_data_offset(cd), &dm_dev.size, &dm_dev.flags);
836
0
  if (r)
837
0
    return r;
838
839
0
  if (asprintf(&cipher, "%s-%s", params->cipher, params->cipher_mode) < 0)
840
0
    return -ENOMEM;
841
842
0
  r = dm_crypt_target_set(&dm_dev.segment, 0, dm_dev.size,
843
0
    crypt_data_device(cd), vol_key, cipher,
844
0
    crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
845
0
    NULL, 0, 0, crypt_get_sector_size(cd));
846
847
0
  if (!r)
848
0
    r = dm_create_device(cd, name, CRYPT_FVAULT2, &dm_dev);
849
850
0
  dm_targets_free(cd, &dm_dev);
851
0
  free(cipher);
852
0
  return r;
853
0
}
854
855
int FVAULT2_read_metadata(
856
  struct crypt_device *cd,
857
  struct fvault2_params *params)
858
1.41k
{
859
1.41k
  int r = 0;
860
1.41k
  int devfd;
861
1.41k
  uint64_t block_size;
862
1.41k
  uint64_t disklbl_blkoff;
863
1.41k
  uint64_t enc_md_blkoff;
864
1.41k
  uint64_t enc_md_blocks_n;
865
1.41k
  struct volume_key *enc_md_key = NULL;
866
1.41k
  struct device *device = crypt_metadata_device(cd);
867
868
1.41k
  devfd = device_open(cd, device, O_RDONLY);
869
1.41k
  if (devfd < 0) {
870
0
    log_err(cd, _("Cannot open device %s."), device_path(device));
871
0
    return -EIO;
872
0
  }
873
874
1.41k
  r = _read_volume_header(devfd, cd, &block_size, &disklbl_blkoff,
875
1.41k
    params->ph_vol_uuid, &enc_md_key);
876
1.41k
  if (r < 0)
877
1.26k
    goto out;
878
879
149
  r = _read_disklabel(devfd, cd, block_size, disklbl_blkoff,
880
149
    &enc_md_blkoff, &enc_md_blocks_n);
881
149
  if (r < 0)
882
115
    goto out;
883
884
34
  r = _read_encrypted_metadata(devfd, cd, block_size, enc_md_blkoff,
885
34
    enc_md_blocks_n, enc_md_key, params);
886
34
  if (r < 0)
887
34
    goto out;
888
889
0
  params->cipher = "aes";
890
0
  params->cipher_mode = "xts-plain64";
891
0
  params->key_size = FVAULT2_XTS_KEY_SIZE;
892
1.41k
out:
893
1.41k
  crypt_free_volume_key(enc_md_key);
894
1.41k
  return r;
895
0
}
896
897
int FVAULT2_get_volume_key(
898
  struct crypt_device *cd,
899
  const char *passphrase,
900
  size_t passphrase_len,
901
  const struct fvault2_params *params,
902
  struct volume_key **r_vol_key)
903
0
{
904
0
  int r = 0;
905
0
  uint8_t family_uuid_bin[FVAULT2_UUID_BIN_SIZE];
906
0
  struct crypt_hash *hash = NULL;
907
0
  void *passphrase_key = NULL, *kek = NULL, *vol_key= NULL;
908
909
0
  *r_vol_key = NULL;
910
911
0
  if (uuid_parse(params->family_uuid, family_uuid_bin) < 0) {
912
0
    log_dbg(cd, "Could not parse logical volume family UUID: %s.",
913
0
      params->family_uuid);
914
0
    r = -EINVAL;
915
0
    goto out;
916
0
  }
917
918
0
  passphrase_key = crypt_safe_alloc(FVAULT2_AES_KEY_SIZE);
919
0
  if (passphrase_key == NULL) {
920
0
    r = -ENOMEM;
921
0
    goto out;
922
0
  }
923
924
0
  r = crypt_pbkdf("pbkdf2", "sha256", passphrase, passphrase_len,
925
0
    params->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE, passphrase_key,
926
0
    FVAULT2_AES_KEY_SIZE, params->pbkdf2_iters, 0, 0);
927
0
  if (r < 0)
928
0
    goto out;
929
930
0
  kek = crypt_safe_alloc(FVAULT2_AES_KEY_SIZE);
931
0
  if (kek == NULL) {
932
0
    r = -ENOMEM;
933
0
    goto out;
934
0
  }
935
936
0
  r = _unwrap_key(passphrase_key, FVAULT2_AES_KEY_SIZE, params->wrapped_kek,
937
0
      FVAULT2_WRAPPED_KEY_SIZE, kek, FVAULT2_AES_KEY_SIZE);
938
0
  if (r < 0)
939
0
    goto out;
940
941
0
  vol_key = crypt_safe_alloc(FVAULT2_XTS_KEY_SIZE);
942
0
  if (vol_key == NULL) {
943
0
    r = -ENOMEM;
944
0
    goto out;
945
0
  }
946
947
0
  r = _unwrap_key(kek, FVAULT2_AES_KEY_SIZE, params->wrapped_vk,
948
0
    FVAULT2_WRAPPED_KEY_SIZE, vol_key, FVAULT2_AES_KEY_SIZE);
949
0
  if (r < 0)
950
0
    goto out;
951
952
0
  r = crypt_hash_init(&hash, "sha256");
953
0
  if (r < 0)
954
0
    goto out;
955
0
  r = crypt_hash_write(hash, vol_key, FVAULT2_AES_KEY_SIZE);
956
0
  if (r < 0)
957
0
    goto out;
958
0
  r = crypt_hash_write(hash, (char *)family_uuid_bin,
959
0
    FVAULT2_UUID_BIN_SIZE);
960
0
  if (r < 0)
961
0
    goto out;
962
0
  r = crypt_hash_final(hash, (char *)vol_key + FVAULT2_AES_KEY_SIZE,
963
0
    FVAULT2_AES_KEY_SIZE);
964
0
  if (r < 0)
965
0
    goto out;
966
967
0
  *r_vol_key = crypt_alloc_volume_key_by_safe_alloc(&vol_key);
968
0
  if (!*r_vol_key)
969
0
    r = -ENOMEM;
970
0
out:
971
0
  crypt_safe_free(passphrase_key);
972
0
  crypt_safe_free(kek);
973
0
  crypt_safe_free(vol_key);
974
0
  if (hash != NULL)
975
0
    crypt_hash_destroy(hash);
976
0
  return r;
977
0
}
978
979
int FVAULT2_dump(
980
  struct crypt_device *cd,
981
  struct device *device,
982
  const struct fvault2_params *params)
983
0
{
984
0
  log_std(cd, "Header information for FVAULT2 device %s.\n", device_path(device));
985
986
0
  log_std(cd, "Physical volume UUID: \t%s\n", params->ph_vol_uuid);
987
0
  log_std(cd, "Family UUID:          \t%s\n", params->family_uuid);
988
989
0
  log_std(cd, "Logical volume offset:\t%" PRIu64 " [bytes]\n", params->log_vol_off);
990
991
0
  log_std(cd, "Logical volume size:  \t%" PRIu64 " [bytes]\n",
992
0
    params->log_vol_size);
993
994
0
  log_std(cd, "Cipher:               \t%s\n", params->cipher);
995
0
  log_std(cd, "Cipher mode:          \t%s\n", params->cipher_mode);
996
997
0
  log_std(cd, "PBKDF2 iterations:    \t%" PRIu32 "\n", params->pbkdf2_iters);
998
999
0
  log_std(cd, "PBKDF2 salt:          \t");
1000
0
  crypt_log_hex(cd, params->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE, " ", 0, NULL);
1001
0
  log_std(cd, "\n");
1002
1003
0
  return 0;
1004
0
}
1005
1006
int FVAULT2_activate_by_volume_key(
1007
  struct crypt_device *cd,
1008
  const char *name,
1009
  struct volume_key *vk,
1010
  const struct fvault2_params *params,
1011
  uint32_t flags)
1012
0
{
1013
0
  assert(crypt_volume_key_length(vk) == FVAULT2_XTS_KEY_SIZE);
1014
1015
0
  return _activate(cd, name, vk, params, flags);
1016
0
}
1017
1018
size_t FVAULT2_volume_key_size(void)
1019
0
{
1020
0
  return FVAULT2_XTS_KEY_SIZE;
1021
0
}