From: Niels Möller Date: Wed, 23 Mar 2011 12:01:11 +0000 (+0100) Subject: * tools/Makefile.in (TARGETS): Added nettle-hash, and related X-Git-Tag: nettle_2.2_release_20110711~110 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=802185441bf2766e898ef4ad93d8c6273132ad74;p=thirdparty%2Fnettle.git * tools/Makefile.in (TARGETS): Added nettle-hash, and related build rules. (SOURCES): Added nettle-hash.c. * tools/nettle-hash.c: New file. Rev: nettle/tools/Makefile.in:1.5 Rev: nettle/tools/nettle-hash.c:1.1 --- diff --git a/tools/Makefile.in b/tools/Makefile.in index 4115b4e1..5ca73b20 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -18,7 +18,7 @@ PRE_CPPFLAGS = -I.. -I$(top_srcdir) PRE_LDFLAGS = -L.. HOGWEED_TARGETS = pkcs1-conv$(EXEEXT) -TARGETS = sexp-conv$(EXEEXT) nettle-lfib-stream$(EXEEXT) \ +TARGETS = sexp-conv$(EXEEXT) nettle-hash$(EXEEXT) nettle-lfib-stream$(EXEEXT) \ @IF_HOGWEED@ $(HOGWEED_TARGETS) all: $(TARGETS) @@ -26,8 +26,9 @@ all: $(TARGETS) sexp_conv_SOURCES = sexp-conv.c input.c output.c parse.c \ getopt.c getopt1.c misc.c pkcs1_conv_SOURCES = pkcs1-conv.c getopt.c getopt1.c misc.c +nettle_hash_SOURCES = nettle-hash.c getopt.c getopt1.c misc.c -SOURCES = $(sexp_conv_SOURCES) nettle-lfib-stream.c pkcs1-conv.c +SOURCES = $(sexp_conv_SOURCES) nettle-hash.c nettle-lfib-stream.c pkcs1-conv.c DISTFILES = $(SOURCES) Makefile.in getopt.h input.h misc.h output.h parse.h @@ -42,6 +43,12 @@ pkcs1_conv_OBJS = $(pkcs1_conv_SOURCES:.c=.$(OBJEXT)) pkcs1-conv$(EXEEXT): $(pkcs1_conv_OBJS) ../libnettle.a ../libhogweed.a $(LINK) $(pkcs1_conv_OBJS) -lhogweed -lnettle $(LIBS) -o $@ +# FIXME: Avoid linking with gmp +nettle_hash_OBJS = $(nettle_hash_SOURCES:.c=.$(OBJEXT)) +nettle-hash$(EXEEXT): $(nettle_hash_OBJS) ../libnettle.a + $(LINK) $(nettle_hash_OBJS) -lnettle $(LIBS) -o $@ + + .c.$(OBJEXT): $(COMPILE) -c $< && $(DEP_PROCESS) diff --git a/tools/nettle-hash.c b/tools/nettle-hash.c new file mode 100644 index 00000000..2874bb97 --- /dev/null +++ b/tools/nettle-hash.c @@ -0,0 +1,246 @@ +/* nettle-hash.c + * + * General hashing tool. */ + +/* nettle, low-level cryptographics library + * + * Copyright (C) 2011 Niels Möller + * + * The nettle library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * The nettle library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the nettle library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#include "nettle-meta.h" +#include "base16.h" + +#include "getopt.h" +#include "misc.h" + +#define BUFSIZE 16384 + +static void +list_algorithms (void) +{ + unsigned i; + const struct nettle_hash *alg; + printf ("%10s digestsize (internal block size), in units of octest\n", "name"); + + for (i = 0; (alg = nettle_hashes[i]); i++) + printf ("%10s %d (%d)\n", + alg->name, alg->digest_size, alg->block_size); +}; + +static const struct nettle_hash * +find_algorithm (const char *name) +{ + size_t length = strlen (name); + const struct nettle_hash *alg; + const struct nettle_hash *found = NULL; + unsigned i; + + for (i = 0; (alg = nettle_hashes[i]); i++) + { + if (!strncmp(name, alg->name, length)) + { + /* Luckily, no valid algorithm name is a prefix of any + other, so we don't need to handle exact matches + specially. */ + + if (found) + die("Hash algorithm `%s' is ambiguous (%s or %s or ...?).\n" + "Use nettle-hash --list to list all available algorithms.\n", + name, alg->name, found->name); + found = alg; + } + } + if (!found) + die("Hash algorithm `%s' is not supported.\n" + "Use nettle-hash --list to list all available algorithms.\n", + name); + return found; +} + +/* Also in examples/io.c */ +static int +hash_file(const struct nettle_hash *hash, void *ctx, FILE *f) +{ + for (;;) + { + char buffer[BUFSIZE]; + size_t res = fread(buffer, 1, sizeof(buffer), f); + if (ferror(f)) + return 0; + + hash->update(ctx, res, buffer); + if (feof(f)) + return 1; + } +} + +static int +digest_file(const struct nettle_hash *alg, + unsigned digest_length, int raw, + FILE *f) +{ + void *ctx; + uint8_t *digest; + ctx = xalloc(alg->context_size); + + alg->init(ctx); + + if (!hash_file (alg, ctx, f)) + { + free (ctx); + return 0; + } + + digest = xalloc(digest_length); + alg->digest(ctx, digest_length, digest); + free(ctx); + + if (raw) + fwrite (digest, digest_length, 1, stdout); + + else + { + unsigned i; + char *hex = xalloc(BASE16_ENCODE_LENGTH(8) + 1); + for (i = 0; i + 8 < digest_length; i += 8) + { + base16_encode_update(hex, 8, digest + i); + hex[BASE16_ENCODE_LENGTH(8)] = 0; + printf("%s ", hex); + } + base16_encode_update(hex, digest_length - i, digest + i); + hex[BASE16_ENCODE_LENGTH(digest_length - i)] = 0; + printf("%s %s\n", hex, alg->name); + free(hex); + } + + free(digest); + + return 1; +} + +int +main (int argc, char **argv) +{ + const char *alg_name = NULL; + const struct nettle_hash *alg; + unsigned length = 0; + int raw = 0; + int c; + + enum { OPT_HELP = 0x300, OPT_RAW, OPT_LIST }; + static const struct option options[] = + { + /* Name, args, flag, val */ + { "help", no_argument, NULL, OPT_HELP }, + { "version", no_argument, NULL, 'V' }, + { "algorithm", required_argument, NULL, 'a' }, + { "length", required_argument, NULL, 'l' }, + { "list", no_argument, NULL, OPT_LIST }, + { "raw", no_argument, NULL, OPT_RAW }, + + { NULL, 0, NULL, 0 } + }; + + while ( (c = getopt_long(argc, argv, "Va:l:", options, NULL)) != -1) + switch (c) + { + default: + abort(); + case OPT_HELP: + printf("nettle-hash -a ALGORITHM [OPTIONS] [FILE ...]\n" + "Options:\n" + " --help Show this help.\n" + " -V, --version Show version information.\n" + " --list List supported hash algorithms.\n" + " -a, --algorithm=ALG Hash algorithm to use.\n" + " -l, --length=LENGTH Desired digest length (octets)\n" + " --raw Raw binary output.\n"); + return EXIT_SUCCESS; + case 'V': + printf("nettle-hash (" PACKAGE_STRING ")\n"); + return EXIT_SUCCESS; + case 'a': + alg_name = optarg; + break; + case 'l': + { + int arg; + arg = atoi (optarg); + if (arg <= 0) + die ("Invalid length argument: `%s'\n", optarg); + length = arg; + } + break; + case OPT_RAW: + raw = 1; + break; + case OPT_LIST: + list_algorithms(); + return EXIT_SUCCESS; + } + + if (!alg_name) + die("Algorithm argument (-a option) is mandatory.\n" + "See nettle-hash --help for further information.\n"); + + alg = find_algorithm (alg_name); + if (!alg) + die("Hash algorithm `%s' not supported or .\n" + "Use nettle-hash --list to list available algorithms.\n", + alg_name); + + if (length == 0) + length = alg->digest_size; + else if (length > alg->digest_size) + die ("Length argument %d too large for selected algorithm.\n", + length); + + argv += optind; + argc -= optind; + + if (argc == 0) + digest_file (alg, length, raw, stdin); + else + { + int i; + for (i = 0; i < argc; i++) + { + FILE *f = fopen (argv[i], "rb"); + if (!f) + die ("Cannot open `%s': %s\n", argv[i], STRERROR(errno)); + printf("%s: ", argv[i]); + if (!digest_file (alg, length, raw, f)) + die("Reading `%s' failed: %s\n", argv[i], STRERROR(errno)); + fclose(f); + } + } + if (fflush(stdout) != 0 ) + die("Write failed: %s\n", STRERROR(errno)); + + return EXIT_SUCCESS; +}