Annotation of src/usr.bin/gzsig/verify.c, Revision 1.3
1.3 ! djm 1: /* $OpenBSD: verify.c,v 1.2 2005/05/28 08:07:45 marius Exp $ */
1.1 marius 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: *
1.2 marius 33: * $Vendor: verify.c,v 1.3 2005/04/07 23:19:35 dugsong Exp $
1.1 marius 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: {
1.3 ! djm 147: fprintf(stderr, "Usage: gzsig verify [-q] pubkey [file ...]\n");
1.1 marius 148: }
149:
150: void
151: verify(int argc, char *argv[])
152: {
153: struct key *key;
154: char *gzipfile;
155: FILE *fin;
1.3 ! djm 156: int i, error, qflag;
1.1 marius 157:
1.3 ! djm 158: qflag = 0;
1.1 marius 159:
1.3 ! djm 160: while ((i = getopt(argc, argv, "qvh?")) != -1) {
1.1 marius 161: switch (i) {
1.3 ! djm 162: case 'q':
! 163: qflag = 1;
! 164: break;
1.1 marius 165: case 'v':
1.3 ! djm 166: qflag = 0;
1.1 marius 167: break;
168: default:
169: verify_usage();
170: exit(1);
171: }
172: }
173: argc -= optind;
174: argv += optind;
175:
176: if (argc < 1) {
177: verify_usage();
178: exit(1);
179: }
180: OpenSSL_add_all_algorithms();
181:
182: if ((key = key_new()) == NULL)
183: fatal(1, "Can't initialize public key");
184:
185: if (key_load_public(key, argv[0]) < 0)
186: fatal(1, "Can't load public key");
187:
188: if (argc == 1 || *argv[1] == '-') {
189: argc = 0;
190:
191: if (verify_signature(key, stdin) == 0) {
1.3 ! djm 192: if (!qflag)
1.1 marius 193: fprintf(stderr, "Verified input\n");
194: } else
195: fatal(1, "Couldn't verify input");
196: }
197: for (i = 1; i < argc; i++) {
198: gzipfile = argv[i];
199:
200: if ((fin = fopen(gzipfile, "r")) < 0) {
201: fprintf(stderr, "Couldn't open %s: %s\n",
202: gzipfile, strerror(errno));
203: continue;
204: }
205: error = verify_signature(key, fin);
206: fclose(fin);
207:
208: if (!error) {
1.3 ! djm 209: if (!qflag)
1.1 marius 210: fprintf(stderr, "Verified %s\n", gzipfile);
211: } else
212: fatal(1, "Couldn't verify %s", gzipfile);
213: }
214: key_free(key);
215: }