9
0
Fork 0
barebox/commands/digest.c

201 lines
4.0 KiB
C

/*
* Copyright (c) 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* GPLv2 ONLY
*/
#include <common.h>
#include <command.h>
#include <fs.h>
#include <fcntl.h>
#include <errno.h>
#include <xfuncs.h>
#include <malloc.h>
#include <digest.h>
#include <getopt.h>
#include <libfile.h>
#include "internal.h"
int __do_digest(struct digest *d, unsigned char *sig,
int argc, char *argv[])
{
int ret = COMMAND_ERROR_USAGE;
int i;
unsigned char *hash;
if (argc < 1)
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;
}
}
if (key) {
ret = digest_set_key(d, key, keylen);
free(tmp_key);
if (ret)
goto err;
} else if (digest_is_flags(d, DIGEST_ALGO_NEED_KEY)) {
eprintf("%s need a key to be used\n", digest_name(d));
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, 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 <algo>\t", "hash or signature algorithm to use")
BAREBOX_CMD_HELP_OPT ("-k <key>\t", "use supplied <key> (ASCII or hex) for MAC")
BAREBOX_CMD_HELP_OPT ("-K <file>\t", "use key from <file> (binary) for MAC")
BAREBOX_CMD_HELP_OPT ("-v <hex>\t", "verify data against supplied <hex> (hash, MAC or signature)")
BAREBOX_CMD_HELP_OPT ("-V <file>\t", "verify data against <file> (hash, MAC or signature)")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(digest)
.cmd = do_digest,
BAREBOX_CMD_DESC("calculate digest")
BAREBOX_CMD_OPTS("-a <algo> [-k <key> | -K <file>] [-s <sig> | -S <file>] FILE|AREA")
BAREBOX_CMD_GROUP(CMD_GRP_FILE)
BAREBOX_CMD_HELP(cmd_digest_help)
BAREBOX_CMD_USAGE(prints_algo_help)
BAREBOX_CMD_END