Coverage Report

Created: 2026-06-08 06:07

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
0
#define FVAULT2_CORE_STORAGE_MAGIC 0x4353
18
19
/* size of the physical volume header in bytes */
20
0
#define FVAULT2_VOL_HEADER_SIZE 512
21
22
/* size of a single metadata block in bytes */
23
0
#define FVAULT2_MD_BLOCK_SIZE 8192
24
25
/* maximal offset to read metadata block */
26
0
#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
0
#define FVAULT2_ENC_MD_PARSED_NONE 0b000
33
0
#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
0
#define FVAULT2_AES_KEY_SIZE 16
41
42
/* size of the volume key and the encrypted metadata decryption key */
43
0
#define FVAULT2_XTS_KEY_SIZE (FVAULT2_AES_KEY_SIZE * 2)
44
45
/* size of an XTS tweak value */
46
0
#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
0
{
157
0
  const uint8_t *data_bytes = data;
158
0
  size_t i;
159
160
0
  for (i = 0; i < data_size; i++)
161
0
    if (data_bytes[i] != value)
162
0
      return false;
163
164
0
  return true;
165
0
}
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
0
{
176
0
  const size_t crc_size = sizeof(struct crc32_checksum);
177
0
  uint32_t seed;
178
0
  uint32_t value;
179
180
0
  assert(data_size >= crc_size);
181
182
0
  value = le32_to_cpu(((const struct crc32_checksum *)data)->value);
183
0
  seed = le32_to_cpu(((const struct crc32_checksum *)data)->seed);
184
0
  if (seed != 0xffffffff)
185
0
    return -EINVAL;
186
187
0
  if (crypt_crc32c(seed, (const uint8_t *)data + crc_size,
188
0
      data_size - crc_size) != value)
189
0
    return -EINVAL;
190
191
0
  return 0;
192
0
}
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 = crypt_safe_alloc(16);
233
0
  if (cipher_in == NULL) {
234
0
    r = -ENOMEM;
235
0
    goto out;
236
0
  }
237
238
0
  cipher_out = crypt_safe_alloc(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
  crypt_safe_free(cipher_in);
287
0
  crypt_safe_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 >= FVAULT2_MD_BLOCK_SIZE ||
375
0
      xml_size > FVAULT2_MD_BLOCK_SIZE - xml_off)
376
0
    return -EINVAL;
377
378
0
  xml = strndup((const char *)md_block + xml_off, xml_size);
379
0
  if (xml == NULL)
380
0
    return -ENOMEM;
381
382
0
  r = _search_xml(xml, "PassphraseWrappedKEKStruct", "data", &pwk_base64);
383
0
  if (r < 0)
384
0
    goto out;
385
0
  r = crypt_base64_decode((char **)&pwk, &decoded_size, pwk_base64, strlen(pwk_base64));
386
0
  if (r < 0)
387
0
    goto out;
388
0
  if (decoded_size != FVAULT2_PWK_SIZE) {
389
0
    r = -EINVAL;
390
0
    goto out;
391
0
  }
392
393
0
  r = _search_xml(xml, "KEKWrappedVolumeKeyStruct", "data", &kwvk_base64);
394
0
  if (r < 0)
395
0
    goto out;
396
0
  r = crypt_base64_decode((char **)&kwvk, &decoded_size, kwvk_base64, strlen(kwvk_base64));
397
0
  if (r < 0)
398
0
    goto out;
399
0
  if (decoded_size != FVAULT2_KWVK_SIZE) {
400
0
    r = -EINVAL;
401
0
    goto out;
402
0
  }
403
404
0
  *pbkdf2_iters = le32_to_cpu(pwk->pbkdf2_iters);
405
0
  memcpy(pbkdf2_salt, pwk->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE);
406
0
  memcpy(wrapped_kek, pwk->wrapped_kek, FVAULT2_WRAPPED_KEY_SIZE);
