4 * (C) 2012 Red Hat Inc.
6 * This copyrighted material is made available to anyone wishing to use,
7 * modify, copy, or redistribute it subject to the terms and conditions
8 * of the GNU General Public License v.2.
10 * You should have received a copy of the GNU General Public License
11 * along with this program; if not, write to the Free Software Foundation,
12 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * Compile flags to use a specific crypto library:
17 * openssl: -lpopt -DCRYPT_OPENSSL -lcrypto
18 * nss: -lpopt -DCRYPT_NSS -I/usr/include/nspr/ -I/usr/include/nss -lnss3
19 * gcrypt: -lpopt -DCRYPT_GCRYPT -lgcrypt -lgpg-error
22 #define _FILE_OFFSET_BITS 64
25 # include "configure.h"
35 #include <sys/types.h>
37 #include <sys/ioctl.h>
38 #include <sys/mount.h>
39 #include <arpa/inet.h>
43 # include <openssl/evp.h>
44 # include <openssl/rand.h>
45 #elif defined(CRYPT_GCRYPT)
47 #elif defined(CRYPT_NSS)
53 #if !defined(CRYPT_OPENSSL) && !defined(CRYPT_GCRYPT) && !defined(CRYPT_NSS)
54 #error No crypto engine specified
57 #define DEFAULT_BLOCK_SIZE 4096
58 #define DM_VERITY_MAX_LEVELS 63
60 #define DEFAULT_SALT_SIZE 32
61 #define MAX_SALT_SIZE 384
65 #define MODE_ACTIVATE 2
67 #define MAX_FORMAT_VERSION 1
70 static int use_superblock
= 1;
72 static const char *dm_device
;
73 static const char *data_device
;
74 static const char *hash_device
;
75 static const char *hash_algorithm
= NULL
;
76 static const char *root_hash
;
78 static int version
= -1;
79 static int data_block_size
= 0;
80 static int hash_block_size
= 0;
81 static char *data_blocks_string
= NULL
;
82 static long long data_blocks
= 0;
83 static char *hash_start_string
= NULL
;
84 static long long hash_start
= 0;
85 static const char *salt_string
= NULL
;
87 static FILE *data_file
;
88 static FILE *hash_file
;
90 static off_t data_file_blocks
;
91 static off_t hash_file_blocks
;
92 static off_t used_hash_blocks
;
94 static unsigned char *root_hash_bytes
;
95 static unsigned char *calculated_digest
;
97 static unsigned char *salt_bytes
;
98 static unsigned salt_size
;
100 static unsigned digest_size
;
101 static unsigned char digest_size_bits
;
102 static unsigned char levels
;
103 static unsigned char hash_per_block_bits
;
105 static off_t hash_level_block
[DM_VERITY_MAX_LEVELS
];
106 static off_t hash_level_size
[DM_VERITY_MAX_LEVELS
];
108 static off_t superblock_position
;
110 static int retval
= 0;
113 uint8_t signature
[8];
115 uint8_t data_block_bits
;
116 uint8_t hash_block_bits
;
120 uint32_t data_blocks_hi
;
121 uint32_t data_blocks_lo
;
122 uint8_t algorithm
[16];
123 uint8_t salt
[MAX_SALT_SIZE
];
127 #define DM_VERITY_SIGNATURE "verity\0\0"
128 #define DM_VERITY_VERSION 0
130 #if defined(__GNUC__) && __GNUC__ >= 2
131 __attribute__((__noreturn__
))
133 static void help(poptContext popt_context
,
134 enum poptCallbackReason reason
,
135 struct poptOption
*key
,
139 if (!strcmp(key
->longName
, "help")) {
140 poptPrintHelp(popt_context
, stdout
, 0);
142 printf("veritysetup");
143 #ifdef DM_LIB_VERSION
144 printf(", device mapper version %s", DM_LIB_VERSION
);
151 static struct poptOption popt_help_options
[] = {
152 { NULL
, 0, POPT_ARG_CALLBACK
, help
, 0, NULL
, NULL
},
153 { "help", 'h', POPT_ARG_NONE
, NULL
, 0, "Show help", NULL
},
154 { "version", 0, POPT_ARG_NONE
, NULL
, 0, "Show version", NULL
},
158 static struct poptOption popt_options
[] = {
159 { NULL
, '\0', POPT_ARG_INCLUDE_TABLE
, popt_help_options
, 0, NULL
, NULL
},
160 { "create", 'c', POPT_ARG_VAL
, &mode
, MODE_CREATE
, "Create hash", NULL
},
161 { "verify", 'v', POPT_ARG_VAL
, &mode
, MODE_VERIFY
, "Verify integrity", NULL
},
162 { "activate", 'a', POPT_ARG_VAL
, &mode
, MODE_ACTIVATE
, "Activate the device", NULL
},
163 { "no-superblock", 0, POPT_ARG_VAL
, &use_superblock
, 0, "Do not create/use superblock" },
164 { "format", 0, POPT_ARG_INT
, &version
, 0, "Format version (1 - normal format, 0 - original Chromium OS format)", "number" },
165 { "data-block-size", 0, POPT_ARG_INT
, &data_block_size
, 0, "Block size on the data device", "bytes" },
166 { "hash-block-size", 0, POPT_ARG_INT
, &hash_block_size
, 0, "Block size on the hash device", "bytes" },
167 { "data-blocks", 0, POPT_ARG_STRING
, &data_blocks_string
, 0, "The number of blocks in the data file", "blocks" },
168 { "hash-start", 0, POPT_ARG_STRING
, &hash_start_string
, 0, "Starting block on the hash device", "512-byte sectors" },
169 { "algorithm", 0, POPT_ARG_STRING
, &hash_algorithm
, 0, "Hash algorithm (default sha256)", "string" },
170 { "salt", 0, POPT_ARG_STRING
, &salt_string
, 0, "Salt", "hex string" },
174 #if defined(__GNUC__) && __GNUC__ >= 2
175 __attribute__((__format__(__printf__
, 1, 2), __noreturn__
))
177 static void exit_err(const char *msg
, ...)
181 vfprintf(stderr
, msg
, args
);
187 #if defined(__GNUC__) && __GNUC__ >= 2
188 __attribute__((__noreturn__
))
190 static void stream_err(FILE *f
, const char *msg
)
195 } else if (feof(f
)) {
196 exit_err("eof on %s", msg
);
198 exit_err("unknown error on %s", msg
);
202 static void *xmalloc(size_t s
)
204 void *ptr
= malloc(!s
? 1 : s
);
205 if (!ptr
) exit_err("out of memory");
209 static char *xstrdup(const char *str
)
211 return strcpy(xmalloc(strlen(str
) + 1), str
);
214 static char *xprint(unsigned long long num
)
216 size_t s
= snprintf(NULL
, 0, "%llu", num
);
217 char *p
= xmalloc(s
+ 1);
218 snprintf(p
, s
+ 1, "%llu", num
);
222 static char *xhexprint(unsigned char *bytes
, size_t len
)
225 char *p
= xmalloc(len
* 2 + 1);
227 for (i
= 0; i
< len
; i
++)
228 snprintf(p
+ i
* 2, 3, "%02x", bytes
[i
]);
232 static off_t
get_size(FILE *f
, const char *name
)
244 if (S_ISREG(st
.st_mode
)) {
246 } else if (S_ISBLK(st
.st_mode
)) {
247 unsigned long long size64
;
248 unsigned long sizeul
;
249 if (!ioctl(h
, BLKGETSIZE64
, &size64
)) {
251 if ((off_t
)size64
< 0 || (off_t
)size64
!= size64
) {
253 exit_err("%s: device size overflow", name
);
257 if (!ioctl(h
, BLKGETSIZE
, &sizeul
)) {
258 size64
= (unsigned long long)sizeul
* 512;
259 if (size64
/ 512 != sizeul
) goto size_overflow
;
262 perror("BLKGETSIZE");
265 exit_err("%s is not a file or a block device", name
);
267 return -1; /* never reached, shut up warning */
270 static void block_fseek(FILE *f
, off_t block
, int block_size
)
272 unsigned long long pos
= (unsigned long long)block
* block_size
;
273 if (pos
/ block_size
!= block
||
276 exit_err("seek position overflow");
277 if (fseeko(f
, pos
, SEEK_SET
)) {
286 static const EVP_MD
*evp
;
288 static int hash_init(const char *name
)
290 OpenSSL_add_all_digests();
291 evp
= EVP_get_digestbyname(name
);
294 return EVP_MD_size(evp
);
297 typedef EVP_MD_CTX hash_context
;
299 static void hash_context_init(hash_context
*ctx
)
301 EVP_MD_CTX_init(ctx
);
304 static void hash_context_reset(hash_context
*ctx
)
306 if (EVP_DigestInit_ex(ctx
, evp
, NULL
) != 1)
307 exit_err("EVP_DigestInit_ex failed");
310 static void hash_context_update(hash_context
*ctx
, unsigned char *data
, size_t len
)
312 if (EVP_DigestUpdate(ctx
, data
, len
) != 1)
313 exit_err("EVP_DigestUpdate failed");
316 static void hash_context_final(hash_context
*ctx
, unsigned char *digest
)
318 if (EVP_DigestFinal_ex(ctx
, digest
, NULL
) != 1)
319 exit_err("EVP_DigestFinal_ex failed");
322 static void hash_context_destroy(hash_context
*ctx
)
324 if (EVP_MD_CTX_cleanup(ctx
) != 1)
325 exit_err("EVP_MD_CTX_cleanup failed");
328 static void crypto_rand_bytes(unsigned char *data
, size_t len
)
330 if (RAND_bytes(data
, len
) != 1)
331 exit_err("RAND_bytes failed");
334 #elif defined(CRYPT_GCRYPT)
336 static int gcrypt_id
;
338 static int hash_init(const char *name
)
341 gcrypt_id
= gcry_md_map_name(name
);
343 if (!strcmp(name
, "wp512")) {
347 if (!strcmp(name
, "rmd160")) {
353 return gcry_md_get_algo_dlen(gcrypt_id
);
356 typedef gcry_md_hd_t hash_context
;
358 static void hash_context_init(hash_context
*ctx
)
360 if (gcry_md_open(ctx
, gcrypt_id
, 0))
361 exit_err("gcry_md_open failed");
364 static void hash_context_reset(hash_context
*ctx
)
369 static void hash_context_update(hash_context
*ctx
, unsigned char *data
, size_t len
)
371 gcry_md_write(*ctx
, data
, len
);
374 static void hash_context_final(hash_context
*ctx
, unsigned char *digest
)
376 unsigned char *p
= gcry_md_read(*ctx
, gcrypt_id
);
377 memcpy(digest
, p
, gcry_md_get_algo_dlen(gcrypt_id
));
380 static void hash_context_destroy(hash_context
*ctx
)
385 static void crypto_rand_bytes(unsigned char *data
, size_t len
)
387 gcry_randomize(data
, len
, GCRY_STRONG_RANDOM
);
390 #elif defined(CRYPT_NSS)
392 static HASH_HashType nss_alg
;
394 static int hash_init(const char *name
)
396 if (NSS_NoDB_Init(NULL
) != SECSuccess
)
397 exit_err("NSS_Init failed");
398 if (!strcmp(name
, "md2"))
399 nss_alg
= HASH_AlgMD2
;
400 else if (!strcmp(name
, "md5"))
401 nss_alg
= HASH_AlgMD5
;
402 else if (!strcmp(name
, "sha1"))
403 nss_alg
= HASH_AlgSHA1
;
404 else if (!strcmp(name
, "sha256"))
405 nss_alg
= HASH_AlgSHA256
;
406 else if (!strcmp(name
, "sha384"))
407 nss_alg
= HASH_AlgSHA384
;
408 else if (!strcmp(name
, "sha512"))
409 nss_alg
= HASH_AlgSHA512
;
413 return HASH_ResultLen(nss_alg
);
416 typedef HASHContext
*hash_context
;
418 static void hash_context_init(hash_context
*ctx
)
420 *ctx
= HASH_Create(nss_alg
);
422 exit_err("HASH_Create failed");
425 static void hash_context_reset(hash_context
*ctx
)
430 static void hash_context_update(hash_context
*ctx
, unsigned char *data
, size_t len
)
432 HASH_Update(*ctx
, data
, len
);
435 static void hash_context_final(hash_context
*ctx
, unsigned char *digest
)
438 HASH_End(*ctx
, digest
, &result_len
, HASH_ResultLen(nss_alg
));
441 static void hash_context_destroy(hash_context
*ctx
)
446 static void crypto_rand_bytes(unsigned char *data
, size_t len
)
448 if (PK11_GenerateRandom(data
, len
) != SECSuccess
)
449 exit_err("PK11_GenerateRandom failed");
455 static off_t
verity_position_at_level(off_t block
, int level
)
457 return block
>> (level
* hash_per_block_bits
);
460 static void calculate_positions(void)
462 unsigned long long hash_position
;
465 digest_size_bits
= 0;
466 while (1 << digest_size_bits
< digest_size
)
468 hash_per_block_bits
= 0;
469 while (((hash_block_size
/ digest_size
) >> hash_per_block_bits
) > 1)
470 hash_per_block_bits
++;
471 if (!hash_per_block_bits
)
472 exit_err("at least two hashes must fit in a hash file block");
475 if (data_file_blocks
) {
476 while (hash_per_block_bits
* levels
< 64 &&
477 (unsigned long long)(data_file_blocks
- 1) >>
478 (hash_per_block_bits
* levels
))
482 if (levels
> DM_VERITY_MAX_LEVELS
)
483 exit_err("too many tree levels");
485 hash_position
= hash_start
* 512 / hash_block_size
;
486 for (i
= levels
- 1; i
>= 0; i
--) {
488 hash_level_block
[i
] = hash_position
;
489 s
= verity_position_at_level(data_file_blocks
, i
);
490 s
= (s
>> hash_per_block_bits
) +
491 !!(s
& ((1 << hash_per_block_bits
) - 1));
492 hash_level_size
[i
] = s
;
493 if (hash_position
+ s
< hash_position
||
494 (off_t
)(hash_position
+ s
) < 0 ||
495 (off_t
)(hash_position
+ s
) != hash_position
+ s
)
496 exit_err("hash device offset overflow");
499 used_hash_blocks
= hash_position
;
502 static void create_or_verify_zero(FILE *wr
, unsigned char *left_block
, unsigned left_bytes
)
505 if (mode
!= MODE_CREATE
) {
507 if (fread(left_block
, left_bytes
, 1, wr
) != 1)
508 stream_err(wr
, "read");
509 for (x
= 0; x
< left_bytes
; x
++) if (left_block
[x
]) {
511 fprintf(stderr
, "spare area is not zeroed at position %lld\n", (long long)ftello(wr
) - left_bytes
);
514 if (fwrite(left_block
, left_bytes
, 1, wr
) != 1)
515 stream_err(wr
, "write");
520 static void create_or_verify_stream(FILE *rd
, FILE *wr
, int block_size
, off_t blocks
)
522 unsigned char *left_block
= xmalloc(hash_block_size
);
523 unsigned char *data_buffer
= xmalloc(block_size
);
524 unsigned char *read_digest
= mode
!= MODE_CREATE
? xmalloc(digest_size
) : NULL
;
525 off_t blocks_to_write
= (blocks
>> hash_per_block_bits
) +
526 !!(blocks
& ((1 << hash_per_block_bits
) - 1));
528 hash_context_init(&ctx
);
529 memset(left_block
, 0, hash_block_size
);
530 while (blocks_to_write
--) {
532 unsigned left_bytes
= hash_block_size
;
533 for (x
= 0; x
< 1 << hash_per_block_bits
; x
++) {
537 if (fread(data_buffer
, block_size
, 1, rd
) != 1)
538 stream_err(rd
, "read");
539 hash_context_reset(&ctx
);
541 hash_context_update(&ctx
, salt_bytes
, salt_size
);
543 hash_context_update(&ctx
, data_buffer
, block_size
);
545 hash_context_update(&ctx
, salt_bytes
, salt_size
);
547 hash_context_final(&ctx
, calculated_digest
);
550 if (mode
!= MODE_CREATE
) {
551 if (fread(read_digest
, digest_size
, 1, wr
) != 1)
552 stream_err(wr
, "read");
553 if (memcmp(read_digest
, calculated_digest
, digest_size
)) {
555 fprintf(stderr
, "verification failed at position %lld in %s file\n", (long long)ftello(rd
) - block_size
, rd
== data_file
? "data" : "metadata");
558 if (fwrite(calculated_digest
, digest_size
, 1, wr
) != 1)
559 stream_err(wr
, "write");
562 left_bytes
-= digest_size
;
564 create_or_verify_zero(wr
, left_block
, (1 << digest_size_bits
) - digest_size
);
565 left_bytes
-= 1 << digest_size_bits
;
569 create_or_verify_zero(wr
, left_block
, left_bytes
);
571 if (mode
== MODE_CREATE
&& wr
) {
577 stream_err(wr
, "write");
580 hash_context_destroy(&ctx
);
583 if (mode
!= MODE_CREATE
)
587 static char **make_target_line(void)
589 const int line_elements
= 14;
590 char **line
= xmalloc(line_elements
* sizeof(char *));
592 char *algorithm_copy
= xstrdup(hash_algorithm
);
593 /* transform ripemdXXX to rmdXXX */
594 if (!strncmp(algorithm_copy
, "ripemd", 6))
595 memmove(algorithm_copy
+ 1, algorithm_copy
+ 4, strlen(algorithm_copy
+ 4) + 1);
596 if (!strcmp(algorithm_copy
, "whirlpool"))
597 strcpy(algorithm_copy
, "wp512");
598 line
[i
++] = xstrdup("0");
599 line
[i
++] = xprint((unsigned long long)data_file_blocks
* data_block_size
/ 512);
600 line
[i
++] = xstrdup("verity");
601 line
[i
++] = xprint(version
);
602 line
[i
++] = xstrdup(data_device
);
603 line
[i
++] = xstrdup(hash_device
);
604 line
[i
++] = xprint(data_block_size
);
605 line
[i
++] = xprint(hash_block_size
);
606 line
[i
++] = xprint(data_file_blocks
);
607 line
[i
++] = xprint(hash_start
* 512 / hash_block_size
);
608 line
[i
++] = algorithm_copy
;
609 line
[i
++] = xhexprint(calculated_digest
, digest_size
);
610 line
[i
++] = !salt_size
? xstrdup("-") : xhexprint(salt_bytes
, salt_size
);
612 if (i
> line_elements
)
613 exit_err("INTERNAL ERROR: insufficient array size");
617 static void free_target_line(char **line
)
620 for (i
= 0; line
[i
]; i
++)
625 static void create_or_verify(void)
629 memset(calculated_digest
, 0, digest_size
);
630 if (mode
!= MODE_ACTIVATE
)
631 for (i
= 0; i
< levels
; i
++) {
632 block_fseek(hash_file
, hash_level_block
[i
], hash_block_size
);
634 block_fseek(data_file
, 0, data_block_size
);
635 create_or_verify_stream(data_file
, hash_file
, data_block_size
, data_file_blocks
);
637 FILE *hash_file_2
= fopen(hash_device
, "r");
642 block_fseek(hash_file_2
, hash_level_block
[i
- 1], hash_block_size
);
643 create_or_verify_stream(hash_file_2
, hash_file
, hash_block_size
, hash_level_size
[i
- 1]);
649 block_fseek(hash_file
, hash_level_block
[levels
- 1], hash_block_size
);
650 create_or_verify_stream(hash_file
, NULL
, hash_block_size
, 1);
652 block_fseek(data_file
, 0, data_block_size
);
653 create_or_verify_stream(data_file
, NULL
, data_block_size
, data_file_blocks
);
656 if (mode
!= MODE_CREATE
) {
657 if (memcmp(calculated_digest
, root_hash_bytes
, digest_size
)) {
658 fprintf(stderr
, "verification failed in the root block\n");
661 if (!retval
&& mode
== MODE_VERIFY
)
662 fprintf(stderr
, "hash successfully verified\n");
666 if (fsync(fileno(hash_file
))) {
670 printf("hash device size: %llu\n", (unsigned long long)used_hash_blocks
* hash_block_size
);
671 printf("data block size %u, hash block size %u, %u tree levels\n", data_block_size
, hash_block_size
, levels
);
673 p
= xhexprint(salt_bytes
, salt_size
);
676 printf("salt: %s\n", p
);
678 p
= xhexprint(calculated_digest
, digest_size
);
679 printf("root hash: %s\n", p
);
681 printf("target line:");
682 target_line
= make_target_line();
683 for (i
= 0; target_line
[i
]; i
++)
684 printf(" %s", target_line
[i
]);
685 free_target_line(target_line
);
690 #if defined(__GNUC__) && __GNUC__ >= 2
691 __attribute__((__noreturn__
))
693 static void activate(void)
698 char **target_line
= make_target_line();
699 for (i
= 0; target_line
[i
]; i
++) {
702 len
+= strlen(target_line
[i
]);
704 table_arg
= xmalloc(len
);
706 for (i
= 0; target_line
[i
]; i
++) {
708 strcat(table_arg
, " ");
709 strcat(table_arg
, target_line
[i
]);
711 free_target_line(target_line
);
712 execlp("dmsetup", "dmsetup", "-r", "create", dm_device
, "--table", table_arg
, NULL
);
717 static void get_hex(const char *string
, unsigned char **result
, size_t len
, const char *description
)
719 size_t rl
= strlen(string
);
721 if (strspn(string
, "0123456789ABCDEFabcdef") != rl
)
722 exit_err("invalid %s", description
);
724 exit_err("invalid length of %s", description
);
725 *result
= xmalloc(len
);
726 memset(*result
, 0, len
);
727 for (u
= 0; u
< rl
; u
++) {
728 unsigned char c
= (string
[u
] & 15) + (string
[u
] > '9' ? 9 : 0);
729 (*result
)[u
/ 2] |= c
<< (((u
& 1) ^ 1) << 2);
733 static struct superblock superblock
;
735 static void load_superblock(void)
737 long long sb_data_blocks
;
739 block_fseek(hash_file
, superblock_position
, 1);
740 if (fread(&superblock
, sizeof(struct superblock
), 1, hash_file
) != 1)
741 stream_err(hash_file
, "read");
742 if (memcmp(superblock
.signature
, DM_VERITY_SIGNATURE
, sizeof(superblock
.signature
)))
743 exit_err("superblock not found on the hash device");
744 if (superblock
.version
> MAX_FORMAT_VERSION
)
745 exit_err("unknown version");
746 if (superblock
.data_block_bits
< 9 || superblock
.data_block_bits
>= 31)
747 exit_err("invalid data_block_bits in the superblock");
748 if (superblock
.hash_block_bits
< 9 || superblock
.hash_block_bits
>= 31)
749 exit_err("invalid data_block_bits in the superblock");
750 sb_data_blocks
= ((unsigned long long)ntohl(superblock
.data_blocks_hi
) << 31 << 1) | ntohl(superblock
.data_blocks_lo
);
751 if (sb_data_blocks
< 0 || (off_t
)sb_data_blocks
< 0 || (off_t
)sb_data_blocks
!= sb_data_blocks
)
752 exit_err("invalid data blocks in the superblock");
753 if (!memchr(superblock
.algorithm
, 0, sizeof(superblock
.algorithm
)))
754 exit_err("invalid hash algorithm in the superblock");
755 if (ntohs(superblock
.salt_size
) > MAX_SALT_SIZE
)
756 exit_err("invalid salt_size in the superblock");
759 version
= superblock
.version
;
761 if (version
!= superblock
.version
)
762 exit_err("version (%d) does not match superblock value (%d)", version
, superblock
.version
);
765 if (!data_block_size
) {
766 data_block_size
= 1 << superblock
.data_block_bits
;
768 if (data_block_size
!= 1 << superblock
.data_block_bits
)
769 exit_err("data block size (%d) does not match superblock value (%d)", data_block_size
, 1 << superblock
.data_block_bits
);
772 if (!hash_block_size
) {
773 hash_block_size
= 1 << superblock
.hash_block_bits
;
775 if (hash_block_size
!= 1 << superblock
.hash_block_bits
)
776 exit_err("hash block size (%d) does not match superblock value (%d)", hash_block_size
, 1 << superblock
.hash_block_bits
);
779 if (!data_blocks_string
) {
780 data_blocks
= sb_data_blocks
;
781 data_blocks_string
= (char *)"";
783 if (data_blocks
!= sb_data_blocks
)
784 exit_err("data blocks (%lld) does not match superblock value (%lld)", data_blocks
, sb_data_blocks
);
787 if (!hash_algorithm
) {
788 hash_algorithm
= (char *)superblock
.algorithm
;
790 if (strcmp(hash_algorithm
, (char *)superblock
.algorithm
))
791 exit_err("hash algorithm (%s) does not match superblock value (%s)", hash_algorithm
, superblock
.algorithm
);
795 salt_size
= ntohs(superblock
.salt_size
);
796 salt_bytes
= xmalloc(salt_size
);
797 memcpy(salt_bytes
, superblock
.salt
, salt_size
);
799 if (salt_size
!= ntohs(superblock
.salt_size
) ||
800 memcmp(salt_bytes
, superblock
.salt
, salt_size
))
801 exit_err("salt does not match superblock value");
805 static void save_superblock(void)
807 memset(&superblock
, 0, sizeof(struct superblock
));
809 memcpy(&superblock
.signature
, DM_VERITY_SIGNATURE
, sizeof(superblock
.signature
));
810 superblock
.version
= version
;
811 superblock
.data_block_bits
= ffs(data_block_size
) - 1;
812 superblock
.hash_block_bits
= ffs(hash_block_size
) - 1;
813 superblock
.salt_size
= htons(salt_size
);
814 superblock
.data_blocks_hi
= htonl(data_file_blocks
>> 31 >> 1);
815 superblock
.data_blocks_lo
= htonl(data_file_blocks
& 0xFFFFFFFF);
816 strncpy((char *)superblock
.algorithm
, hash_algorithm
, sizeof superblock
.algorithm
);
817 memcpy(superblock
.salt
, salt_bytes
, salt_size
);
819 block_fseek(hash_file
, superblock_position
, 1);
820 if (fwrite(&superblock
, sizeof(struct superblock
), 1, hash_file
) != 1)
821 stream_err(hash_file
, "write");
824 int main(int argc
, const char **argv
)
826 poptContext popt_context
;
831 if (sizeof(struct superblock
) != 512)
832 exit_err("INTERNAL ERROR: bad superblock size %ld", (long)sizeof(struct superblock
));
834 popt_context
= poptGetContext("verity", argc
, argv
, popt_options
, 0);
836 poptSetOtherOptionHelp(popt_context
, "[-c | -v | -a] [<device name> if activating] <data device> <hash device> [<root hash> if activating or verifying] [OPTION...]");
839 poptPrintHelp(popt_context
, stdout
, 0);
843 r
= poptGetNextOpt(popt_context
);
845 exit_err("bad option %s", poptBadOption(popt_context
, 0));
848 exit_err("verify, create or activate mode not specified");
850 if (mode
== MODE_ACTIVATE
) {
851 dm_device
= poptGetArg(popt_context
);
853 exit_err("device name is missing");
854 if (!*dm_device
|| strchr(dm_device
, '/'))
855 exit_err("invalid device name to activate");
858 data_device
= poptGetArg(popt_context
);
860 exit_err("data device is missing");
862 hash_device
= poptGetArg(popt_context
);
864 exit_err("metadata device is missing");
866 if (mode
!= MODE_CREATE
) {
867 root_hash
= poptGetArg(popt_context
);
869 exit_err("root hash not specified");
872 s
= poptGetArg(popt_context
);
874 exit_err("extra argument %s", s
);
876 data_file
= fopen(data_device
, "r");
882 hash_file
= fopen(hash_device
, mode
!= MODE_CREATE
? "r" : "r+");
883 if (!hash_file
&& errno
== ENOENT
&& mode
== MODE_CREATE
)
884 hash_file
= fopen(hash_device
, "w+");
890 if (data_blocks_string
) {
891 data_blocks
= strtoll(data_blocks_string
, &end
, 10);
892 if (!*data_blocks_string
|| *end
)
893 exit_err("invalid number of data blocks");
896 if (hash_start_string
) {
897 hash_start
= strtoll(hash_start_string
, &end
, 10);
898 if (!*hash_start_string
|| *end
)
899 exit_err("invalid hash start");
902 if (hash_start
< 0 ||
903 (unsigned long long)hash_start
* 512 / 512 != hash_start
||
904 (off_t
)(hash_start
* 512) < 0 ||
905 (off_t
)(hash_start
* 512) != hash_start
* 512) exit_err("invalid hash start");
907 if (salt_string
|| !use_superblock
) {
908 if (!salt_string
|| !strcmp(salt_string
, "-"))
910 salt_size
= strlen(salt_string
) / 2;
911 if (salt_size
> MAX_SALT_SIZE
)
912 exit_err("too long salt (max %d bytes)", MAX_SALT_SIZE
);
913 get_hex(salt_string
, &salt_bytes
, salt_size
, "salt");
916 if (use_superblock
) {
917 superblock_position
= hash_start
* 512;
918 if (mode
!= MODE_CREATE
)
923 version
= MAX_FORMAT_VERSION
;
924 if (version
< 0 || version
> MAX_FORMAT_VERSION
)
925 exit_err("invalid format version");
927 if (!data_block_size
)
928 data_block_size
= DEFAULT_BLOCK_SIZE
;
929 if (!hash_block_size
)
930 hash_block_size
= data_block_size
;
932 if (data_block_size
< 512 || (data_block_size
& (data_block_size
- 1)) || data_block_size
>= 1U << 31)
933 exit_err("invalid data block size");
935 if (hash_block_size
< 512 || (hash_block_size
& (hash_block_size
- 1)) || hash_block_size
>= 1U << 31)
936 exit_err("invalid hash block size");
938 if (data_blocks
< 0 || (off_t
)data_blocks
< 0 || (off_t
)data_blocks
!= data_blocks
)
939 exit_err("invalid number of data blocks");
941 data_file_blocks
= get_size(data_file
, data_device
) / data_block_size
;
942 hash_file_blocks
= get_size(hash_file
, hash_device
) / hash_block_size
;
944 if (data_file_blocks
< data_blocks
)
945 exit_err("data file is too small");
946 if (data_blocks_string
)
947 data_file_blocks
= data_blocks
;
949 if (use_superblock
) {
950 hash_start
= hash_start
+ (sizeof(struct superblock
) + 511) / 512;
951 hash_start
= (hash_start
+ (hash_block_size
/ 512 - 1)) & ~(long long)(hash_block_size
/ 512 - 1);
954 if ((unsigned long long)hash_start
* 512 % hash_block_size
)
955 exit_err("hash start not aligned on block size");
958 hash_algorithm
= "sha256";
959 if (strlen(hash_algorithm
) >= sizeof(superblock
.algorithm
) && use_superblock
)
960 exit_err("hash algorithm name is too long");
962 digest_size
= hash_init(hash_algorithm
);
963 if (!digest_size
) exit_err("hash algorithm %s not found", hash_algorithm
);
966 salt_size
= DEFAULT_SALT_SIZE
;
967 salt_bytes
= xmalloc(salt_size
);
968 crypto_rand_bytes(salt_bytes
, salt_size
);
971 calculated_digest
= xmalloc(digest_size
);
973 if (mode
!= MODE_CREATE
) {
974 get_hex(root_hash
, &root_hash_bytes
, digest_size
, "root_hash");
977 calculate_positions();
981 if (use_superblock
) {
982 if (mode
== MODE_CREATE
)
989 if (mode
== MODE_ACTIVATE
&& !retval
)
993 free(calculated_digest
);
994 if (mode
!= MODE_CREATE
)
995 free(root_hash_bytes
);
996 poptFreeContext(popt_context
);