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:
parent
df4b6f133b
commit
b0be99fc10
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
int __do_digest(struct digest *d, unsigned char *key, int keylen,
|
||||
unsigned char *sig,
|
||||
int argc, char *argv[]);
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue