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