9
0
Fork 0

command: add generic digest command

That can be used for digest calculation and verify

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Jean-Christophe PLAGNIOL-VILLARD 2015-03-17 12:53:16 +01:00 committed by Sascha Hauer
parent df4b6f133b
commit b0be99fc10
7 changed files with 264 additions and 73 deletions

View File

@ -14,7 +14,7 @@ if COMMAND_SUPPORT
config COMPILE_HASH
tristate
select DIGEST
select CMD_DIGEST
help
Turns on compilation of digest.c
@ -842,6 +842,16 @@ config CMD_CMP
Returns successfully if the two files are the same, return with an error if not
config CMD_DIGEST
tristate
select DIGEST
prompt "digest"
help
Usage: digest -a <algo> [-k <key> | -K <file>] [-s <sig> | -S <file>] FILE|AREA
Calculate a digest over a FILE or a memory area with the possibility
to checkit.
config CMD_DIRNAME
tristate
prompt "dirname"

View File

@ -1,4 +1,5 @@
obj-$(CONFIG_STDDEV) += stddev.o
obj-$(CONFIG_CMD_DIGEST) += digest.o
obj-$(CONFIG_COMPILE_HASH) += hashsum.o
obj-$(CONFIG_COMPILE_MEMORY) += mem.o
obj-$(CONFIG_CMD_BOOTM) += bootm.o

204
commands/digest.c Normal file
View File