407
0
  memcpy(wrapped_vk, kwvk->wrapped_vk, FVAULT2_WRAPPED_KEY_SIZE);
408
0
out:
409
0
  free(xml);
410
0
  free(pwk_base64);
411
0
  free(kwvk_base64);
412
0
  free(pwk);
413
0
  free(kwvk);
414
0
  return r;
415
0
}
416
417
/**
418
 * Validate a UUID string and reformat it to match system defaults.
419
 * @param[in] uuid_in the original UUID string
420
 * @param[out] uuid_out the reformatted UUID string
421
 */
422
static int _reformat_uuid(
423
  const char *uuid_in,
424
  char *uuid_out)
425
0
{
426
0
  uint8_t uuid_bin[FVAULT2_UUID_LEN];
427
0
  int r;
428
429
0
  r = uuid_parse(uuid_in, uuid_bin);
430
0
  if (r < 0)
431
0
    return -EINVAL;
432
433
0
  uuid_unparse(uuid_bin, uuid_out);
434
0
  return 0;
435
0
}
436
437
/**
438
 * Extract relevant info from a metadata block of type 0x001A.
439
 * @param[in] md_block the pre-read and decrypted metadata block
440
 * @param[out] log_vol_size encrypted logical volume size in bytes
441
 * @param[out] family_uuid logical volume family UUID
442
 */
443
static int _parse_metadata_block_0x001a(
444
  const struct metadata_block_0x001a *md_block,
445
  uint64_t *log_vol_size,
446
  char *family_uuid)
447
0
{
448
0
  int r = 0;
449
0
  char *xml = NULL;
450
0
  char *log_vol_size_str = NULL;
451
0
  char *family_uuid_str = NULL;
452
0
  uint32_t xml_off = le32_to_cpu(md_block->xml_off);
453
0
  uint32_t xml_size = le32_to_cpu(md_block->xml_size);
454
455
0
  if (xml_off >= FVAULT2_MD_BLOCK_SIZE ||
456
0
      xml_size > FVAULT2_MD_BLOCK_SIZE - xml_off)
457
0
    return -EINVAL;
458
459
0
  xml = strndup((const char *)md_block + xml_off, xml_size);
460
0
  if (xml == NULL)
461
0
    return -ENOMEM;
462
463
0
  r = _search_xml(xml, "com.apple.corestorage.lv.size", "integer", &log_vol_size_str);
464
0
  if (r < 0)
465
0
    goto out;
466
0
  *log_vol_size = strtoull(log_vol_size_str, NULL, 16);
467
0
  if (*log_vol_size == 0 || *log_vol_size == ULLONG_MAX) {
468
0
    r = -EINVAL;
469
0
    goto out;
470
0
  }
471
472
0
  r = _search_xml(xml, "com.apple.corestorage.lv.familyUUID", "string", &family_uuid_str);
473
0
  if (r < 0)
474
0
    goto out;
475
0
  r = _reformat_uuid(family_uuid_str, family_uuid);
476
0
  if (r < 0)
477
0
    goto out;
478
0
out:
479
0
  free(xml);
480
0
  free(log_vol_size_str);
481
0
  free(family_uuid_str);
482
0
  return r;
483
0
}
484
485
/**
486
 * Extract relevant info from a metadata block of type 0x0305.
487
 * @param[in] md_block the pre-read and decrypted metadata block
488
 * @param[out] log_vol_blkoff block-offset of the encrypted logical volume
489
 */
490
static int _parse_metadata_block_0x0305(
491
  const struct metadata_block_0x0305 *md_block,
492
  uint32_t *log_vol_blkoff)
493
0
{
494
0
  *log_vol_blkoff = le32_to_cpu(md_block->log_vol_blkoff);
495
0
  return 0;
496
0
}
497
498
/**
499
 * Extract relevant info from the physical volume header.
500
 * @param[in] devfd opened device file descriptor
501
 * @param[in] cd crypt_device passed into FVAULT2_read_metadata
502
 * @param[out] block_size used to compute byte-offsets from block-offsets
503
 * @param[out] disklbl_blkoff block-offset of the disk label block
504
 * @param[out] ph_vol_uuid physical volume UUID
505
 * @param[out] enc_md_key AES-XTS key used to decrypt the encrypted metadata
506
 */
