]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - libblkid/src/superblocks/luks.c
0230b349267081966641122a0dbbecc57df47e6d
2 * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3 * Copyright (C) 2018 Milan Broz <gmazyland@gmail.com>
5 * Inspired by libvolume_id by
6 * Kay Sievers <kay.sievers@vrfy.org>
8 * This file may be redistributed under the terms of the
9 * GNU Lesser General Public License.
19 #include "superblocks.h"
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
33 #define LUKS_MAGIC "LUKS\xba\xbe"
34 #define LUKS_MAGIC_2 "SKUL\xba\xbe"
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 }
40 static const uint64_t secondary_offsets
[] = LUKS2_HDR2_OFFSETS
;
43 uint8_t magic
[LUKS_MAGIC_L
];
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
;
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
));
57 char magic
[LUKS_MAGIC_L
];
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 */
68 uint8_t csum
[LUKS2_CHECKSUM_L
];
69 /* Padding to 4k, then JSON area */
70 } __attribute__ ((packed
));
72 static int luks_attributes(blkid_probe pr
, struct luks2_phdr
*header
, uint64_t offset
)
75 struct luks_phdr
*header_v1
;
77 if (blkid_probe_set_magic(pr
, offset
, LUKS_MAGIC_L
, (unsigned char *) &header
->magic
))
78 return BLKID_PROBE_NONE
;
80 version
= be16_to_cpu(header
->version
);
81 blkid_probe_sprintf_version(pr
, "%u", version
);
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
);
96 return BLKID_PROBE_OK
;
99 static int probe_luks(blkid_probe pr
, const struct blkid_idmag
*mag
__attribute__((__unused__
)))
101 struct luks2_phdr
*header
;
104 header
= (struct luks2_phdr
*) blkid_probe_get_buffer(pr
, 0, sizeof(struct luks2_phdr
));
106 return errno
? -errno
: BLKID_PROBE_NONE
;
108 if (!memcmp(header
->magic
, LUKS_MAGIC
, LUKS_MAGIC_L
)) {
109 /* LUKS primary header was found. */
110 return luks_attributes(pr
, header
, 0);
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
));
119 return errno
? -errno
: BLKID_PROBE_NONE
;
121 if (!memcmp(header
->magic
, LUKS_MAGIC_2
, LUKS_MAGIC_L
))
122 return luks_attributes(pr
, header
, secondary_offsets
[i
]);
125 return BLKID_PROBE_NONE
;
128 const struct blkid_idinfo luks_idinfo
=
130 .name
= "crypto_LUKS",
131 .usage
= BLKID_USAGE_CRYPTO
,
132 .probefunc
= probe_luks
,
133 .magics
= BLKID_NONE_MAGIC