@ -0,0 +1,204 @@
/*
* 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 *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 <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

View File

@ -27,12 +27,11 @@
#include <digest.h>
#include <getopt.h>
static int do_digest(char *algorithm, int argc, char *argv[])
#include "internal.h"
static int do_hash(char *algo, int argc, char *argv[])
{
struct digest *d;
int ret = 0;
int i;
unsigned char *hash;
unsigned char *key = NULL;
size_t keylen = 0;
int opt;
@ -46,71 +45,26 @@ static int do_digest(char *algorithm, int argc, char *argv[])
}
}
if (key) {
char *tmp = asprintf("hmac(%s)", algo);
d = digest_alloc(tmp);
free(tmp);
} else {
d = digest_alloc(algo);
}
BUG_ON(!d);
argc -= optind;
argv += optind;
if (key) {
char *tmp = asprintf("hmac(%s)", algorithm);
d = digest_alloc(tmp);
BUG_ON(!d);
ret = digest_set_key(d, key, keylen);
free(tmp);
if (ret) {
perror("set_key");
goto err;
}
} else {
d = digest_alloc(algorithm);
BUG_ON(!d);
}
if (argc < 1)
return COMMAND_ERROR_USAGE;
hash = calloc(digest_length(d), sizeof(unsigned char));
if (!hash) {
perror("calloc");
return COMMAND_ERROR_USAGE;
}
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[0] && !parse_area_spec(argv[0], &start, &size))
argv++;
}
ret = digest_file_window(d, filename,
hash, start, size);
if (ret < 0) {
ret = 1;
} else {
for (i = 0; i < digest_length(d); i++)
printf("%02x", hash[i]);
printf(" %s\t0x%08llx ... 0x%08llx\n",
filename, start, start + size);
}
argv++;
}
err:
free(hash);
digest_free(d);
return ret;
return __do_digest(d, key, keylen, NULL, argc, argv);
}
#ifdef CONFIG_CMD_MD5SUM
static int do_md5(int argc, char *argv[])
{
return do_digest("md5", argc, argv);
return do_hash("md5", argc, argv);
}
BAREBOX_CMD_HELP_START(md5sum)
@ -131,7 +85,7 @@ BAREBOX_CMD_END
static int do_sha1(int argc, char *argv[])
{
return do_digest("sha1", argc, argv);
return do_hash("sha1", argc, argv);
}
BAREBOX_CMD_HELP_START(sha1sum)
@ -152,7 +106,7 @@ BAREBOX_CMD_END
static int do_sha224(int argc, char *argv[])
{
return do_digest("sha224", argc, argv);
return do_hash("sha224", argc, argv);
}
BAREBOX_CMD_HELP_START(sha224sum)
@ -173,7 +127,7 @@ BAREBOX_CMD_END
static int do_sha256(int argc, char *argv[])
{
return do_digest("sha256", argc, argv);
return do_hash("sha256", argc, argv);
}
BAREBOX_CMD_HELP_START(sha256sum)
@ -194,7 +148,7 @@ BAREBOX_CMD_END
static int do_sha384(int argc, char *argv[])
{
return do_digest("sha384", argc, argv);
return do_hash("sha384", argc, argv);
}
BAREBOX_CMD_HELP_START(sha384sum)
@ -215,7 +169,7 @@ BAREBOX_CMD_END
static int do_sha512(int argc, char *argv[])
{
return do_digest("sha512", argc, argv);
return do_hash("sha512", argc, argv);
}
BAREBOX_CMD_HELP_START(sha512sum)

3
commands/internal.h Normal file
View File

@ -0,0 +1,3 @@
int __do_digest(struct digest *d, unsigned char *key, int keylen,
unsigned char *sig,
int argc, char *argv[]);

View File

@ -124,6 +124,15 @@ static struct digest_algo *digest_algo_get_by_name(const char *name)
return NULL;
}
void digest_algo_prints(const char *prefix)
{
struct digest_algo* d;
list_for_each_entry(d, &digests, list) {
printf("%s%s\n", prefix, d->name);
}
}
struct digest *digest_alloc(const char *name)
{
struct digest *d;
@ -157,6 +166,7 @@ EXPORT_SYMBOL_GPL(digest_free);
int digest_file_window(struct digest *d, const char *filename,
unsigned char *hash,
unsigned char *sig,
ulong start, ulong size)
{
ulong len = 0;
@ -217,7 +227,10 @@ int digest_file_window(struct digest *d, const char *filename,
len += now;
}
ret = digest_final(d, hash);
if (sig)
ret = digest_verify(d, sig);
else
ret = digest_final(d, hash);
out_free:
if (flags)
@ -230,7 +243,8 @@ out:
EXPORT_SYMBOL_GPL(digest_file_window);
int digest_file(struct digest *d, const char *filename,
unsigned char *hash)
unsigned char *hash,
unsigned char *sig)
{
struct stat st;
int ret;
@ -240,12 +254,13 @@ int digest_file(struct digest *d, const char *filename,
if (ret < 0)
return ret;
return digest_file_window(d, filename, hash, 0, st.st_size);
return digest_file_window(d, filename, hash, sig, 0, st.st_size);
}
EXPORT_SYMBOL_GPL(digest_file);
int digest_file_by_name(const char *algo, const char *filename,
unsigned char *hash)
unsigned char *hash,
unsigned char *sig)
{
struct digest *d;
int ret;
@ -254,7 +269,7 @@ int digest_file_by_name(const char *algo, const char *filename,
if (!d)
return -EIO;
ret = digest_file(d, filename, hash);
ret = digest_file(d, filename, hash, sig);
digest_free(d);
return ret;
}

View File

@ -52,17 +52,21 @@ struct digest {
*/
int digest_algo_register(struct digest_algo *d);
void digest_algo_unregister(struct digest_algo *d);
void digest_algo_prints(const char *prefix);
struct digest *digest_alloc(const char *name);
void digest_free(struct digest *d);
int digest_file_window(struct digest *d, const char *filename,
unsigned char *hash,
unsigned char *sig,
ulong start, ulong size);
int digest_file(struct digest *d, const char *filename,
unsigned char *hash);
unsigned char *hash,
unsigned char *sig);
int digest_file_by_name(const char *algo, const char *filename,
unsigned char *hash);
unsigned char *hash,
unsigned char *sig);
static inline int digest_init(struct digest *d)
{