507
static int _read_volume_header(
508
  int devfd,
509
  struct crypt_device *cd,
510
  uint64_t *block_size,
511
  uint64_t *disklbl_blkoff,
512
  char *ph_vol_uuid,
513
  struct volume_key **enc_md_key)
514
0
{
515
0
  int r = 0;
516
0
  struct device *dev = crypt_metadata_device(cd);
517
0
  struct volume_header *vol_header = NULL;
518
0
  void *enc_key = NULL;
519
520
0
  assert(sizeof(*vol_header) == FVAULT2_VOL_HEADER_SIZE);
521
522
0
  vol_header = malloc(FVAULT2_VOL_HEADER_SIZE);
523
0
  if (vol_header == NULL) {
524
0
    r = -ENOMEM;
525
0
    goto out;
526
0
  }
527
528
0
  log_dbg(cd, "Reading FVAULT2 volume header of size %u bytes.", FVAULT2_VOL_HEADER_SIZE);
529
0
  if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
530
0
      device_alignment(dev), vol_header,
531
0
      FVAULT2_VOL_HEADER_SIZE, 0) != FVAULT2_VOL_HEADER_SIZE) {
532
0
    log_err(cd, _("Could not read %u bytes of volume header."), FVAULT2_VOL_HEADER_SIZE);
533
0
    r = -EIO;
534
0
    goto out;
535
0
  }
536
537
0
  r = _check_crc(vol_header, FVAULT2_VOL_HEADER_SIZE);
538
0
  if (r < 0) {
539
0
    log_dbg(cd, "CRC mismatch.");
540
0
    goto out;
541
0
  }
542
543
0
  if (le16_to_cpu(vol_header->version) != 1) {
544
0
    log_err(cd, _("Unsupported FVAULT2 version %" PRIu16 "."),
545
0
      le16_to_cpu(vol_header->version));
546
0
    r = -EINVAL;
547
0
    goto out;
548
0
  }
549
550
0
  if (be16_to_cpu(vol_header->magic) != FVAULT2_CORE_STORAGE_MAGIC) {
551
0
    log_dbg(cd, "Invalid Core Storage magic bytes.");
552
0
    r = -EINVAL;
553
0
    goto out;
554
0
  }
555
556
0
  if (le32_to_cpu(vol_header->key_data_size) != FVAULT2_AES_KEY_SIZE) {
557
0
    log_dbg(cd, "Unsupported AES key size: %" PRIu32 " bytes.",
558
0
      le32_to_cpu(vol_header->key_data_size));
559
0
    r = -EINVAL;
560
0
    goto out;
561
0
  }
562
563
0
  enc_key = crypt_safe_alloc(FVAULT2_XTS_KEY_SIZE);
564
0
  if (!enc_key) {
565
0
    r = -ENOMEM;
566
0
    goto out;
567
0
  }
568
569
0
  *block_size = le32_to_cpu(vol_header->block_size);
570
0
  *disklbl_blkoff = le64_to_cpu(vol_header->disklbl_blkoff);
571
0
  uuid_unparse(vol_header->ph_vol_uuid, ph_vol_uuid);
572
0
  crypt_safe_memcpy(enc_key, vol_header->key_data, FVAULT2_AES_KEY_SIZE);
573
0
  crypt_safe_memcpy((char *)enc_key + FVAULT2_AES_KEY_SIZE,
574
0
    vol_header->ph_vol_uuid, FVAULT2_AES_KEY_SIZE);
575
576
0
  *enc_md_key = crypt_alloc_volume_key_by_safe_alloc(&enc_key);
577
0
  if (*enc_md_key == NULL) {
578
0
    crypt_safe_free(enc_key);
579
0
    r = -ENOMEM;
580
0
  }
581
0
out:
582
0
  free(vol_header);
583
0
  return r;
584
0
}
585
586
/**
587
 * Extract info from the disk label block and the volume groups descriptor.
588
 * @param[in] devfd opened device file descriptor
589
 * @param[in] cd crypt_device passed into FVAULT2_read_metadata
590
 * @param[in] block_size used to compute byte-offsets from block-offsets
591
 * @param[in] disklbl_blkoff block-offset of the disk label block
592
 * @param[out] enc_md_blkoff block-offset of the encrypted metadata
593
 * @param[out] enc_md_blocks_n total count of encrypted metadata blocks
594
 */
595
static int _read_disklabel(
596
  int devfd,
597
  struct crypt_device *cd,
598
  uint64_t block_size,
599
  uint64_t disklbl_blkoff,
600
  uint64_t *enc_md_blkoff,
601
  uint64_t *enc_md_blocks_n)
602
0
{
603
0
  int r = 0;
604
0
  uint64_t off;
605
0
  ssize_t size;
606
0
  void *md_block = NULL;
607
0
  struct metadata_block_0x0011 *md_block_11;
608
0
  struct volume_groups_descriptor *vol_gr_des = NULL;
609
0
  struct device *dev = crypt_metadata_device(cd);
610
611
0
  md_block = malloc(FVAULT2_MD_BLOCK_SIZE);
612
0
  if (md_block == NULL) {
613
0
    r = -ENOMEM;
614
0
    goto out;
615
0
  }
616
617
0
  if (uint64_mult_overflow(&off, disklbl_blkoff, block_size) ||
618
0
      off > FVAULT2_MAX_OFF) {
619
0
    log_dbg(cd, "Device offset overflow.");
620
0
    r = -EINVAL;
621
0
    goto out;
622
0
  }
623
0
  size = FVAULT2_MD_BLOCK_SIZE;
624
0
  log_dbg(cd, "Reading FVAULT2 disk label header of size %zu bytes.", size);
625
0
  if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
626
0
      device_alignment(dev), md_block, size, off) != size) {
627
0
    r = -EIO;
628
0
    goto out;
629
0
  }
630
631
0
  r = _check_crc(md_block, FVAULT2_MD_BLOCK_SIZE);
632
0
  if (r < 0) {
633
0
    log_dbg(cd, "CRC mismatch.");
634
0
    goto out;
635
0
  }
636
637
0
  vol_gr_des = malloc(sizeof(*vol_gr_des));
638
0
  if (vol_gr_des == NULL) {
639
0
    r = -ENOMEM;
640
0
    goto out;
641
0
  }
642
643
0
  md_block_11 = md_block;
644
0
  off += le32_to_cpu(md_block_11->vol_gr_des_off);
645
0
  if (off > FVAULT2_MAX_OFF) {
646
0
    log_dbg(cd, "Device offset overflow.");
647
0
    r = -EINVAL;
648
0
    goto out;
649
0
  }
650
0
  size = sizeof(struct volume_groups_descriptor);
651
0
  log_dbg(cd, "Reading FVAULT2 volume groups descriptor of size %zu bytes.", size);
652
0
  if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
653
0
      device_alignment(dev), vol_gr_des, size, off) != size) {
654
0
    r = -EIO;
655
0
    goto out;
656
0
  }
657
658
0
  *enc_md_blkoff = le64_to_cpu(vol_gr_des->enc_md_blkoff);
659
0
  *enc_md_blocks_n = le64_to_cpu(vol_gr_des->enc_md_blocks_n);
660
0
out:
661
0
  free(md_block);
662
0
  free(vol_gr_des);
663
0
  return r;
