[BACK]Return to sign.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / gzsig

Annotation of src/usr.bin/gzsig/sign.c, Revision 1.3

1.3     ! djm         1: /* $OpenBSD: sign.c,v 1.2 2005/05/28 08:07:45 marius Exp $ */
1.1       marius      2:
                      3: /*
                      4:  * sign.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: sign.c,v 1.2 2005/04/01 16:47:31 dugsong Exp $
1.1       marius     34:  */
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/types.h>
                     38: #include <sys/stat.h>
                     39:
                     40: #include <openssl/ssl.h>
                     41: #include <openssl/evp.h>
                     42: #include <openssl/sha.h>
                     43:
                     44: #include <errno.h>
                     45: #include <stdio.h>
                     46: #include <stdlib.h>
                     47: #include <string.h>
                     48: #include <unistd.h>
                     49:
                     50: #include "extern.h"
                     51: #include "gzip.h"
                     52: #include "key.h"
                     53: #include "util.h"
                     54:
                     55: static char *passphrase = NULL;
                     56:
                     57: static int
                     58: embed_signature(struct key *key, FILE *fin, FILE *fout)
                     59: {
                     60:        struct gzip_header gh;
                     61:        struct gzip_xfield *gx;
                     62:        struct gzsig_data *gd;
                     63:        u_char *sig, digest[20], buf[8192];
                     64:        SHA_CTX ctx;
                     65:        int i, siglen;
                     66:        long offset;
                     67:
                     68:        /* Read gzip header. */
                     69:        if (fread((u_char *)&gh, 1, sizeof(gh), fin) != sizeof(gh)) {
                     70:                fprintf(stderr, "Error reading gzip header: %s\n",
                     71:                    strerror(errno));
                     72:                return (-1);
                     73:        }
                     74:        /* Verify gzip header. */
                     75:        if (memcmp(gh.magic, GZIP_MAGIC, sizeof(gh.magic)) != 0) {
                     76:                fprintf(stderr, "Invalid gzip file\n");
                     77:                return (-1);
                     78:        }
                     79:        if (gh.flags & GZIP_FCONT) {
                     80:                fprintf(stderr, "Multi-part gzip files not supported\n");
                     81:                return (-1);
                     82:        }
                     83:        /* Skip over any existing signature. */
                     84:        if (gh.flags & GZIP_FEXTRA) {
                     85:                gx = (struct gzip_xfield *)buf;
                     86:                gd = (struct gzsig_data *)(gx + 1);
                     87:
                     88:                if (fread((u_char *)gx, 1, sizeof(*gx), fin) != sizeof(*gx)) {
                     89:                        fprintf(stderr, "Error reading extra field: %s\n",
                     90:                            strerror(errno));
                     91:                        return (-1);
                     92:                }
                     93:                if (memcmp(gx->subfield.id, GZSIG_ID, 2) != 0) {
                     94:                        fprintf(stderr, "Unknown extra field\n");
                     95:                        return (-1);
                     96:                }
                     97:                gx->subfield.len = letoh16(gx->subfield.len);
                     98:
                     99:                if (gx->subfield.len < sizeof(*gd) ||
                    100:                    gx->subfield.len > sizeof(buf) - sizeof(*gx)) {
                    101:                        fprintf(stderr, "Invalid signature length\n");
                    102:                        return (-1);
                    103:                }
                    104:                if (fread((u_char *)gd, 1, gx->subfield.len, fin) !=
                    105:                    gx->subfield.len) {
                    106:                        fprintf(stderr, "Error reading signature: %s\n",
                    107:                            strerror(errno));
                    108:                        return (-1);
                    109:                }
                    110:                fprintf(stderr, "Overwriting existing signature\n");
                    111:        }
                    112:        /* Skip over any options. */
                    113:        offset = ftell(fin);
                    114:
                    115:        if (gh.flags & GZIP_FNAME) {
                    116:                while (getc(fin) != '\0')
                    117:                        ;
                    118:        }
                    119:        if (gh.flags & GZIP_FCOMMENT) {
                    120:                while (getc(fin) != '\0')
                    121:                        ;
                    122:        }
                    123:        if (gh.flags & GZIP_FENCRYPT) {
                    124:                if (fread(buf, 1, GZIP_FENCRYPT_LEN, fin) != GZIP_FENCRYPT_LEN)
                    125:                        return (-1);
                    126:        }
                    127:        /* Compute checksum over compressed data and trailer. */
                    128:        SHA1_Init(&ctx);
                    129:
                    130:        while ((i = fread(buf, 1, sizeof(buf), fin)) > 0) {
                    131:                SHA1_Update(&ctx, buf, i);
                    132:        }
                    133:        SHA1_Final(digest, &ctx);
                    134:
                    135:        /* Generate signature. */
                    136:        gx = (struct gzip_xfield *)buf;
                    137:        gd = (struct gzsig_data *)(gx + 1);
                    138:        sig = (u_char *)(gd + 1);
                    139:
                    140:        siglen = key_sign(key, digest, sizeof(digest), sig,
                    141:            sizeof(buf) - (sig - buf));
                    142:
                    143:        if (siglen < 0) {
                    144:                fprintf(stderr, "Error signing checksum\n");
                    145:                return (-1);
                    146:        }
                    147:        i = sizeof(*gd) + siglen;
                    148:        gx->subfield.len = htole16(i);
                    149:        gx->len = htole16(sizeof(gx->subfield) + i);
                    150:        memcpy(gx->subfield.id, GZSIG_ID, sizeof(gx->subfield.id));
                    151:        gd->version = GZSIG_VERSION;
                    152:
                    153:        /* Write out gzip header. */
                    154:        gh.flags |= GZIP_FEXTRA;
                    155:
                    156:        if (fwrite((u_char *)&gh, 1, sizeof(gh), fout) != sizeof(gh)) {
                    157:                fprintf(stderr, "Error writing output: %s\n", strerror(errno));
                    158:                return (-1);
                    159:        }
                    160:        /* Write out signature. */
                    161:        if (fwrite(buf, 1, sizeof(*gx) + i, fout) != sizeof(*gx) + i) {
                    162:                fprintf(stderr, "Error writing output: %s\n", strerror(errno));
                    163:                return (-1);
                    164:        }
                    165:        /* Write out options, compressed data, and trailer. */
                    166:        if (fseek(fin, offset, SEEK_SET) < 0) {
                    167:                fprintf(stderr, "Error writing output: %s\n", strerror(errno));
                    168:                return (-1);
                    169:        }
                    170:        while ((i = fread(buf, 1, sizeof(buf), fin)) > 0) {
                    171:                if (fwrite(buf, 1, i, fout) != i) {
                    172:                        fprintf(stderr, "Error writing output: %s\n",
                    173:                            strerror(errno));
                    174:                        return (-1);
                    175:                }
                    176:        }
                    177:        if (ferror(fin)) {
                    178:                fprintf(stderr, "Error reading input: %s\n", strerror(errno));
                    179:                return (-1);
                    180:        }
                    181:        return (0);
                    182: }
                    183:
                    184: void
                    185: sign_usage(void)
                    186: {
1.3     ! djm       187:        fprintf(stderr, "Usage: gzsig sign [-q] privkey [file ...]\n");
1.1       marius    188: }
                    189:
                    190: int
                    191: sign_passwd_cb(char *buf, int size, int rwflag, void *u)
                    192: {
                    193:        char *p;
                    194:
                    195:        if (passphrase != NULL) {
                    196:                if (strlcpy(buf, passphrase, size) >= size)
                    197:                        errx(1, "Passphrase too long");
                    198:        } else {
                    199:                p = getpass("Enter passphrase: ");
                    200:                if (strlcpy(buf, p, size) >= size)
                    201:                        errx(1, "Passphrase too long");
                    202:                memset(p, 0, strlen(p));
                    203:        }
                    204:
                    205:        return (strlen(buf));
                    206: }
                    207:
                    208: void
                    209: sign(int argc, char *argv[])
                    210: {
                    211:        struct key *key;
                    212:        char *gzipfile, tmpfile[MAXPATHLEN];
                    213:        FILE *fin, *fout;
1.3     ! djm       214:        int i, fd, error, qflag;
1.1       marius    215:
1.3     ! djm       216:        qflag = 0;
1.1       marius    217:
1.3     ! djm       218:        while ((i = getopt(argc, argv, "qvh?p:")) != -1) {
1.1       marius    219:                switch (i) {
1.3     ! djm       220:                case 'q':
        !           221:                        qflag = 1;
        !           222:                        break;
1.1       marius    223:                case 'v':
1.3     ! djm       224:                        qflag = 0;
1.1       marius    225:                        break;
                    226:                case 'p':
                    227:                        passphrase = optarg;
                    228:                        break;
                    229:                default:
                    230:                        sign_usage();
                    231:                        exit(1);
                    232:                }
                    233:        }
                    234:        argc -= optind;
                    235:        argv += optind;
                    236:
                    237:        if (argc < 1) {
                    238:                sign_usage();
                    239:                exit(1);
                    240:        }
                    241:        OpenSSL_add_all_algorithms();
                    242:
                    243:        if ((key = key_new()) == NULL)
                    244:                fatal(1, "Couldn't initialize private key");
                    245:
                    246:        if (key_load_private(key, argv[0]) < 0)
                    247:                fatal(1, "Couldn't load private key");
                    248:
                    249:        if (argc == 1 || *argv[1] == '-') {
                    250:                argc = 0;
                    251:
                    252:                if (embed_signature(key, stdin, stdout) == 0) {
1.3     ! djm       253:                        if (!qflag)
1.1       marius    254:                                fprintf(stderr, "Signed input\n");
                    255:                } else
                    256:                        fatal(1, "Couldn't sign input");
                    257:        }
                    258:        for (i = 1; i < argc; i++) {
                    259:                gzipfile = argv[i];
                    260:
                    261:                if ((fin = fopen(gzipfile, "r+")) == NULL) {
                    262:                        fprintf(stderr,  "Error opening %s: %s\n",
                    263:                            gzipfile, strerror(errno));
                    264:                        continue;
                    265:                }
                    266:                snprintf(tmpfile, sizeof(tmpfile), "%s.XXXXXX", gzipfile);
                    267:
                    268:                if ((fd = mkstemp(tmpfile)) < 0) {
                    269:                        fprintf(stderr, "Error creating %s: %s\n",
                    270:                            tmpfile, strerror(errno));
                    271:                        fclose(fin);
                    272:                        continue;
                    273:                }
                    274:                if ((fout = fdopen(fd, "w")) == NULL) {
                    275:                        fprintf(stderr, "Error opening %s: %s\n",
                    276:                            tmpfile, strerror(errno));
                    277:                        fclose(fin);
                    278:                        close(fd);
                    279:                        continue;
                    280:                }
                    281:                if (copy_permissions(gzipfile, tmpfile) < 0) {
                    282:                        fprintf(stderr, "Error initializing %s: %s\n",
                    283:                            tmpfile, strerror(errno));
                    284:                        fclose(fin);
                    285:                        fclose(fout);
                    286:                        continue;
                    287:                }
                    288:                error = embed_signature(key, fin, fout);
                    289:
                    290:                fclose(fin);
                    291:                fclose(fout);
                    292:
                    293:                if (!error) {
                    294:                        if (rename(tmpfile, gzipfile) < 0) {
                    295:                                unlink(tmpfile);
                    296:                                fatal(1, "Couldn't sign %s", gzipfile);
                    297:                        }
1.3     ! djm       298:                        if (!qflag)
1.1       marius    299:                                fprintf(stderr, "Signed %s\n", gzipfile);
                    300:                } else {
                    301:                        unlink(tmpfile);
                    302:                        fatal(1, "Couldn't sign %s", gzipfile);
                    303:                }
                    304:        }
                    305:        key_free(key);
                    306:
                    307:        if (passphrase != NULL)
                    308:                memset(passphrase, 0, strlen(passphrase));
                    309: }