Coverage Report

Created: 2025-11-11 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/util-linux/libblkid/src/superblocks/cs_fvault2.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2022 Milan Broz <gmazyland@gmail.com>
3
 *
4
 * This file may be redistributed under the terms of the
5
 * GNU Lesser General Public License.
6
 */
7
8
#include "superblocks.h"
9
#include "crc32c.h"
10
11
/*
12
 * For header details, see:
13
 * https://github.com/libyal/libfvde/blob/main/documentation/FileVault%20Drive%20Encryption%20(FVDE).asciidoc
14
 * https://is.muni.cz/auth/th/p0aok/thesis.pdf
15
 */
16
17
/* Apple Core Storage magic bytes */
18
#define CS_MAGIC  "CS"
19
20
struct crc32_checksum {
21
  uint32_t value;
22
  uint32_t seed;
23
} __attribute__((packed));
24
25
/*
26
 * The superblock structure describes "physical volume"; Core Storage
27
 * then uses another abstractions above, similar to LVM.
28
 * After activation through dm-crypt, filesystem (usually HFS+) is on top.
29
 * The filesystem block size and used data size cannot be directly derived from
30
 * this superblock structure without parsing other metadata blocks.
31
 */
32
33
struct cs_fvault2_sb {
34
  struct crc32_checksum checksum;
35
  uint16_t version;
36
  uint16_t block_type;
37
  uint8_t unknown1[52];
38
  uint64_t ph_vol_size;
39
  uint8_t unknown2[16];
40
  uint16_t magic;
41
  uint32_t checksum_algo;
42
  uint8_t unknown3[2];
43
  uint32_t block_size;
44
  uint32_t metadata_size;
45
  uint64_t disklbl_blkoff;
46
  uint64_t other_md_blkoffs[3];
47
  uint8_t unknown4[32];
48
  uint32_t key_data_size;
49
  uint32_t cipher;
50
  uint8_t key_data[16];
51
  uint8_t unknown5[112];
52
  uint8_t ph_vol_uuid[16];
53
  uint8_t unknown6[192];
54
} __attribute__((packed));
55
56
static int cs_fvault2_verify_csum(blkid_probe pr, const struct cs_fvault2_sb *sb)
57
8
{
58
8
  uint32_t seed = le32_to_cpu(sb->checksum.seed);
59
8
  uint32_t crc = le32_to_cpu(sb->checksum.value);
60
8
  unsigned char *buf = (unsigned char *)sb + sizeof(sb->checksum);
61
8
  size_t buf_size = sizeof(*sb) - sizeof(sb->checksum);
62
63
8
  return blkid_probe_verify_csum(pr, crc32c(seed, buf, buf_size), crc);
64
8
}
65
66
static int probe_cs_fvault2(blkid_probe pr, const struct blkid_idmag *mag)
67
1.40k
{
68
1.40k
  const struct cs_fvault2_sb *sb;
69
70
1.40k
  sb = blkid_probe_get_sb(pr, mag, struct cs_fvault2_sb);
71
1.40k
  if (!sb)
72
0
    return errno ? -errno : BLKID_PROBE_NONE;
73
74
  /* Apple Core storage Physical Volume Header; only type 1 checksum is supported  */
75
1.40k
  if (le16_to_cpu(sb->version) != 1 ||
76
226
      le32_to_cpu(sb->checksum_algo) != 1)
77
1.39k
    return BLKID_PROBE_NONE;
78
79
8
  if (!cs_fvault2_verify_csum(pr, sb))
80
8
    return BLKID_PROBE_NONE;
81
82
  /* We support only block type 0x10 as it should be used for FileVault2 */
83
0
  if (le16_to_cpu(sb->block_type) != 0x10 ||
84
0
      le32_to_cpu(sb->key_data_size) != 16 ||
85
0
      le32_to_cpu(sb->cipher) != 2 /* AES-XTS */)
86
0
    return BLKID_PROBE_NONE;
87
88
0
  blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(sb->version));
89
0
  blkid_probe_set_uuid(pr, sb->ph_vol_uuid);
90
91
0
  return BLKID_PROBE_OK;
92
0
}
93
94
const struct blkid_idinfo cs_fvault2_idinfo =
95
{
96
  .name   = "cs_fvault2",
97
  .usage    = BLKID_USAGE_CRYPTO,
98
  .probefunc  = probe_cs_fvault2,
99
  .magics   =
100
  {
101
    { .magic = CS_MAGIC, .len = 2, .sboff = 88 },
102
    { NULL }
103
  }
104
};