[PATCH 7/7] command: add generic digest command
Sascha Hauer
s.hauer at pengutronix.de
Fri Mar 13 00:26:16 PDT 2015
On Thu, Mar 12, 2015 at 03:22:26PM +0100, Jean-Christophe PLAGNIOL-VILLARD wrote:
> That can be used for digest calculation and verify
>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
> ---
> commands/Kconfig | 12 +++-
> commands/Makefile | 1 +
> commands/digest.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> commands/hashsum.c | 68 ++++--------------
> commands/internal.h | 3 +
> common/password.c | 43 +-----------
> crypto/digest.c | 92 +++++++++++++++++++++++--
> include/digest.h | 13 +++-
> 8 files changed, 322 insertions(+), 105 deletions(-)
> create mode 100644 commands/digest.c
> create mode 100644 commands/internal.h
>
> diff --git a/commands/Kconfig b/commands/Kconfig
> index 7e3e8b7..847ff76 100644
> --- a/commands/Kconfig
> +++ b/commands/Kconfig
> @@ -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"
> diff --git a/commands/Makefile b/commands/Makefile
> index e42662f..b902f58 100644
> --- a/commands/Makefile
> +++ b/commands/Makefile
> @@ -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
> diff --git a/commands/digest.c b/commands/digest.c
> new file mode 100644
> index 0000000..e9b4e66
> --- /dev/null
> +++ b/commands/digest.c
> @@ -0,0 +1,195 @@
> +/*
> + * Copyright (c) 2015 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at 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 = 0;
> + int i;
> + unsigned char *hash;
> +
> + 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[1] && !parse_area_spec(argv[1], &start, &size))
> + argv++;
> + }
> +
> + ret = digest_file_window(d, filename,
> + key, keylen,
> + 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);
> + digest_free(d);
> +
> + return ret;
> +}
> +
> +static void __prints_algo(void)
> +{
> + puts("available algo:\n\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, ret;
> +
> + if (argc < 2) {
> + __prints_algo();
> + return 0;
> + }
This is an untuitive trigger to print the available algos. Can we add an
explicit option here?
> +
> + 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);
> + __prints_algo();
> + return COMMAND_ERROR_USAGE;
> + }
> +
> + argc -= optind;
> + argv += optind;
> +
> + if (keyfile) {
> + tmp_key = key = read_file(keyfile, &keylen);
Why two variables? Both tmp_key and key are never changed.
> + if (!key) {
> + eprintf("file '%s' not found\n", keyfile);
> + goto err;
> + }
> + }
> +
> + digest_set_key(d, key, keylen);
This can fail. You should check the error code.
> +unsigned char to_digit(unsigned char c)
> +{
> + if (c >= '0' && c <= '9')
> + c -= '0';
> + else
> + c -= 'a' - 10;
> +
> + return c;
> +}
> +
> +unsigned char to_hexa(unsigned char c)
> +{
> + if (c < 10)
> + c += '0';
> + else
> + c += 'a' - 10;
> +
> + return c;
> +}
> +
> +int base64_to_hex(const unsigned char *sum, unsigned char *buf, size_t length)
> +{
The ASCII input here contains hex digits, base64 is something different.
Also these functions are useful enough to be always available, not only
when digest is enabled.
I just sent a patch containing the kernels implementation of bin2hex and
hex2bin. Please base on this one.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the barebox
mailing list