Annotation of src/usr.bin/gzsig/verify.c, Revision 1.1
1.1 ! marius 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * verify.c
! 5: *
! 6: * Copyright (c) 2001 Dug Song <dugsong@arbor.net>
! 7: * Copyright (c) 2001 Arbor Networks, Inc.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: *
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. The names of the copyright holders may not be used to endorse or
! 19: * promote products derived from this software without specific
! 20: * prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! 23: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
! 24: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
! 25: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 26: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 27: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 28: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 29: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 30: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 31: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 32: *
! 33: * $Id: verify.c,v 1.3 2005/04/07 23:19:35 dugsong Exp $
! 34: */
! 35:
! 36: #include <sys/types.h>
! 37:
! 38: #include <openssl/ssl.h>
! 39: #include <openssl/evp.h>
! 40: #include <openssl/sha.h>
! 41:
! 42: #include <errno.h>
! 43: #include <stdio.h>
! 44: #include <stdlib.h>
! 45: #include <string.h>
! 46: #include <unistd.h>
! 47:
! 48: #include "extern.h"
! 49: #include "gzip.h"
! 50: #include "key.h"
! 51: #include "util.h"
! 52:
! 53: static int
! 54: verify_signature(struct key *key, FILE *fin)
! 55: {
! 56: struct gzip_header gh;
! 57: struct gzip_xfield *gx;
! 58: struct gzsig_data *gd;
! 59: u_char *sig, digest[20], buf[8192], sbuf[4096];
! 60: SHA_CTX ctx;
! 61: int i, siglen;
! 62:
! 63: /* Read gzip header. */
! 64: if ((i = fread((u_char *)&gh, 1, sizeof(gh), fin)) != sizeof(gh)) {
! 65: fprintf(stderr, "Error reading gzip header: %s\n",
! 66: strerror(errno));
! 67: return (-1);
! 68: }
! 69: /* Verify gzip header. */
! 70: if (memcmp(gh.magic, GZIP_MAGIC, sizeof(gh.magic)) != 0) {
! 71: fprintf(stderr, "Invalid gzip file\n");
! 72: return (-1);
! 73: } else if (gh.flags & GZIP_FCONT){
! 74: fprintf(stderr, "Multi-part gzip files not supported\n");
! 75: return (-1);
! 76: } else if ((gh.flags & GZIP_FEXTRA) == 0) {
! 77: fprintf(stderr, "No gzip signature found\n");
! 78: return (-1);
! 79: }
! 80: /* Read signature. */
! 81: gx = (struct gzip_xfield *)buf;
! 82:
! 83: if ((i = fread((u_char *)gx, 1, sizeof(*gx), fin)) != sizeof(*gx)) {
! 84: fprintf(stderr, "Error reading extra field: %s\n",
! 85: strerror(errno));
! 86: return (-1);
! 87: }
! 88: if (memcmp(gx->subfield.id, GZSIG_ID, sizeof(gx->subfield.id)) != 0) {
! 89: fprintf(stderr, "Unknown extra field\n");
! 90: return (-1);
! 91: }
! 92: gx->subfield.len = letoh16(gx->subfield.len);
! 93:
! 94: if (gx->subfield.len <= 0 || gx->subfield.len > sizeof(sbuf)) {
! 95: fprintf(stderr, "Invalid signature length\n");
! 96: return (-1);
! 97: }
! 98: gd = (struct gzsig_data *)sbuf;
! 99:
! 100: if ((i = fread((u_char *)gd, 1, gx->subfield.len, fin)) !=
! 101: gx->subfield.len) {
! 102: fprintf(stderr, "Error reading signature: %s\n",
! 103: strerror(errno));
! 104: return (-1);
! 105: }
! 106: /* Skip over any options. */
! 107: if (gh.flags & GZIP_FNAME) {
! 108: while (getc(fin) != '\0')
! 109: ;
! 110: }
! 111: if (gh.flags & GZIP_FCOMMENT) {
! 112: while (getc(fin) != '\0')
! 113: ;
! 114: }
! 115: if (gh.flags & GZIP_FENCRYPT &&
! 116: fread(buf, 1, GZIP_FENCRYPT_LEN, fin) != GZIP_FENCRYPT_LEN)
! 117: return (-1);
! 118:
! 119: /* Check signature version. */
! 120: if (gd->version != GZSIG_VERSION) {
! 121: fprintf(stderr, "Unknown signature version: %d\n",
! 122: gd->version);
! 123: return (-1);
! 124: }
! 125: /* Compute SHA1 checksum over compressed data and trailer. */
! 126: sig = (u_char *)(gd + 1);
! 127: siglen = gx->subfield.len - sizeof(*gd);
! 128:
! 129: SHA1_Init(&ctx);
! 130:
! 131: while ((i = fread(buf, 1, sizeof(buf), fin)) > 0) {
! 132: SHA1_Update(&ctx, buf, i);
! 133: }
! 134: SHA1_Final(digest, &ctx);
! 135:
! 136: /* Verify signature. */
! 137: if (key_verify(key, digest, sizeof(digest), sig, siglen) < 0) {
! 138: fprintf(stderr, "Error verifying signature\n");
! 139: return (-1);
! 140: }
! 141: return (0);
! 142: }
! 143:
! 144: void
! 145: verify_usage(void)
! 146: {
! 147: fprintf(stderr, "Usage: gzsig verify [-v] pubkey [file ...]\n");
! 148: }
! 149:
! 150: void
! 151: verify(int argc, char *argv[])
! 152: {
! 153: struct key *key;
! 154: char *gzipfile;
! 155: FILE *fin;
! 156: int i, error, vflag;
! 157:
! 158: vflag = 0;
! 159:
! 160: while ((i = getopt(argc, argv, "vh?")) != -1) {
! 161: switch (i) {
! 162: case 'v':
! 163: vflag = 1;
! 164: break;
! 165: default:
! 166: verify_usage();
! 167: exit(1);
! 168: }
! 169: }
! 170: argc -= optind;
! 171: argv += optind;
! 172:
! 173: if (argc < 1) {
! 174: verify_usage();
! 175: exit(1);
! 176: }
! 177: OpenSSL_add_all_algorithms();
! 178:
! 179: if ((key = key_new()) == NULL)
! 180: fatal(1, "Can't initialize public key");
! 181:
! 182: if (key_load_public(key, argv[0]) < 0)
! 183: fatal(1, "Can't load public key");
! 184:
! 185: if (argc == 1 || *argv[1] == '-') {
! 186: argc = 0;
! 187:
! 188: if (verify_signature(key, stdin) == 0) {
! 189: if (vflag)
! 190: fprintf(stderr, "Verified input\n");
! 191: } else
! 192: fatal(1, "Couldn't verify input");
! 193: }
! 194: for (i = 1; i < argc; i++) {
! 195: gzipfile = argv[i];
! 196:
! 197: if ((fin = fopen(gzipfile, "r")) < 0) {
! 198: fprintf(stderr, "Couldn't open %s: %s\n",
! 199: gzipfile, strerror(errno));
! 200: continue;
! 201: }
! 202: error = verify_signature(key, fin);
! 203: fclose(fin);
! 204:
! 205: if (!error) {
! 206: if (vflag)
! 207: fprintf(stderr, "Verified %s\n", gzipfile);
! 208: } else
! 209: fatal(1, "Couldn't verify %s", gzipfile);
! 210: }
! 211: key_free(key);
! 212: }