| // Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by the GPL v2 license that can |
| // be found in the LICENSE file. |
| // |
| // Driver program for creating verity hash images. |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #include "verity/file_hasher.h" |
| #include "verity/logging.h" |
| #include "verity/simple_file/env.h" |
| #include "verity/simple_file/file.h" |
| #include "verity/utils.h" |
| |
| namespace { |
| void print_usage(const char* name) { |
| // We used to advertise more algorithms, but they've never been implemented: |
| // sha512 sha384 sha mdc2 ripemd160 md4 md2 |
| fprintf( |
| stderr, |
| "Usage:\n" |
| " %s <arg>=<value>...\n" |
| "Options:\n" |
| " mode One of 'create' or 'verify'\n" |
| " alg Hash algorithm to use. One of:\n" |
| " sha256 sha224 sha1 md5\n" |
| " payload Path to the image to hash\n" |
| " payload_blocks Size of the image, in blocks (4096 bytes)\n" |
| " hashtree Path to a hash tree to create or read from\n" |
| " root_hexdigest Digest of the root node (in hex) for verification\n" |
| " salt Salt (in hex)\n" |
| "\n", |
| name); |
| } |
| |
| typedef enum { VERITY_NONE = 0, VERITY_CREATE, VERITY_VERIFY } verity_mode_t; |
| |
| static unsigned int parse_blocks(const char* block_s) { |
| return (unsigned int)strtoul(block_s, NULL, 0); |
| } |
| } // namespace |
| |
| static int verity_create(const char* alg, |
| const char* image_path, |
| unsigned int image_blocks, |
| const char* hash_path, |
| const char* salt); |
| |
| void splitarg(char* arg, char** key, char** val) { |
| char* sp = NULL; |
| *key = strtok_r(arg, "=", &sp); |
| *val = strtok_r(NULL, "=", &sp); |
| } |
| |
| int main(int argc, char** argv) { |
| verity_mode_t mode = VERITY_CREATE; |
| const char* alg = NULL; |
| const char* payload = NULL; |
| const char* hashtree = NULL; |
| const char* salt = NULL; |
| unsigned int payload_blocks = 0; |
| int i; |
| char *key, *val; |
| |
| for (i = 1; i < argc; i++) { |
| splitarg(argv[i], &key, &val); |
| if (!key) |
| continue; |
| if (!val) { |
| fprintf(stderr, "missing value: %s\n", key); |
| print_usage(argv[0]); |
| return -1; |
| } |
| if (!strcmp(key, "alg")) { |
| alg = val; |
| } else if (!strcmp(key, "payload")) { |
| payload = val; |
| } else if (!strcmp(key, "payload_blocks")) { |
| payload_blocks = parse_blocks(val); |
| } else if (!strcmp(key, "hashtree")) { |
| hashtree = val; |
| } else if (!strcmp(key, "root_hexdigest")) { |
| // Silently drop root_hexdigest for now... |
| } else if (!strcmp(key, "mode")) { |
| // Silently drop the mode for now... |
| } else if (!strcmp(key, "salt")) { |
| salt = val; |
| } else { |
| fprintf(stderr, "bogus key: '%s'\n", key); |
| print_usage(argv[0]); |
| return -1; |
| } |
| } |
| |
| if (!alg || !payload || !hashtree) { |
| fprintf(stderr, "missing data: %s%s%s\n", alg ? "" : "alg ", |
| payload ? "" : "payload ", hashtree ? "" : "hashtree"); |
| print_usage(argv[0]); |
| return -1; |
| } |
| |
| if (mode == VERITY_CREATE) { |
| return verity_create(alg, payload, payload_blocks, hashtree, salt); |
| } else { |
| LOG(FATAL) << "Verification not done yet"; |
| } |
| return -1; |
| } |
| |
| static int verity_create(const char* alg, |
| const char* image_path, |
| unsigned int image_blocks, |
| const char* hash_path, |
| const char* salt) { |
| // Configure files |
| simple_file::Env env; |
| |
| simple_file::File source; |
| LOG_IF(FATAL, !source.Initialize(image_path, O_RDONLY, &env)) |
| << "Failed to open the source file: " << image_path; |
| simple_file::File destination; |
| LOG_IF(FATAL, |
| !destination.Initialize(hash_path, O_CREAT | O_RDWR | O_TRUNC, &env)) |
| << "Failed to open destination file: " << hash_path; |
| |
| // Create the actual worker and create the hash image. |
| verity::FileHasher hasher; |
| LOG_IF(FATAL, !hasher.Initialize(&source, &destination, image_blocks, alg)) |
| << "Failed to initialize hasher"; |
| if (salt) |
| hasher.set_salt(salt); |
| LOG_IF(FATAL, !hasher.Hash()) << "Failed to hash hasher"; |
| LOG_IF(FATAL, !hasher.Store()) << "Failed to store hasher"; |
| hasher.PrintTable(true); |
| return 0; |
| } |