2 * LUKS keyslot entropy tester. Works only for header version 1.
4 * Functionality: Determines sample entropy (symbols: bytes) for
5 * each (by default) 512B sector in each used keyslot. If it
6 * is lower than a threshold, the sector address is printed
7 * as it is suspected of having non-"random" data in it, indicating
8 * damage by overwriting. This can obviously not find overwriting
9 * with random or random-like data (encrypted, compressed).
12 * v0.1: 09.09.2012 Initial release
13 * v0.2: 08.10.2012 Converted to use libcryptsetup
15 * Copyright (C) 2012, Arno Wagner <arno@wagner.name>
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
39 #include <libcryptsetup.h>
42 "Version 0.2 [8.10.2012]\n"
44 " chk_luks_keyslots [options] luks-device \n"
46 "This tool checks all keyslots of a LUKS device for \n"
47 "low entropy sections. If any are found, they are reported. \n"
48 "This allows to find areas damaged by things like filesystem \n"
49 "creation or RAID superblocks. \n"
52 " -t <num> Entropy threshold. Possible values 0.0 ... 1.0 \n"
53 " Default: 0.90, which works well for 512B sectors.\n"
54 " For 512B sectors, you will get frequent misdetections\n"
55 " at thresholds around 0.94\n"
56 " Higher value: more sensitive but more false detections.\n"
57 " -s <num> Sector size. Must divide keyslot-size.\n"
58 " Default: 512 Bytes.\n"
59 " Values smaller than 128 are generally not very useful.\n"
60 " For values smaller than the default, you need to adjust\n"
61 " the threshold down to reduce misdetection. For values\n"
62 " larger than the default you need to adjust the threshold\n"
63 " up to retain sensitivity.\n"
64 " -v Print found suspicious sectors verbosely. \n"
65 " -d Print decimal addresses instead of hex ones.\n"
71 static int sector_size = 512;
72 static double threshold = 0.90;
73 static int print_decimal = 0;
74 static int verbose = 0;
78 /* Calculates and returns sample entropy on byte level for
81 static double ent_samp(unsigned char * buf, int len)
83 int freq[256]; /* stores symbol frequencies */
87 /* 0. Plausibility checks */
91 /* 1. count all frequencies */
92 for (i = 0; i < 256; i++) {
96 for (i = 0; i < len; i ++)
99 /* 2. calculate sample entropy */
101 for (i = 0; i < 256; i++) {
116 static void print_address(FILE *out, uint64_t value)
119 fprintf(out,"%08" PRIu64 " ", value);
121 fprintf(out,"%#08" PRIx64 " ", value);
125 /* uses default "hd" style, i.e. 16 bytes followed by ASCII */
126 static void hexdump_line(FILE *out, uint64_t address, unsigned char *buf) {
128 static char tbl[16] = "0123456789ABCDEF";
131 print_address(out, address);
135 for (i = 0; i < 16; i++) {
137 tbl[(unsigned char)buf[i]>> 4],
138 tbl[(unsigned char)buf[i] & 0x0f]);
147 for (i = 0; i < 16; i++) {
148 if (isprint(buf[i])) {
149 fprintf(out, "%c", buf[i]);
157 static void hexdump_sector(FILE *out, unsigned char *buf, uint64_t address, int len)
162 while (len - done >= 16) {
163 hexdump_line(out, address + done, buf + done);
168 static int check_keyslots(FILE *out, struct crypt_device *cd, int f_luks)
173 uint64_t start, length, end;
174 crypt_keyslot_info ki;
175 unsigned char buffer[sector_size];
177 for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1) ; i++) {
178 fprintf(out, "- processing keyslot %d:", i);
179 ki = crypt_keyslot_status(cd, i);
180 if (ki == CRYPT_SLOT_INACTIVE) {
181 fprintf(out, " keyslot not in use\n");
185 if (ki == CRYPT_SLOT_INVALID) {
186 fprintf(out, "\nError: keyslot invalid.\n");
190 if (crypt_keyslot_area(cd, i, &start, &length) < 0) {
191 fprintf(stderr,"\nError: querying keyslot area failed for slot %d\n", i);
195 end = start + length;
197 fprintf(out, " start: ");
198 print_address(out, start);
199 fprintf(out, " end: ");
200 print_address(out, end);
203 /* check whether sector-size divides size */
204 if (length % sector_size != 0) {
205 fprintf(stderr,"\nError: Argument to -s does not divide keyslot size\n");
209 for (ofs = start; (uint64_t)ofs < end; ofs += sector_size) {
210 if (lseek(f_luks, ofs, SEEK_SET) != ofs) {
211 fprintf(stderr,"\nCannot seek to keyslot area.\n");
214 if (read(f_luks, buffer, sector_size) != sector_size) {
215 fprintf(stderr,"\nCannot read keyslot area.\n");
218 ent = ent_samp(buffer, sector_size);
219 if (ent < threshold) {
220 fprintf(out, " low entropy at: ");
221 print_address(out, ofs);
222 fprintf(out, " entropy: %f\n", ent);
224 fprintf(out, " Binary dump:\n");
225 hexdump_sector(out, buffer, (uint64_t)ofs, sector_size);
236 int main(int argc, char **argv)
238 /* for option processing */
242 /* for use of libcryptsetup */
243 struct crypt_device *cd;
246 int f_luks; /* device file for the luks device */
249 /* temporary helper vars */
257 /* global initializations */
260 /* get commandline parameters */
261 while ((c = getopt (argc, argv, "t:s:vd")) != -1) {
265 tvalue = strtod(s, &end);
267 fprintf(stderr, "\nError: Parsing of argument to -t failed.\n");
271 if (tvalue < 0.0 || tvalue > 1.0) {
272 fprintf(stderr,"\nError: Argument to -t must be in 0.0 ... 1.0\n");
279 svalue = strtol(s, &end, 10);
281 fprintf(stderr, "\nError: Parsing of argument to -s failed.\n");
286 fprintf(stderr,"\nError: Argument to -s must be >= 1 \n");
289 sector_size = svalue;
298 if (optopt == 't' || optopt == 's')
299 fprintf (stderr,"\nError: Option -%c requires an argument.\n",
301 else if (isprint (optopt)) {
302 fprintf(stderr,"\nError: Unknown option `-%c'.\n", optopt);
303 fprintf(stderr,"\n\n%s", help);
305 fprintf (stderr, "\nError: Unknown option character `\\x%x'.\n",
307 fprintf(stderr,"\n\n%s", help);
315 /* parse non-option stuff. Should be exactly one, the device. */
316 if (optind+1 != argc) {
317 fprintf(stderr,"\nError: exactly one non-option argument expected!\n");
318 fprintf(stderr,"\n\n%s", help);
321 device = argv[optind];
323 /* test whether we can open and read device */
324 /* This is needed as we are reading the actual data
325 * in the keyslots directly from the LUKS container.
327 f_luks = open(device, O_RDONLY);
329 fprintf(stderr,"\nError: Opening of device %s failed:\n", device);
334 /* now get the parameters we need via libcryptsetup */
335 /* Basically we need all active keyslots and their placement on disk */
337 /* first init. This does the following:
338 * - gets us a crypt_device struct with some values filled in
339 * Note: This does some init stuff we do not need, but that
340 * should not cause trouble.
343 res = crypt_init(&cd, device);
345 fprintf(stderr, "crypt_init() failed. Maybe not running as root?\n");
350 /* now load LUKS header into the crypt_device
351 * This should also make sure a valid LUKS1 header is on disk
352 * and hence we should be able to skip magic and version checks.
354 res = crypt_load(cd, CRYPT_LUKS1, NULL);
356 fprintf(stderr, "crypt_load() failed. LUKS header too broken/absent?\n");
362 fprintf(out, "\nparameters (commandline and LUKS header):\n");
363 fprintf(out, " sector size: %d\n", sector_size);
364 fprintf(out, " threshold: %0f\n\n", threshold);
366 r = check_keyslots(out, cd, f_luks);