664
0
}
665
666
/**
667
 * Extract info from relevant encrypted metadata blocks.
668
 * @param[in] devfd opened device file descriptor
669
 * @param[in] cd crypt_device passed into FVAULT2_read_metadata
670
 * @param[in] block_size used to compute byte-offsets from block-offsets
671
 * @param[in] start_blkoff block-offset of the start of the encrypted metadata
672
 * @param[in] blocks_n total count of encrypted metadata blocks
673
 * @param[in] key AES-XTS key for decryption
674
 * @param[out] params decryption parameters struct to fill
675
 */
676
static int _read_encrypted_metadata(
677
  int devfd,
678
  struct crypt_device *cd,
679
  uint64_t block_size,
680
  uint64_t start_blkoff,
681
  uint64_t blocks_n,
682
  const struct volume_key *key,
683
  struct fvault2_params *params)
684
0
{
685
0
  int r = 0;
686
0
  int status = FVAULT2_ENC_MD_PARSED_NONE;
687
0
  struct device *dev = crypt_metadata_device(cd);
688
0
  struct crypt_cipher *cipher = NULL;
689
0
  void *tweak;
690
0
  void *md_block_enc = NULL;
691
0
  void *md_block = NULL;
692
0
  struct metadata_block_header *md_block_header;
693
0
  uint32_t log_vol_blkoff;
694
0
  uint64_t i, start_off;
695
0
  off_t off;
696
0
  unsigned int block_type;
697
698
0
  tweak = calloc(FVAULT2_XTS_TWEAK_SIZE, 1);
699
0
  if (tweak == NULL) {
700
0
    r = -ENOMEM;
701
0
    goto out;
702
0
  }
703
704
0
  md_block_enc = malloc(FVAULT2_MD_BLOCK_SIZE);
705
0
  if (md_block_enc == NULL) {
706
0
    r = -ENOMEM;
707
0
    goto out;
708
0
  }
709
710
0
  md_block = malloc(FVAULT2_MD_BLOCK_SIZE);
711
0
  if (md_block == NULL) {
712
0
    r = -ENOMEM;
713
0
    goto out;
714
0
  }
715
716
0
  r = crypt_cipher_init(&cipher, "aes", "xts", crypt_volume_key_get_key(key), FVAULT2_XTS_KEY_SIZE);
717
0
  if (r < 0)
718
0
    goto out;
719
720
0
  if (uint64_mult_overflow(&start_off, start_blkoff, block_size) ||
721
0
      start_off > FVAULT2_MAX_OFF) {
722
0
    log_dbg(cd, "Device offset overflow.");
723
0
    r = -EINVAL;
724
0
    goto out;
725
0
  }
726
727
0
  log_dbg(cd, "Reading FVAULT2 encrypted metadata blocks.");
728
0
  for (i = 0; i < blocks_n; i++) {
729
0
    off = start_off + i * FVAULT2_MD_BLOCK_SIZE;
730
0
    if (off > FVAULT2_MAX_OFF) {
731
0
      log_dbg(cd, "Device offset overflow.");
732
0
      r = -EINVAL;
733
0
      goto out;
734
0
    }
735
0
    if (read_lseek_blockwise(devfd, device_block_size(cd, dev),
736
0
        device_alignment(dev), md_block_enc,
737
0
        FVAULT2_MD_BLOCK_SIZE, off)
738
0
        != FVAULT2_MD_BLOCK_SIZE) {
739
0
      r = -EIO;
740
0
      goto out;
741
0
    }
742
743
0
    if (_filled_with(0, md_block_enc, FVAULT2_MD_BLOCK_SIZE))
744
0
      break;
745
746
0
    *(uint64_t *)tweak = cpu_to_le64(i);
747
0
    r = crypt_cipher_decrypt(cipher, md_block_enc, md_block,
748
0
      FVAULT2_MD_BLOCK_SIZE, tweak, FVAULT2_XTS_TWEAK_SIZE);
749
0
    if (r < 0)
750
0
      goto out;
751
752
0
    r = _check_crc(md_block, FVAULT2_MD_BLOCK_SIZE);
753
0
    if (r < 0) {
754
0
      log_dbg(cd, "CRC mismatch.");
755
0
      goto out;
756
0
    }
757
758
0
    md_block_header = md_block;
759
0
    block_type = le16_to_cpu(md_block_header->block_type);
760
0
    switch (block_type) {
761
0
    case 0x0019:
762
0
      log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x0019.", i);
763
0
      r = _parse_metadata_block_0x0019(md_block,
764
0
        &params->pbkdf2_iters,
765
0
        (uint8_t *)params->pbkdf2_salt,
766
0
        (uint8_t *)params->wrapped_kek,
767
0
        (uint8_t *)params->wrapped_vk);
768
0
      if (r < 0)
769
0
        goto out;
770
0
      status |= FVAULT2_ENC_MD_PARSED_0x0019;
771
0
      break;
772
773
0
    case 0x001A:
774
0
      log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x001A.", i);
775
0
      r = _parse_metadata_block_0x001a(md_block,
776
0
        &params->log_vol_size,
777
0
        params->family_uuid);
778
0
      if (r < 0)
779
0
        goto out;
780
0
      status |= FVAULT2_ENC_MD_PARSED_0x001A;
781
0
      break;
782
783
0
    case 0x0305:
784
0
      log_dbg(cd, "Get FVAULT2 metadata block %" PRIu64 " type 0x0305.", i);
785
0
      r = _parse_metadata_block_0x0305(md_block,
786
0
        &log_vol_blkoff);
787
0
      if (r < 0)
788
0
        goto out;
789
0
      if (uint64_mult_overflow(&params->log_vol_off,
790
0
          log_vol_blkoff, block_size)) {
791
0
        log_dbg(cd, "Device offset overflow.");
792
0
        r = -EINVAL;
793
0
        goto out;
794
0
      }
795
0
      status |= FVAULT2_ENC_MD_PARSED_0x0305;
796
0
      break;
797
0
    }
798
0
  }
799
800
0
  if (status != FVAULT2_ENC_MD_PARSED_ALL) {
801
0
    log_dbg(cd, "Necessary FVAULT2 metadata blocks not found.");
802
0
    r = -EINVAL;
803
0
    goto out;
804
0
  }
805
0
out:
806
0
  free(tweak);
807
0
  free(md_block_enc);
808
0
  free(md_block);
809
0
  if (cipher != NULL)
810
0
    crypt_cipher_destroy(cipher);
811
0
  return r;
812
0
}
813
814
/**
815
 * Activate device.
816
 * @param[in] cd crypt_device struct passed into FVAULT2_activate_by_*
817
 * @param[in] name name of the mapped device
818
 * @param[in] vol_key the pre-derived AES-XTS volume key
819
 * @param[in] params logical volume decryption parameters
820
 * @param[in] flags flags assigned to the crypt_dm_active_device struct
821
 */
822
static int _activate(
823
  struct crypt_device *cd,
824
  const char *name,
825
  struct volume_key *vol_key,
826
  const struct fvault2_params *params,
827
  uint32_t flags)
828
0
{
829
0
  int r = 0;
830
0
  char *cipher = NULL;
831
0
  struct crypt_dm_active_device dm_dev = {
832
0
    .flags = flags,
833
0
    .size = params->log_vol_size / SECTOR_SIZE
834
0
  };
835
836
0
  r = device_block_adjust(cd, crypt_data_device(cd), DEV_EXCL,
837
0
    crypt_get_data_offset(cd), &dm_dev.size, &dm_dev.flags);
838
0
  if (r)
839
0
    return r;
840
841
0
  if (asprintf(&cipher, "%s-%s", params->cipher, params->cipher_mode) < 0)
842
0
    return -ENOMEM;
843
844
0
  r = dm_crypt_target_set(&dm_dev.segment, 0, dm_dev.size,
845
0
    crypt_data_device(cd), vol_key, cipher,
846
0
    crypt_get_iv_offset(cd), crypt_get_data_offset(cd),
847
0
    NULL, 0, 0, crypt_get_sector_size(cd));
848
849
0
  if (!r)
850
0
    r = dm_create_device(cd, name, CRYPT_FVAULT2, &dm_dev);
851
852
0
  dm_targets_free(cd, &dm_dev);
853
0
  free(cipher);
854
0
  return r;
855
0
}
856
857
int FVAULT2_read_metadata(
858
  struct crypt_device *cd,
859
  struct fvault2_params *params)
