From e96025a183d0d6ef0ecd68a317e35a8ae21bb8c9 Mon Sep 17 00:00:00 2001 From: espie Date: Fri, 16 May 2014 16:18:33 +0000 Subject: [PATCH] rework -C (perfect candidate for using hash tables, really): insert files we want to check into a hash, parse SHA256 message on the fly, delete entries whose checksum match, then display entries that failed. This completely avoids allocating temporary storage for file names and checksums and removes the quadratic match (argv[i] vs line[n]). okay tedu@ --- usr.bin/signify/signify.c | 162 +++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 72 deletions(-) diff --git a/usr.bin/signify/signify.c b/usr.bin/signify/signify.c index e5cdfb4abd1..f91dc575152 100644 --- a/usr.bin/signify/signify.c +++ b/usr.bin/signify/signify.c @@ -1,4 +1,4 @@ -/* $OpenBSD: signify.c,v 1.84 2014/05/15 13:14:15 espie Exp $ */ +/* $OpenBSD: signify.c,v 1.85 2014/05/16 16:18:33 espie Exp $ */ /* * Copyright (c) 2013 Ted Unangst * @@ -31,6 +31,11 @@ #include #include "crypto_api.h" +#ifndef VERIFY_ONLY +#include +#include +#include +#endif #define SIGBYTES crypto_sign_ed25519_BYTES #define SECRETBYTES crypto_sign_ed25519_SECRETKEYBYTES @@ -538,14 +543,28 @@ struct checksum { char algo[32]; }; +static void * +ecalloc(size_t s1, size_t s2, void *data) +{ + void *p = calloc(s1, s2); + if (!p) + err(1, "calloc"); + return p; +} + +static void +efree(void *p, void *data) +{ + free(p); +} + static void -recodehash(char *hash) +recodehash(char *hash, size_t len) { uint8_t data[HASHBUFSIZE / 2]; int i, rv; - if (strlen(hash)+1 == SHA256_DIGEST_STRING_LENGTH || - strlen(hash)+1 == SHA512_DIGEST_STRING_LENGTH) + if (strlen(hash) == len) return; if ((rv = b64_pton(hash, data, sizeof(data))) == -1) errx(1, "invalid base64 encoding"); @@ -553,93 +572,92 @@ recodehash(char *hash) snprintf(hash + i * 2, HASHBUFSIZE - i * 2, "%2.2x", data[i]); } +static int +verifychecksum(struct checksum *c, int quiet) +{ + char buf[HASHBUFSIZE]; + if (strcmp(c->algo, "SHA256") == 0) { + recodehash(c->hash, SHA256_DIGEST_STRING_LENGTH-1); + if (!SHA256File(c->file, buf)) + return 0; + } else if (strcmp(c->algo, "SHA512") == 0) { + recodehash(c->hash, SHA512_DIGEST_STRING_LENGTH-1); + if (!SHA512File(c->file, buf)) + return 0; + } else { + errx(1, "can't handle algorithm %s", c->algo); + } + if (strcmp(c->hash, buf) != 0) { + return 0; + } + if (!quiet) + printf("%s: OK\n", c->file); + return 1; +} + static void verifychecksums(char *msg, int argc, char **argv, int quiet) { - char buf[1024]; + + struct ohash_info info = { 0, NULL, ecalloc, efree, NULL }; + struct ohash myh; + unsigned int i; + struct checksum c; char *line, *endline; - struct checksum *checksums = NULL, *c = NULL; - int nchecksums = 0, checksumspace = 0; - int i, j, rv, uselist, count, hasfailed; - int *failures; + int hasfailed = 0; + int rv; + const char *e; + unsigned int slot; + + + if (argc) { + ohash_init(&myh, 6, &info); + for (i = 0; i < argc; i++) { + slot = ohash_qlookup(&myh, argv[i]); + e = ohash_find(&myh, slot); + if (e == NULL) + ohash_insert(&myh, slot, argv[i]); + } + } line = msg; while (line && *line) { - if (nchecksums == checksumspace) { - checksumspace = 2 * (nchecksums + 1); - if (!(checksums = reallocarray(checksums, - checksumspace, sizeof(*checksums)))) - err(1, "realloc"); - } - c = &checksums[nchecksums++]; if ((endline = strchr(line, '\n'))) *endline++ = '\0'; - rv = sscanf(line, "%31s %1023s = %223s", - c->algo, buf, c->hash); - if (rv != 3 || buf[0] != '(' || buf[strlen(buf) - 1] != ')') + rv = sscanf(line, "%31s (%1023s = %223s", + c.algo, c.file, c.hash); + if (rv != 3 || c.file[0] == 0 || c.file[strlen(c.file)-1] != ')') errx(1, "unable to parse checksum line %s", line); - recodehash(c->hash); - buf[strlen(buf) - 1] = 0; - strlcpy(c->file, buf + 1, sizeof(c->file)); + c.file[strlen(c.file) - 1] = 0; line = endline; - } - - if (argc) { - uselist = 0; - count = argc; - } else { - uselist = 1; - count = nchecksums; - } - if (!(failures = calloc(count, sizeof(*failures)))) - err(1, "calloc"); - for (i = 0; i < count; i++) { - if (uselist) { - c = &checksums[i]; - } else { - for (j = 0; j < nchecksums; j++) { - c = &checksums[j]; - if (strcmp(c->file, argv[i]) == 0) - break; + if (argc) { + slot = ohash_qlookup(&myh, c.file); + e = ohash_find(&myh, slot); + if (e != NULL) { + if (verifychecksum(&c, quiet)) + ohash_remove(&myh, slot); } - if (j == nchecksums) { - failures[i] = 1; - continue; + } else { + if (!verifychecksum(&c, quiet)) { + fprintf(stderr, "%s: FAIL\n", c.file); + hasfailed = 1; } } + } - if (strcmp(c->algo, "SHA256") == 0) { - if (!SHA256File(c->file, buf)) { - failures[i] = 1; - continue; - } - } else if (strcmp(c->algo, "SHA512") == 0) { - if (!SHA512File(c->file, buf)) { - failures[i] = 1; - continue; + if (argc) { + for (i = 0; i < argc; i++) { + slot = ohash_qlookup(&myh, argv[i]); + e = ohash_find(&myh, slot); + if (e != NULL) { + fprintf(stderr, "%s: FAIL\n", argv[i]); + hasfailed = 1; } - } else { - errx(1, "can't handle algorithm %s", c->algo); - } - if (strcmp(c->hash, buf) != 0) { - failures[i] = 1; - continue; - } - if (!quiet) - printf("%s: OK\n", c->file); - } - hasfailed = 0; - for (i = 0; i < count; i++) { - if (failures[i]) { - fprintf(stderr, "%s: FAIL\n", - uselist ? checksums[i].file : argv[i]); - hasfailed = 1; - } + } + ohash_delete(&myh); } if (hasfailed) exit(1); - free(checksums); - free(failures); } static void -- 2.20.1