-/* $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 <tedu@openbsd.org>
*
#include <sha2.h>
#include "crypto_api.h"
+#ifndef VERIFY_ONLY
+#include <stdint.h>
+#include <stddef.h>
+#include <ohash.h>
+#endif
#define SIGBYTES crypto_sign_ed25519_BYTES
#define SECRETBYTES crypto_sign_ed25519_SECRETKEYBYTES
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");
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