860
0
{
861
0
  int r = 0;
862
0
  int devfd;
863
0
  uint64_t block_size;
864
0
  uint64_t disklbl_blkoff;
865
0
  uint64_t enc_md_blkoff;
866
0
  uint64_t enc_md_blocks_n;
867
0
  struct volume_key *enc_md_key = NULL;
868
0
  struct device *device = crypt_metadata_device(cd);
869
870
0
  devfd = device_open(cd, device, O_RDONLY);
871
0
  if (devfd < 0) {
872
0
    log_err(cd, _("Cannot open device %s."), device_path(device));
873
0
    return -EIO;
874
0
  }
875
876
0
  r = _read_volume_header(devfd, cd, &block_size, &disklbl_blkoff,
877
0
    params->ph_vol_uuid, &enc_md_key);
878
0
  if (r < 0)
879
0
    goto out;
880
881
0
  r = _read_disklabel(devfd, cd, block_size, disklbl_blkoff,
882
0
    &enc_md_blkoff, &enc_md_blocks_n);
883
0
  if (r < 0)
884
0
    goto out;
885
886
0
  r = _read_encrypted_metadata(devfd, cd, block_size, enc_md_blkoff,
887
0
    enc_md_blocks_n, enc_md_key, params);
888
0
  if (r < 0)
889
0
    goto out;
890
891
0
  params->cipher = "aes";
892
0
  params->cipher_mode = "xts-plain64";
893
0
  params->key_size = FVAULT2_XTS_KEY_SIZE;
894
0
out:
895
0
  crypt_free_volume_key(enc_md_key);
896
0
  return r;
897
0
}
898
899
int FVAULT2_get_volume_key(
900
  struct crypt_device *cd,
901
  const char *passphrase,
902
  size_t passphrase_len,
903
  const struct fvault2_params *params,
904
  struct volume_key **r_vol_key)
