From b0be99fc10e50c41b75647a2486c05f9bd47f1c3 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Tue, 17 Mar 2015 12:53:16 +0100 Subject: command: add generic digest command That can be used for digest calculation and verify Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- commands/digest.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 commands/digest.c (limited to 'commands/digest.c') diff --git a/commands/digest.c b/commands/digest.c new file mode 100644 index 0000000000..ef95e94816 --- /dev/null +++ b/commands/digest.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2015 Jean-Christophe PLAGNIOL-VILLARD + * + * GPLv2 ONLY + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internal.h" + +int __do_digest(struct digest *d, unsigned char *key, int keylen, + unsigned char *sig, + int argc, char *argv[]) +{ + int ret = COMMAND_ERROR_USAGE; + int i; + unsigned char *hash; + + if (argc < 1) + goto err; + + if (key) { + ret = digest_set_key(d, key, keylen); + if (ret) { + perror("set_key"); + goto err; + } + } + + hash = calloc(digest_length(d), sizeof(unsigned char)); + if (!hash) { + perror("calloc"); + goto err; + } + + while (*argv) { + char *filename = "/dev/mem"; + loff_t start = 0, size = ~0; + + /* arguments are either file, file+area or area */ + if (parse_area_spec(*argv, &start, &size)) { + filename = *argv; + if (argv[1] && !parse_area_spec(argv[1], &start, &size)) + argv++; + } + + ret = digest_file_window(d, filename, + hash, sig, start, size); + if (ret < 0) { + ret = 1; + } else { + if (!sig) { + for (i = 0; i < digest_length(d); i++) + printf("%02x", hash[i]); + + printf(" %s\t0x%08llx ... 0x%08llx\n", + filename, start, start + size); + } + } + + argv++; + } + + free(hash); +err: + digest_free(d); + + return ret; +} + +static void prints_algo_help(void) +{ + puts("\navailable algo:\n"); + digest_algo_prints("\t"); +} + +static int do_digest(int argc, char *argv[]) +{ + struct digest *d; + unsigned char *tmp_key = NULL; + unsigned char *tmp_sig = NULL; + char *sig = NULL; + char *sigfile = NULL; + size_t siglen = 0; + char *key = NULL; + char *keyfile = NULL; + size_t keylen = 0; + size_t digestlen = 0; + char *algo = NULL; + int opt; + int ret = COMMAND_ERROR; + + if (argc < 2) + return COMMAND_ERROR_USAGE; + + while((opt = getopt(argc, argv, "a:k:K:s:S:")) > 0) { + switch(opt) { + case 'k': + key = optarg; + keylen = strlen(key); + break; + case 'K': + keyfile = optarg; + break; + case 'a': + algo = optarg; + break; + case 's': + sig = optarg; + siglen = strlen(sig); + break; + case 'S': + sigfile = optarg; + break; + } + } + + if (!algo) + return COMMAND_ERROR_USAGE; + + d = digest_alloc(algo); + if (!d) { + eprintf("algo '%s' not found\n", algo); + return COMMAND_ERROR_USAGE; + } + + argc -= optind; + argv += optind; + + if (keyfile) { + tmp_key = key = read_file(keyfile, &keylen); + if (!key) { + eprintf("file '%s' not found\n", keyfile); + goto err; + } + } + + ret = digest_set_key(d, key, keylen); + free(tmp_key); + if (ret) + goto err; + + if (sigfile) { + sig = tmp_sig = read_file(sigfile, &siglen); + if (!tmp_sig) { + eprintf("file '%s' not found\n", sigfile); + goto err; + } + } + + if (sig) { + digestlen = digest_length(d); + if (siglen == 2 * digestlen) { + if (!tmp_sig) + tmp_sig = xmalloc(digestlen); + + ret = hex2bin(tmp_sig, sig, digestlen); + if (ret) + goto err; + + sig = tmp_sig; + } else if (siglen != digestlen) { + eprintf("%s wrong size %zu, expected %zu\n", + sigfile, siglen, digestlen); + goto err; + } + } + + ret = __do_digest(d, NULL, 0, sig, argc, argv); + free(tmp_sig); + return ret; + +err: + digest_free(d); + return ret; +} + +BAREBOX_CMD_HELP_START(digest) +BAREBOX_CMD_HELP_TEXT("Calculate a digest over a FILE or a memory area.") +BAREBOX_CMD_HELP_TEXT("Options:") +BAREBOX_CMD_HELP_OPT ("-a \t", "hash or signature algorithm to use") +BAREBOX_CMD_HELP_OPT ("-k \t", "use supplied (ASCII or hex) for MAC") +BAREBOX_CMD_HELP_OPT ("-K \t", "use key from (binary) for MAC") +BAREBOX_CMD_HELP_OPT ("-v \t", "verify data against supplied (hash, MAC or signature)") +BAREBOX_CMD_HELP_OPT ("-V \t", "verify data against (hash, MAC or signature)") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(digest) + .cmd = do_digest, + BAREBOX_CMD_DESC("calculate digest") + BAREBOX_CMD_OPTS("-a [-k | -K ] [-s | -S ] FILE|AREA") + BAREBOX_CMD_GROUP(CMD_GRP_FILE) + BAREBOX_CMD_HELP(cmd_digest_help) + BAREBOX_CMD_USAGE(prints_algo_help) +BAREBOX_CMD_END -- cgit v1.2.3