blob: 97e042c9ffc2e8bc3a093ada2951b2f4bdc5d6e3 [file] [log] [blame]
// 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;
}