905
0
{
906
0
  int r = 0;
907
0
  uint8_t family_uuid_bin[FVAULT2_UUID_BIN_SIZE];
908
0
  struct crypt_hash *hash = NULL;
909
0
  void *passphrase_key = NULL, *kek = NULL, *vol_key= NULL;
910
911
0
  *r_vol_key = NULL;
912
913
0
  if (uuid_parse(params->family_uuid, family_uuid_bin) < 0) {
914
0
    log_dbg(cd, "Could not parse logical volume family UUID: %s.",
915
0
      params->family_uuid);
916
0
    r = -EINVAL;
917
0
    goto out;
918
0
  }
919
920
0
  passphrase_key = crypt_safe_alloc(FVAULT2_AES_KEY_SIZE);
921
0
  if (passphrase_key == NULL) {
922
0
    r = -ENOMEM;
923
0
    goto out;
924
0
  }
925
926
0
  r = crypt_pbkdf("pbkdf2", "sha256", passphrase, passphrase_len,
927
0
    params->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE, passphrase_key,
928
0
    FVAULT2_AES_KEY_SIZE, params->pbkdf2_iters, 0, 0);
929
0
  if (r < 0)
930
0
    goto out;
931
932
0
  kek = crypt_safe_alloc(FVAULT2_AES_KEY_SIZE);
933
0
  if (kek == NULL) {
934
0
    r = -ENOMEM;
935
0
    goto out;
936
0
  }
937
938
0
  r = _unwrap_key(passphrase_key, FVAULT2_AES_KEY_SIZE, params->wrapped_kek,
939
0
      FVAULT2_WRAPPED_KEY_SIZE, kek, FVAULT2_AES_KEY_SIZE);
940
0
  if (r < 0)
941
0
    goto out;
942
943
0
  vol_key = crypt_safe_alloc(FVAULT2_XTS_KEY_SIZE);
944
0
  if (vol_key == NULL) {
945
0
    r = -ENOMEM;
946
0
    goto out;
947
0
  }
948
949
0
  r = _unwrap_key(kek, FVAULT2_AES_KEY_SIZE, params->wrapped_vk,
950
0
    FVAULT2_WRAPPED_KEY_SIZE, vol_key, FVAULT2_AES_KEY_SIZE);
951
0
  if (r < 0)
952
0
    goto out;
953
954
0
  r = crypt_hash_init(&hash, "sha256");
955
0
  if (r < 0)
956
0
    goto out;
957
0
  r = crypt_hash_write(hash, vol_key, FVAULT2_AES_KEY_SIZE);
958
0
  if (r < 0)
959
0
    goto out;
960
0
  r = crypt_hash_write(hash, (char *)family_uuid_bin,
961
0
    FVAULT2_UUID_BIN_SIZE);
962
0
  if (r < 0)
963
0
    goto out;
964
0
  r = crypt_hash_final(hash, (char *)vol_key + FVAULT2_AES_KEY_SIZE,
965
0
    FVAULT2_AES_KEY_SIZE);
966
0
  if (r < 0)
967
0
    goto out;
968
969
0
  *r_vol_key = crypt_alloc_volume_key_by_safe_alloc(&vol_key);
970
0
  if (!*r_vol_key)
971
0
    r = -ENOMEM;
972
0
out:
973
0
  crypt_safe_free(passphrase_key);
974
0
  crypt_safe_free(kek);
975
0
  crypt_safe_free(vol_key);
976
0
  if (hash != NULL)
977
0
    crypt_hash_destroy(hash);
978
0
  return r;
979
0
}
980
981
int FVAULT2_dump(
982
  struct crypt_device *cd,
983
  struct device *device,
984
  const struct fvault2_params *params)
985
0
{
986
0
  log_std(cd, "Header information for FVAULT2 device %s.\n", device_path(device));
987
988
0
  log_std(cd, "Physical volume UUID: \t%s\n", params->ph_vol_uuid);
989
0
  log_std(cd, "Family UUID:          \t%s\n", params->family_uuid);
990
991
0
  log_std(cd, "Logical volume offset:\t%" PRIu64 " [bytes]\n", params->log_vol_off);
992
993
0
  log_std(cd, "Logical volume size:  \t%" PRIu64 " [bytes]\n",
994
0
    params->log_vol_size);
995
996
0
  log_std(cd, "Cipher:               \t%s\n", params->cipher);
997
0
  log_std(cd, "Cipher mode:          \t%s\n", params->cipher_mode);
998
999
0
  log_std(cd, "PBKDF2 iterations:    \t%" PRIu32 "\n", params->pbkdf2_iters);
1000
1001
0
  log_std(cd, "PBKDF2 salt:          \t");
1002
0
  crypt_log_hex(cd, params->pbkdf2_salt, FVAULT2_PBKDF2_SALT_SIZE, " ", 0, NULL);
1003
0
  log_std(cd, "\n");
1004
1005
0
  return 0;
1006
0
}
1007
1008
int FVAULT2_activate_by_volume_key(
1009
  struct crypt_device *cd,
1010
  const char *name,
1011
  struct volume_key *vk,
1012
  const struct fvault2_params *params,
1013
  uint32_t flags)
1014
0
{
1015
0
  assert(crypt_volume_key_length(vk) == FVAULT2_XTS_KEY_SIZE);
1016
1017
0
  return _activate(cd, name, vk, params, flags);
1018
0
}
1019
1020
size_t FVAULT2_volume_key_size(void)
1021
0
{
1022
0
  return FVAULT2_XTS_KEY_SIZE;
1023
0
}