]> git.ipfire.org Git - thirdparty/util-linux.git/blob - libblkid/src/superblocks/luks.c
0230b349267081966641122a0dbbecc57df47e6d
[thirdparty/util-linux.git] / libblkid / src / superblocks / luks.c
1 /*
2 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3 * Copyright (C) 2018 Milan Broz <gmazyland@gmail.com>
4 *
5 * Inspired by libvolume_id by
6 * Kay Sievers <kay.sievers@vrfy.org>
7 *
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <ctype.h>
17 #include <stdint.h>
18
19 #include "superblocks.h"
20
21 #define LUKS_CIPHERNAME_L 32
22 #define LUKS_CIPHERMODE_L 32
23 #define LUKS_HASHSPEC_L 32
24 #define LUKS_DIGESTSIZE 20
25 #define LUKS_SALTSIZE 32
26 #define LUKS_MAGIC_L 6
27 #define UUID_STRING_L 40
28 #define LUKS2_LABEL_L 48
29 #define LUKS2_SALT_L 64
30 #define LUKS2_CHECKSUM_ALG_L 32
31 #define LUKS2_CHECKSUM_L 64
32
33 #define LUKS_MAGIC "LUKS\xba\xbe"
34 #define LUKS_MAGIC_2 "SKUL\xba\xbe"
35
36 /* Offsets for secondary header (for scan if primary header is corrupted). */
37 #define LUKS2_HDR2_OFFSETS { 0x04000, 0x008000, 0x010000, 0x020000, \
38 0x40000, 0x080000, 0x100000, 0x200000, 0x400000 }
39
40 static const uint64_t secondary_offsets[] = LUKS2_HDR2_OFFSETS;
41
42 struct luks_phdr {
43 uint8_t magic[LUKS_MAGIC_L];
44 uint16_t version;
45 uint8_t cipherName[LUKS_CIPHERNAME_L];
46 uint8_t cipherMode[LUKS_CIPHERMODE_L];
47 uint8_t hashSpec[LUKS_HASHSPEC_L];
48 uint32_t payloadOffset;
49 uint32_t keyBytes;
50 uint8_t mkDigest[LUKS_DIGESTSIZE];
51 uint8_t mkDigestSalt[LUKS_SALTSIZE];
52 uint32_t mkDigestIterations;
53 uint8_t uuid[UUID_STRING_L];
54 } __attribute__((packed));
55
56 struct luks2_phdr {
57 char magic[LUKS_MAGIC_L];
58 uint16_t version;
59 uint64_t hdr_size; /* in bytes, including JSON area */
60 uint64_t seqid; /* increased on every update */
61 char label[LUKS2_LABEL_L];
62 char checksum_alg[LUKS2_CHECKSUM_ALG_L];
63 uint8_t salt[LUKS2_SALT_L]; /* unique for every header/offset */
64 char uuid[UUID_STRING_L];
65 char subsystem[LUKS2_LABEL_L]; /* owner subsystem label */
66 uint64_t hdr_offset; /* offset from device start in bytes */
67 char _padding[184];
68 uint8_t csum[LUKS2_CHECKSUM_L];
69 /* Padding to 4k, then JSON area */
70 } __attribute__ ((packed));
71
72 static int luks_attributes(blkid_probe pr, struct luks2_phdr *header, uint64_t offset)
73 {
74 int version;
75 struct luks_phdr *header_v1;
76
77 if (blkid_probe_set_magic(pr, offset, LUKS_MAGIC_L, (unsigned char *) &header->magic))
78 return BLKID_PROBE_NONE;
79
80 version = be16_to_cpu(header->version);
81 blkid_probe_sprintf_version(pr, "%u", version);
82
83 if (version == 1) {
84 header_v1 = (struct luks_phdr *)header;
85 blkid_probe_strncpy_uuid(pr,
86 (unsigned char *) header_v1->uuid, UUID_STRING_L);
87 } else if (version == 2) {
88 blkid_probe_strncpy_uuid(pr,
89 (unsigned char *) header->uuid, UUID_STRING_L);
90 blkid_probe_set_label(pr,
91 (unsigned char *) header->label, LUKS2_LABEL_L);
92 blkid_probe_set_id_label(pr, "SUBSYSTEM",
93 (unsigned char *) header->subsystem, LUKS2_LABEL_L);
94 }
95
96 return BLKID_PROBE_OK;
97 }
98
99 static int probe_luks(blkid_probe pr, const struct blkid_idmag *mag __attribute__((__unused__)))
100 {
101 struct luks2_phdr *header;
102 size_t i;
103
104 header = (struct luks2_phdr *) blkid_probe_get_buffer(pr, 0, sizeof(struct luks2_phdr));
105 if (!header)
106 return errno ? -errno : BLKID_PROBE_NONE;
107
108 if (!memcmp(header->magic, LUKS_MAGIC, LUKS_MAGIC_L)) {
109 /* LUKS primary header was found. */
110 return luks_attributes(pr, header, 0);
111 }
112
113 /* No primary header, scan for known offsets of LUKS2 secondary header. */
114 for (i = 0; i < ARRAY_SIZE(secondary_offsets); i++) {
115 header = (struct luks2_phdr *) blkid_probe_get_buffer(pr,
116 secondary_offsets[i], sizeof(struct luks2_phdr));
117
118 if (!header)
119 return errno ? -errno : BLKID_PROBE_NONE;
120
121 if (!memcmp(header->magic, LUKS_MAGIC_2, LUKS_MAGIC_L))
122 return luks_attributes(pr, header, secondary_offsets[i]);
123 }
124
125 return BLKID_PROBE_NONE;
126 }
127
128 const struct blkid_idinfo luks_idinfo =
129 {
130 .name = "crypto_LUKS",
131 .usage = BLKID_USAGE_CRYPTO,
132 .probefunc = probe_luks,
133 .magics = BLKID_NONE_MAGIC
134 };