Create smaller header device.
[platform/upstream/cryptsetup.git] / src / veritysetup.c
1 /*
2  * veritysetup - setup cryptographic volumes for dm-verity
3  *
4  * Copyright (C) 2012, Red Hat, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <inttypes.h>
27 #include <popt.h>
28 #include <limits.h>
29 #include <sys/stat.h>
30
31 #include "cryptsetup.h"
32
33 #define PACKAGE_VERITY "veritysetup"
34
35 static int use_superblock = 1;
36
37 static const char *hash_algorithm = NULL;
38 static int hash_type = 1;
39 static int data_block_size = DEFAULT_VERITY_DATA_BLOCK;
40 static int hash_block_size = DEFAULT_VERITY_HASH_BLOCK;
41 static uint64_t data_blocks = 0;
42 static const char *salt_string = NULL;
43 static uint64_t hash_offset = 0;
44 static const char *opt_uuid = NULL;
45
46 static int opt_verbose = 0;
47 static int opt_debug = 0;
48 static int opt_version_mode = 0;
49
50 static const char **action_argv;
51 static int action_argc;
52
53 static size_t hex_to_bytes(const char *hex, char **result)
54 {
55         char buf[3] = "xx\0", *endp, *bytes;
56         size_t i, len;
57
58         len = strlen(hex);
59         if (len % 2)
60                 return -EINVAL;
61         len /= 2;
62
63         if (!(bytes = malloc(len)))
64                 return -ENOMEM;
65
66         for (i = 0; i < len; i++) {
67                 memcpy(buf, &hex[i * 2], 2);
68                 bytes[i] = strtoul(buf, &endp, 16);
69                 if (endp != &buf[2]) {
70                         free(bytes);
71                         return -EINVAL;
72                 }
73         }
74         *result = bytes;
75         return i;
76 }
77
78 __attribute__((format(printf, 5, 6)))
79 static void clogger(struct crypt_device *cd, int level, const char *file,
80                    int line, const char *format, ...)
81 {
82         va_list argp;
83         char *target = NULL;
84
85         va_start(argp, format);
86
87         if (vasprintf(&target, format, argp) > 0) {
88                 if (level >= 0) {
89                         crypt_log(cd, level, target);
90 #ifdef CRYPT_DEBUG
91                 } else if (opt_debug)
92                         printf("# %s:%d %s\n", file ?: "?", line, target);
93 #else
94                 } else if (opt_debug)
95                         printf("# %s\n", target);
96 #endif
97         }
98
99         va_end(argp);
100         free(target);
101 }
102
103 static void _log(int level, const char *msg, void *usrptr __attribute__((unused)))
104 {
105         switch(level) {
106
107         case CRYPT_LOG_NORMAL:
108                 fputs(msg, stdout);
109                 break;
110         case CRYPT_LOG_VERBOSE:
111                 if (opt_verbose)
112                         fputs(msg, stdout);
113                 break;
114         case CRYPT_LOG_ERROR:
115                 fputs(msg, stderr);
116                 break;
117         case CRYPT_LOG_DEBUG:
118                 if (opt_debug)
119                         printf("# %s\n", msg);
120                 break;
121         default:
122                 fprintf(stderr, "Internal error on logging class for msg: %s", msg);
123                 break;
124         }
125 }
126
127 static int _prepare_format(struct crypt_params_verity *params,
128                            const char *data_device,
129                            uint32_t flags)
130 {
131         char *salt = NULL;
132         int len;
133
134         params->hash_name = hash_algorithm ?: DEFAULT_VERITY_HASH;
135         params->data_device = data_device;
136
137         if (salt_string && !strcmp(salt_string, "-")) {
138                 params->salt_size = 0;
139                 params->salt = NULL;
140         } else if (salt_string) {
141                 len = hex_to_bytes(salt_string, &salt);
142                 if (len < 0) {
143                         log_err(_("Invalid salt string specified.\n"));
144                         return -EINVAL;
145                 }
146                 params->salt_size = len;
147                 params->salt = salt;
148         } else {
149                 params->salt_size = DEFAULT_VERITY_SALT_SIZE;
150                 params->salt = NULL;
151         }
152
153         params->data_block_size = data_block_size;
154         params->hash_block_size = hash_block_size;
155         params->data_size = data_blocks;
156         params->hash_area_offset = hash_offset;
157         params->hash_type = hash_type;
158         params->flags = flags;
159
160         return 0;
161 }
162
163 static int action_format(int arg)
164 {
165         struct crypt_device *cd = NULL;
166         struct crypt_params_verity params = {};
167         uint32_t flags = CRYPT_VERITY_CREATE_HASH;
168         int r;
169
170         if ((r = crypt_init(&cd, action_argv[1])))
171                 goto out;
172
173         if (!use_superblock)
174                 flags |= CRYPT_VERITY_NO_HEADER;
175
176         r = _prepare_format(&params, action_argv[0], flags);
177         if (r < 0)
178                 goto out;
179
180         r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, opt_uuid, NULL, 0, &params);
181         if (!r)
182                 crypt_dump(cd);
183 out:
184         crypt_free(cd);
185         free((char*)params.salt);
186         return r;
187 }
188
189 static int _activate(const char *dm_device,
190                       const char *data_device,
191                       const char *hash_device,
192                       const char *root_hash,
193                       uint32_t flags)
194 {
195         struct crypt_device *cd = NULL;
196         struct crypt_params_verity params = {};
197         uint32_t activate_flags = CRYPT_ACTIVATE_READONLY;
198         char *root_hash_bytes = NULL;
199         size_t hash_size;
200         int r;
201
202         if ((r = crypt_init(&cd, hash_device)))
203                 goto out;
204
205         if (use_superblock) {
206                 params.flags = flags;
207                 params.hash_area_offset = hash_offset;
208                 r = crypt_load(cd, CRYPT_VERITY, &params);
209         } else {
210                 r = _prepare_format(&params, data_device, flags | CRYPT_VERITY_NO_HEADER);
211                 if (r < 0)
212                         goto out;
213                 r = crypt_format(cd, CRYPT_VERITY, NULL, NULL, NULL, NULL, 0, &params);
214         }
215         if (r < 0)
216                 goto out;
217         r = crypt_set_data_device(cd, data_device);
218         if (r < 0)
219                 goto out;
220
221         hash_size = crypt_get_volume_key_size(cd);
222         if (hex_to_bytes(root_hash, &root_hash_bytes) != hash_size) {
223                 log_err(_("Invalid root hash string specified.\n"));
224                 r = -EINVAL;
225                 goto out;
226         }
227         r = crypt_activate_by_volume_key(cd, dm_device,
228                                          root_hash_bytes,
229                                          hash_size,
230                                          activate_flags);
231 out:
232         crypt_free(cd);
233         free(root_hash_bytes);
234         free((char*)params.salt);
235         return r;
236 }
237
238 static int action_create(int arg)
239 {
240         return _activate(action_argv[0],
241                          action_argv[1],
242                          action_argv[2],
243                          action_argv[3], 0);
244 }
245
246 static int action_verify(int arg)
247 {
248         return _activate(NULL,
249                          action_argv[0],
250                          action_argv[1],
251                          action_argv[2],
252                          CRYPT_VERITY_CHECK_HASH);
253 }
254
255 static int action_remove(int arg)
256 {
257         struct crypt_device *cd = NULL;
258         int r;
259
260         r = crypt_init_by_name(&cd, action_argv[0]);
261         if (r == 0)
262                 r = crypt_deactivate(cd, action_argv[0]);
263
264         crypt_free(cd);
265         return r;
266 }
267
268 static int action_status(int arg)
269 {
270         crypt_status_info ci;
271         struct crypt_active_device cad;
272         struct crypt_params_verity vp = {};
273         struct crypt_device *cd = NULL;
274         struct stat st;
275         char *backing_file;
276         unsigned i, path = 0;
277         int r = 0;
278
279         /* perhaps a path, not a dm device name */
280         if (strchr(action_argv[0], '/') && !stat(action_argv[0], &st))
281                 path = 1;
282
283         ci = crypt_status(NULL, action_argv[0]);
284         switch (ci) {
285         case CRYPT_INVALID:
286                 r = -EINVAL;
287                 break;
288         case CRYPT_INACTIVE:
289                 if (path)
290                         log_std("%s is inactive.\n", action_argv[0]);
291                 else
292                         log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
293                 r = -ENODEV;
294                 break;
295         case CRYPT_ACTIVE:
296         case CRYPT_BUSY:
297                 if (path)
298                         log_std("%s is active%s.\n", action_argv[0],
299                                 ci == CRYPT_BUSY ? " and is in use" : "");
300                 else
301                         log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
302                                 ci == CRYPT_BUSY ? " and is in use" : "");
303
304                 r = crypt_init_by_name_and_header(&cd, action_argv[0], NULL);
305                 if (r < 0 || !crypt_get_type(cd))
306                         goto out;
307
308                 log_std("  type:        %s\n", crypt_get_type(cd));
309
310                 r = crypt_get_active_device(cd, action_argv[0], &cad);
311                 if (r < 0)
312                         goto out;
313
314                 log_std("  status:      %s\n",
315                         cad.flags & CRYPT_ACTIVATE_CORRUPTED ? "corrupted" : "verified");
316
317                 r = crypt_get_verity_info(cd, &vp);
318                 if (r < 0)
319                         goto out;
320
321                 log_std("  hash type:   %u\n", vp.hash_type);
322                 log_std("  data block:  %u\n", vp.data_block_size);
323                 log_std("  hash block:  %u\n", vp.hash_block_size);
324                 log_std("  hash name:   %s\n", vp.hash_name);
325                 log_std("  salt:        ");
326                 if (vp.salt_size)
327                         for(i = 0; i < vp.salt_size; i++)
328                                 log_std("%02hhx", (const char)vp.salt[i]);
329                 else
330                         log_std("-");
331                 log_std("\n");
332
333                 log_std("  data device: %s\n", vp.data_device);
334                 if (crypt_loop_device(vp.data_device)) {
335                         backing_file = crypt_loop_backing_file(vp.data_device);
336                         log_std("  data loop:   %s\n", backing_file);
337                         free(backing_file);
338                 }
339                 log_std("  size:        %" PRIu64 " sectors\n", cad.size);
340                 log_std("  mode:        %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
341                                            "readonly" : "read/write");
342
343                 log_std("  hash device: %s\n", vp.hash_device);
344                 if (crypt_loop_device(vp.hash_device)) {
345                         backing_file = crypt_loop_backing_file(vp.hash_device);
346                         log_std("  hash loop:   %s\n", backing_file);
347                         free(backing_file);
348                 }
349                 log_std("  hash offset: %" PRIu64 " sectors\n",
350                         vp.hash_area_offset * vp.hash_block_size / 512);
351         }
352 out:
353         crypt_free(cd);
354         if (r == -ENOTSUP)
355                 r = 0;
356         return r;
357 }
358
359 static int action_dump(int arg)
360 {
361         struct crypt_device *cd = NULL;
362         struct crypt_params_verity params = {};
363         int r;
364
365         if ((r = crypt_init(&cd, action_argv[0])))
366                 return r;
367
368         params.hash_area_offset = hash_offset;
369         r = crypt_load(cd, CRYPT_VERITY, &params);
370         if (!r)
371                 crypt_dump(cd);
372         crypt_free(cd);
373         return r;
374 }
375
376 static __attribute__ ((noreturn)) void usage(poptContext popt_context,
377                                              int exitcode, const char *error,
378                                              const char *more)
379 {
380         poptPrintUsage(popt_context, stderr, 0);
381         if (error)
382                 log_err("%s: %s\n", more, error);
383         poptFreeContext(popt_context);
384         exit(exitcode);
385 }
386
387 static void _dbg_version_and_cmd(int argc, const char **argv)
388 {
389         int i;
390
391         log_std("# %s %s processing \"", PACKAGE_VERITY, PACKAGE_VERSION);
392         for (i = 0; i < argc; i++) {
393                 if (i)
394                         log_std(" ");
395                 log_std("%s", argv[i]);
396         }
397         log_std("\"\n");
398 }
399
400 static struct action_type {
401         const char *type;
402         int (*handler)(int);
403         int required_action_argc;
404         const char *arg_desc;
405         const char *desc;
406 } action_types[] = {
407         { "format",     action_format, 2, N_("<data_device> <hash_device>"),N_("format device") },
408         { "verify",     action_verify, 3, N_("<data_device> <hash_device> <root_hash>"),N_("verify device") },
409         { "create",     action_create, 4, N_("<name> <data_device> <hash_device> <root_hash>"),N_("create active device") },
410         { "remove",     action_remove, 1, N_("<name>"),N_("remove (deactivate) device") },
411         { "status",     action_status, 1, N_("<name>"),N_("show active device status") },
412         { "dump",       action_dump,   1, N_("<hash_device>"),N_("show on-disk information") },
413         { NULL, NULL, 0, NULL, NULL }
414 };
415
416 static void help(poptContext popt_context,
417                  enum poptCallbackReason reason __attribute__((unused)),
418                  struct poptOption *key,
419                  const char *arg __attribute__((unused)),
420                  void *data __attribute__((unused)))
421 {
422         struct action_type *action;
423
424         if (key->shortName == '?') {
425                 log_std("%s %s\n", PACKAGE_VERITY, PACKAGE_VERSION);
426                 poptPrintHelp(popt_context, stdout, 0);
427                 log_std(_("\n"
428                          "<action> is one of:\n"));
429                 for(action = action_types; action->type; action++)
430                         log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
431                 log_std(_("\n"
432                          "<name> is the device to create under %s\n"
433                          "<data_device> is the data device\n"
434                          "<hash_device> is the device containing verification data\n"
435                          "<root_hash> hash of the root node on <hash_device>\n"),
436                         crypt_get_dir());
437
438                 log_std(_("\nDefault compiled-in dm-verity parameters:\n"
439                          "\tHash: %s, Data block (bytes): %u, "
440                          "Hash block (bytes): %u, Salt size: %u, Hash format: %u\n"),
441                         DEFAULT_VERITY_HASH, DEFAULT_VERITY_DATA_BLOCK,
442                         DEFAULT_VERITY_HASH_BLOCK, DEFAULT_VERITY_SALT_SIZE,
443                         1);
444                 exit(EXIT_SUCCESS);
445         } else
446                 usage(popt_context, EXIT_SUCCESS, NULL, NULL);
447 }
448
449 static void show_status(int errcode)
450 {
451         char error[256], *error_;
452
453         if(!opt_verbose)
454                 return;
455
456         if(!errcode) {
457                 log_std(_("Command successful.\n"));
458                 return;
459         }
460
461         crypt_get_error(error, sizeof(error));
462
463         if (!error[0]) {
464                 error_ = strerror_r(-errcode, error, sizeof(error));
465                 if (error_ != error) {
466                         strncpy(error, error_, sizeof(error));
467                         error[sizeof(error) - 1] = '\0';
468                 }
469         }
470
471         log_err(_("Command failed with code %i"), -errcode);
472         if (*error)
473                 log_err(": %s\n", error);
474         else
475                 log_err(".\n");
476 }
477
478 static int run_action(struct action_type *action)
479 {
480         int r;
481
482         log_dbg("Running command %s.", action->type);
483
484         r = action->handler(0);
485
486         show_status(r);
487
488         /* Translate exit code to simple codes */
489         switch (r) {
490         case 0:         r = EXIT_SUCCESS; break;
491         case -EEXIST:
492         case -EBUSY:    r = 5; break;
493         case -ENOTBLK:
494         case -ENODEV:   r = 4; break;
495         case -ENOMEM:   r = 3; break;
496         case -EPERM:    r = 2; break;
497         case -EINVAL:
498         case -ENOENT:
499         case -ENOSYS:
500         default:        r = EXIT_FAILURE;
501         }
502         return r;
503 }
504
505 int main(int argc, const char **argv)
506 {
507         static char *popt_tmp;
508         static const char *null_action_argv[] = {NULL};
509         static struct poptOption popt_help_options[] = {
510                 { NULL,    '\0', POPT_ARG_CALLBACK, help, 0, NULL,                         NULL },
511                 { "help",  '?',  POPT_ARG_NONE,     NULL, 0, N_("Show this help message"), NULL },
512                 { "usage", '\0', POPT_ARG_NONE,     NULL, 0, N_("Display brief usage"),    NULL },
513                 POPT_TABLEEND
514         };
515         static struct poptOption popt_options[] = {
516                 { NULL,              '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
517                 { "version",         '\0', POPT_ARG_NONE, &opt_version_mode, 0, N_("Print package version"), NULL },
518                 { "verbose",         'v',  POPT_ARG_NONE, &opt_verbose,      0, N_("Shows more detailed error messages"), NULL },
519                 { "debug",           '\0', POPT_ARG_NONE, &opt_debug,        0, N_("Show debug messages"), NULL },
520                 { "no-superblock",   0,    POPT_ARG_VAL,  &use_superblock,   0, N_("Do not use verity superblock"), NULL },
521                 { "format",          0,    POPT_ARG_INT,  &hash_type,        0, N_("Format type (1 - normal, 0 - original Chrome OS)"), N_("number") },
522                 { "data-block-size", 0,    POPT_ARG_INT,  &data_block_size,  0, N_("Block size on the data device"), N_("bytes") },
523                 { "hash-block-size", 0,    POPT_ARG_INT,  &hash_block_size,  0, N_("Block size on the hash device"), N_("bytes") },
524                 { "data-blocks",     0,    POPT_ARG_STRING, &popt_tmp,       1, N_("The number of blocks in the data file"), N_("blocks") },
525                 { "hash-offset",     0,    POPT_ARG_STRING, &popt_tmp,       2, N_("Starting offset on the hash device"), N_("bytes") },
526                 { "hash",            'h',  POPT_ARG_STRING, &hash_algorithm, 0, N_("Hash algorithm"), N_("string") },
527                 { "salt",            's',  POPT_ARG_STRING, &salt_string,    0, N_("Salt"), N_("hex string") },
528                 { "uuid",            '\0', POPT_ARG_STRING, &opt_uuid,       0, N_("UUID for device to use."), NULL },
529                 POPT_TABLEEND
530         };
531
532         poptContext popt_context;
533         struct action_type *action;
534         const char *aname;
535         int r;
536
537         crypt_set_log_callback(NULL, _log, NULL);
538
539         setlocale(LC_ALL, "");
540         bindtextdomain(PACKAGE, LOCALEDIR);
541         textdomain(PACKAGE);
542
543         popt_context = poptGetContext("verity", argc, argv, popt_options, 0);
544         poptSetOtherOptionHelp(popt_context,
545                                N_("[OPTION...] <action> <action-specific>"));
546
547         while((r = poptGetNextOpt(popt_context)) > 0) {
548                 unsigned long long ull_value;
549                 char *endp;
550
551                 errno = 0;
552                 ull_value = strtoull(popt_tmp, &endp, 10);
553                 if (*endp || !*popt_tmp || !isdigit(*popt_tmp) ||
554                     (errno == ERANGE && ull_value == ULLONG_MAX) ||
555                     (errno != 0 && ull_value == 0))
556                         r = POPT_ERROR_BADNUMBER;
557
558                 switch(r) {
559                         case 1:
560                                 data_blocks = ull_value;
561                                 break;
562                         case 2:
563                                 hash_offset = ull_value;
564                                 break;
565                 }
566
567                 if (r < 0)
568                         break;
569         }
570
571         if (r < -1)
572                 usage(popt_context, EXIT_FAILURE, poptStrerror(r),
573                       poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
574
575         if (opt_version_mode) {
576                 log_std("%s %s\n", PACKAGE_VERITY, PACKAGE_VERSION);
577                 poptFreeContext(popt_context);
578                 exit(EXIT_SUCCESS);
579         }
580
581         if (!(aname = poptGetArg(popt_context)))
582                 usage(popt_context, EXIT_FAILURE, _("Argument <action> missing."),
583                       poptGetInvocationName(popt_context));
584         for(action = action_types; action->type; action++)
585                 if (strcmp(action->type, aname) == 0)
586                         break;
587         if (!action->type)
588                 usage(popt_context, EXIT_FAILURE, _("Unknown action."),
589                       poptGetInvocationName(popt_context));
590
591         action_argc = 0;
592         action_argv = poptGetArgs(popt_context);
593         /* Make return values of poptGetArgs more consistent in case of remaining argc = 0 */
594         if(!action_argv)
595                 action_argv = null_action_argv;
596
597         /* Count args, somewhat unnice, change? */
598         while(action_argv[action_argc] != NULL)
599                 action_argc++;
600
601         if(action_argc < action->required_action_argc) {
602                 char buf[128];
603                 snprintf(buf, 128,_("%s: requires %s as arguments"), action->type, action->arg_desc);
604                 usage(popt_context, EXIT_FAILURE, buf,
605                       poptGetInvocationName(popt_context));
606         }
607
608         if (data_block_size < 0 || hash_block_size < 0 || hash_type < 0) {
609                 usage(popt_context, EXIT_FAILURE,
610                       _("Negative number for option not permitted."),
611                       poptGetInvocationName(popt_context));
612         }
613
614         if (opt_debug) {
615                 opt_verbose = 1;
616                 crypt_set_debug_level(-1);
617                 _dbg_version_and_cmd(argc, argv);
618         }
619
620         r = run_action(action);
621         poptFreeContext(popt_context);
622         return r;
623 }