aboutsummaryrefslogtreecommitdiff
path: root/orig
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2017-04-13 23:37:19 +0200
committerDimitri Sokolyuk <demon@dim13.org>2017-04-13 23:37:19 +0200
commitf7f69134a9bf352d3e6cfb0fa081c08f53beebc8 (patch)
tree6b5d74eb94c18405a47d3c265ceb42f82dc92fa1 /orig
parenta1d8443b3291dbd660bcd323470fb2d28673c01a (diff)
sync
Diffstat (limited to 'orig')
-rw-r--r--orig/Makefile3
-rw-r--r--orig/signify.153
-rw-r--r--orig/signify.c331
-rw-r--r--orig/signify.h33
-rw-r--r--orig/zsig.c313
5 files changed, 613 insertions, 120 deletions
diff --git a/orig/Makefile b/orig/Makefile
index 09c3075..161c43d 100644
--- a/orig/Makefile
+++ b/orig/Makefile
@@ -1,6 +1,7 @@
-# $OpenBSD: Makefile,v 1.10 2014/07/22 00:41:19 deraadt Exp $
+# $OpenBSD: Makefile,v 1.11 2016/09/02 16:10:56 espie Exp $
SRCS= signify.c
+SRCS+= zsig.c
SRCS+= fe25519.c sc25519.c smult_curve25519_ref.c
SRCS+= mod_ed25519.c mod_ge25519.c
SRCS+= crypto_api.c
diff --git a/orig/signify.1 b/orig/signify.1
index dbf2ea5..569c14e 100644
--- a/orig/signify.1
+++ b/orig/signify.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: signify.1,v 1.33 2016/01/06 23:14:05 benno Exp $
+.\" $OpenBSD: signify.1,v 1.41 2017/03/09 19:42:05 benno Exp $
.\"
.\"Copyright (c) 2013 Marc Espie <espie@openbsd.org>
.\"Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
@@ -14,7 +14,7 @@
.\"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.Dd $Mdocdate: January 6 2016 $
+.Dd $Mdocdate: March 9 2017 $
.Dt SIGNIFY 1
.Os
.Sh NAME
@@ -35,15 +35,16 @@
.Fl s Ar seckey
.Nm signify
.Fl S
-.Op Fl e
+.Op Fl ez
.Op Fl x Ar sigfile
.Fl s Ar seckey
.Fl m Ar message
.Nm signify
.Fl V
-.Op Fl eq
+.Op Fl eqz
+.Op Fl p Ar pubkey
+.Op Fl t Ar keytype
.Op Fl x Ar sigfile
-.Fl p Ar pubkey
.Fl m Ar message
.Sh DESCRIPTION
The
@@ -62,6 +63,11 @@ should be the signed output of
.Xr sha256 1 .
.It Fl G
Generate a new key pair.
+Keynames should follow the convention of
+.Pa keyname.pub
+and
+.Pa keyname.sec
+for the public and secret keys, respectively.
.It Fl S
Sign the specified message file and create a signature.
.It Fl V
@@ -104,10 +110,21 @@ Secret (private) key produced by
and used by
.Fl S
to sign a message.
+.It Fl t Ar keytype
+When deducing the correct key to check a signature, make sure
+the actual key matches
+.Pa /etc/signify/*-keytype.pub .
.It Fl x Ar sigfile
The signature file to create or verify.
The default is
.Ar message Ns .sig .
+.It Fl z
+Sign and verify
+.Xr gzip 1
+archives, where the signing data
+is embedded in the
+.Xr gzip 1
+header.
.El
.Pp
The key and signature files created by
@@ -115,10 +132,10 @@ The key and signature files created by
have the same format.
The first line of the file is a free form text comment that may be edited,
so long as it does not exceed a single line.
-.\" Signature comments will be generated based on the name of the secret
-.\" key used for signing.
-.\" This comment can then be used as a hint for the name of the public key
-.\" when verifying.
+Signature comments will be generated based on the name of the secret
+key used for signing.
+This comment can then be used as a hint for the name of the public key
+when verifying.
The second line of the file is the actual key or signature base64 encoded.
.Sh EXIT STATUS
.Ex -std signify
@@ -148,15 +165,26 @@ Verify a release directory containing
.Pa SHA256.sig
and a full set of release files:
.Bd -literal -offset indent -compact
-$ signify -C -p /etc/signify/openbsd-60-base.pub -x SHA256.sig
+$ signify -C -p /etc/signify/openbsd-62-base.pub -x SHA256.sig
.Ed
.Pp
Verify a bsd.rd before an upgrade:
.Bd -literal -offset indent -compact
-$ signify -C -p /etc/signify/openbsd-60-base.pub -x SHA256.sig bsd.rd
+$ signify -C -p /etc/signify/openbsd-62-base.pub -x SHA256.sig bsd.rd
+.Ed
+.Pp
+Sign a gzip archive:
+.Bd -literal -offset indent -compact
+$ signify -Sz -s key-arc.sec -m in.tgz -x out.tgz
+.Ed
+.Pp
+Verify a gzip pipeline:
+.Bd -literal -offset indent -compact
+$ ftp url | signify -Vz -t arc | tar ztf -
.Ed
.Sh SEE ALSO
.Xr fw_update 1 ,
+.Xr gzip 1 ,
.Xr pkg_add 1 ,
.Xr sha256 1
.Sh HISTORY
@@ -165,4 +193,7 @@ The
command first appeared in
.Ox 5.5 .
.Sh AUTHORS
+.An -nosplit
.An Ted Unangst Aq Mt tedu@openbsd.org
+and
+.An Marc Espie Aq Mt espie@openbsd.org .
diff --git a/orig/signify.c b/orig/signify.c
index a4cb84a..5158326 100644
--- a/orig/signify.c
+++ b/orig/signify.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: signify.c,v 1.105 2015/12/04 11:05:22 tedu Exp $ */
+/* $OpenBSD: signify.c,v 1.126 2016/10/06 22:38:25 espie Exp $ */
/*
* Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
*
@@ -34,6 +34,7 @@
#include <sha2.h>
#include "crypto_api.h"
+#include "signify.h"
#define SIGBYTES crypto_sign_ed25519_BYTES
#define SECRETBYTES crypto_sign_ed25519_SECRETKEYBYTES
@@ -70,8 +71,6 @@ struct sig {
uint8_t sig[SIGBYTES];
};
-extern char *__progname;
-
static void __dead
usage(const char *error)
{
@@ -81,14 +80,14 @@ usage(const char *error)
#ifndef VERIFYONLY
"\t%1$s -C [-q] -p pubkey -x sigfile [file ...]\n"
"\t%1$s -G [-n] [-c comment] -p pubkey -s seckey\n"
- "\t%1$s -S [-e] [-x sigfile] -s seckey -m message\n"
+ "\t%1$s -S [-ez] [-x sigfile] -s seckey -m message\n"
#endif
- "\t%1$s -V [-eq] [-x sigfile] -p pubkey -m message\n",
- __progname);
+ "\t%1$s -V [-eqz] [-p pubkey] [-t keytype] [-x sigfile] -m message\n",
+ getprogname());
exit(1);
}
-static int
+int
xopen(const char *fname, int oflags, mode_t mode)
{
struct stat sb;
@@ -112,7 +111,7 @@ xopen(const char *fname, int oflags, mode_t mode)
return fd;
}
-static void *
+void *
xmalloc(size_t len)
{
void *p;
@@ -190,7 +189,7 @@ readmsg(const char *filename, unsigned long long *msglenp)
errx(1, "msg too large in %s", filename);
space = msglen;
if (!(msg = realloc(msg, msglen + space + 1)))
- errx(1, "realloc");
+ err(1, "realloc");
}
if ((x = read(fd, msg + msglen, space)) == -1)
err(1, "read from %s", filename);
@@ -207,7 +206,7 @@ readmsg(const char *filename, unsigned long long *msglenp)
return msg;
}
-static void
+void
writeall(int fd, const void *buf, size_t buflen, const char *filename)
{
ssize_t x;
@@ -221,26 +220,32 @@ writeall(int fd, const void *buf, size_t buflen, const char *filename)
}
#ifndef VERIFYONLY
-static void
-writeb64file(const char *filename, const char *comment, const void *buf,
- size_t buflen, const void *msg, size_t msglen, int oflags, mode_t mode)
+static char *
+createheader(const char *comment, const void *buf, size_t buflen)
{
- char header[1024];
+ char *header;
char b64[1024];
- int fd, rv, nr;
- fd = xopen(filename, O_CREAT|oflags|O_NOFOLLOW|O_WRONLY, mode);
- if ((nr = snprintf(header, sizeof(header), "%s%s\n",
- COMMENTHDR, comment)) == -1 || nr >= sizeof(header))
- errx(1, "comment too long");
- writeall(fd, header, strlen(header), filename);
- if ((rv = b64_ntop(buf, buflen, b64, sizeof(b64))) == -1)
+ if (b64_ntop(buf, buflen, b64, sizeof(b64)) == -1)
errx(1, "base64 encode failed");
- b64[rv++] = '\n';
- writeall(fd, b64, rv, filename);
+ if (asprintf(&header, "%s%s\n%s\n", COMMENTHDR, comment, b64) == -1)
+ err(1, "asprintf failed");
explicit_bzero(b64, sizeof(b64));
- if (msg)
- writeall(fd, msg, msglen, filename);
+ return header;
+}
+
+static void
+writekeyfile(const char *filename, const char *comment, const void *buf,
+ size_t buflen, int oflags, mode_t mode)
+{
+ char *header;
+ int fd;
+
+ fd = xopen(filename, O_CREAT|oflags|O_NOFOLLOW|O_WRONLY, mode);
+ header = createheader(comment, buf, buflen);
+ writeall(fd, header, strlen(header), filename);
+ explicit_bzero(header, strlen(header));
+ free(header);
close(fd);
}
@@ -322,39 +327,83 @@ generate(const char *pubkeyfile, const char *seckeyfile, int rounds,
explicit_bzero(digest, sizeof(digest));
explicit_bzero(xorkey, sizeof(xorkey));
- if ((nr = snprintf(commentbuf, sizeof(commentbuf), "%s secret key",
- comment)) == -1 || nr >= sizeof(commentbuf))
+ nr = snprintf(commentbuf, sizeof(commentbuf), "%s secret key", comment);
+ if (nr == -1 || nr >= sizeof(commentbuf))
errx(1, "comment too long");
- writeb64file(seckeyfile, commentbuf, &enckey,
- sizeof(enckey), NULL, 0, O_EXCL, 0600);
+ writekeyfile(seckeyfile, commentbuf, &enckey,
+ sizeof(enckey), O_EXCL, 0600);
explicit_bzero(&enckey, sizeof(enckey));
memcpy(pubkey.pkalg, PKALG, 2);
memcpy(pubkey.keynum, keynum, KEYNUMLEN);
- if ((nr = snprintf(commentbuf, sizeof(commentbuf), "%s public key",
- comment)) == -1 || nr >= sizeof(commentbuf))
+ nr = snprintf(commentbuf, sizeof(commentbuf), "%s public key", comment);
+ if (nr == -1 || nr >= sizeof(commentbuf))
errx(1, "comment too long");
- writeb64file(pubkeyfile, commentbuf, &pubkey,
- sizeof(pubkey), NULL, 0, O_EXCL, 0666);
+ writekeyfile(pubkeyfile, commentbuf, &pubkey,
+ sizeof(pubkey), O_EXCL, 0666);
}
-static void
-sign(const char *seckeyfile, const char *msgfile, const char *sigfile,
- int embedded)
+static const char *
+check_keyname_compliance(const char *pubkeyfile, const char *seckeyfile)
+{
+ const char *pos;
+
+ /* basename may or may not modify input */
+ pos = strrchr(seckeyfile, '/');
+ if (pos != NULL)
+ seckeyfile = pos+1;
+
+ size_t len;
+ len = strlen(seckeyfile);
+ if (len < 5) /* ?.key */
+ goto bad;
+ if (strcmp(seckeyfile + len - 4, ".sec") != 0)
+ goto bad;
+ if (pubkeyfile != NULL) {
+ pos = strrchr(pubkeyfile, '/');
+ if (pos != NULL)
+ pubkeyfile = pos+1;
+
+ if (strlen(pubkeyfile) != len)
+ goto bad;
+ if (strcmp(pubkeyfile + len - 4, ".pub") != 0)
+ goto bad;
+ if (strncmp(pubkeyfile, seckeyfile, len - 4) != 0)
+ goto bad;
+ }
+
+ return seckeyfile;
+bad:
+ errx(1, "please use naming scheme of keyname.pub and keyname.sec");
+}
+
+uint8_t *
+createsig(const char *seckeyfile, const char *msgfile, uint8_t *msg,
+ unsigned long long msglen)
{
- struct sig sig;
- uint8_t digest[SHA512_DIGEST_LENGTH];
struct enckey enckey;
uint8_t xorkey[sizeof(enckey.seckey)];
- uint8_t *msg;
- char comment[COMMENTMAXLEN], sigcomment[COMMENTMAXLEN];
- char *secname;
- unsigned long long msglen;
- int i, rounds, nr;
+ struct sig sig;
+ char *sighdr;
+ uint8_t digest[SHA512_DIGEST_LENGTH];
+ int i, nr, rounds;
SHA2_CTX ctx;
+ char comment[COMMENTMAXLEN], sigcomment[COMMENTMAXLEN];
readb64file(seckeyfile, &enckey, sizeof(enckey), comment);
+ if (strcmp(seckeyfile, "-") == 0) {
+ nr = snprintf(sigcomment, sizeof(sigcomment),
+ "signature from %s", comment);
+ } else {
+ const char *keyname = check_keyname_compliance(NULL,
+ seckeyfile);
+ nr = snprintf(sigcomment, sizeof(sigcomment),
+ VERIFYWITH "%.*s.pub", (int)strlen(keyname) - 4, keyname);
+ }
+ if (nr == -1 || nr >= sizeof(sigcomment))
+ errx(1, "comment too long");
+
if (memcmp(enckey.kdfalg, KDFALG, 2) != 0)
errx(1, "unsupported KDF");
rounds = ntohl(enckey.kdfrounds);
@@ -370,29 +419,35 @@ sign(const char *seckeyfile, const char *msgfile, const char *sigfile,
errx(1, "incorrect passphrase");
explicit_bzero(digest, sizeof(digest));
- msg = readmsg(msgfile, &msglen);
-
signmsg(enckey.seckey, msg, msglen, sig.sig);
memcpy(sig.keynum, enckey.keynum, KEYNUMLEN);
explicit_bzero(&enckey, sizeof(enckey));
memcpy(sig.pkalg, PKALG, 2);
- secname = strstr(seckeyfile, ".sec");
- if (secname && strlen(secname) == 4) {
- if ((nr = snprintf(sigcomment, sizeof(sigcomment), VERIFYWITH "%.*s.pub",
- (int)strlen(seckeyfile) - 4, seckeyfile)) == -1 || nr >= sizeof(sigcomment))
- errx(1, "comment too long");
- } else {
- if ((nr = snprintf(sigcomment, sizeof(sigcomment), "signature from %s",
- comment)) == -1 || nr >= sizeof(sigcomment))
- errx(1, "comment too long");
- }
+
+ sighdr = createheader(sigcomment, &sig, sizeof(sig));
+ return sighdr;
+}
+
+static void
+sign(const char *seckeyfile, const char *msgfile, const char *sigfile,
+ int embedded)
+{
+ uint8_t *msg;
+ char *sighdr;
+ int fd;
+ unsigned long long msglen;
+
+ msg = readmsg(msgfile, &msglen);
+
+ sighdr = createsig(seckeyfile, msgfile, msg, msglen);
+
+ fd = xopen(sigfile, O_CREAT|O_TRUNC|O_NOFOLLOW|O_WRONLY, 0666);
+ writeall(fd, sighdr, strlen(sighdr), sigfile);
+ free(sighdr);
if (embedded)
- writeb64file(sigfile, sigcomment, &sig, sizeof(sig), msg,
- msglen, O_TRUNC, 0666);
- else
- writeb64file(sigfile, sigcomment, &sig, sizeof(sig), NULL,
- 0, O_TRUNC, 0666);
+ writeall(fd, msg, msglen, sigfile);
+ close(fd);
free(msg);
}
@@ -423,18 +478,42 @@ verifymsg(struct pubkey *pubkey, uint8_t *msg, unsigned long long msglen,
}
static void
+check_keytype(const char *pubkeyfile, const char *keytype)
+{
+ const char *p;
+ size_t typelen;
+
+ if (!(p = strrchr(pubkeyfile, '-')))
+ goto bad;
+ p++;
+ typelen = strlen(keytype);
+ if (strncmp(p, keytype, typelen) != 0)
+ goto bad;
+ if (strcmp(p + typelen, ".pub") != 0)
+ goto bad;
+ return;
+
+bad:
+ errx(1, "incorrect keytype: %s is not %s", pubkeyfile, keytype);
+}
+
+static void
readpubkey(const char *pubkeyfile, struct pubkey *pubkey,
- const char *sigcomment)
+ const char *sigcomment, const char *keytype)
{
- const char *safepath = "/etc/signify/";
+ const char *safepath = "/etc/signify";
+ char keypath[1024];
if (!pubkeyfile) {
pubkeyfile = strstr(sigcomment, VERIFYWITH);
- if (pubkeyfile) {
+ if (pubkeyfile && strchr(pubkeyfile, '/') == NULL) {
pubkeyfile += strlen(VERIFYWITH);
- if (strncmp(pubkeyfile, safepath, strlen(safepath)) != 0 ||
- strstr(pubkeyfile, "/../") != NULL)
- errx(1, "untrusted path %s", pubkeyfile);
+ if (keytype)
+ check_keytype(pubkeyfile, keytype);
+ if (snprintf(keypath, sizeof(keypath), "%s/%s",
+ safepath, pubkeyfile) >= sizeof(keypath))
+ errx(1, "name too long %s", pubkeyfile);
+ pubkeyfile = keypath;
} else
usage("must specify pubkey");
}
@@ -443,7 +522,7 @@ readpubkey(const char *pubkeyfile, struct pubkey *pubkey,
static void
verifysimple(const char *pubkeyfile, const char *msgfile, const char *sigfile,
- int quiet)
+ int quiet, const char *keytype)
{
char sigcomment[COMMENTMAXLEN];
struct sig sig;
@@ -454,7 +533,7 @@ verifysimple(const char *pubkeyfile, const char *msgfile, const char *sigfile,
msg = readmsg(msgfile, &msglen);
readb64file(sigfile, &sig, sizeof(sig), sigcomment);
- readpubkey(pubkeyfile, &pubkey, sigcomment);
+ readpubkey(pubkeyfile, &pubkey, sigcomment, keytype);
verifymsg(&pubkey, msg, msglen, &sig, quiet);
@@ -463,7 +542,7 @@ verifysimple(const char *pubkeyfile, const char *msgfile, const char *sigfile,
static uint8_t *
verifyembedded(const char *pubkeyfile, const char *sigfile,
- int quiet, unsigned long long *msglenp)
+ int quiet, unsigned long long *msglenp, const char *keytype)
{
char sigcomment[COMMENTMAXLEN];
struct sig sig;
@@ -474,7 +553,7 @@ verifyembedded(const char *pubkeyfile, const char *sigfile,
msg = readmsg(sigfile, &msglen);
siglen = parseb64file(sigfile, msg, &sig, sizeof(sig), sigcomment);
- readpubkey(pubkeyfile, &pubkey, sigcomment);
+ readpubkey(pubkeyfile, &pubkey, sigcomment, keytype);
msglen -= siglen;
memmove(msg, msg + siglen, msglen);
@@ -488,20 +567,21 @@ verifyembedded(const char *pubkeyfile, const char *sigfile,
static void
verify(const char *pubkeyfile, const char *msgfile, const char *sigfile,
- int embedded, int quiet)
+ int embedded, int quiet, const char *keytype)
{
unsigned long long msglen;
uint8_t *msg;
int fd;
if (embedded) {
- msg = verifyembedded(pubkeyfile, sigfile, quiet, &msglen);
+ msg = verifyembedded(pubkeyfile, sigfile, quiet, &msglen,
+ keytype);
fd = xopen(msgfile, O_CREAT|O_TRUNC|O_NOFOLLOW|O_WRONLY, 0666);
writeall(fd, msg, msglen, msgfile);
free(msg);
close(fd);
} else {
- verifysimple(pubkeyfile, msgfile, sigfile, quiet);
+ verifysimple(pubkeyfile, msgfile, sigfile, quiet, keytype);
}
}
@@ -513,7 +593,7 @@ struct checksum {
char algo[32];
};
-static void *
+static void *
ecalloc(size_t s1, size_t s2, void *data)
{
void *p;
@@ -637,11 +717,31 @@ check(const char *pubkeyfile, const char *sigfile, int quiet, int argc,
unsigned long long msglen;
uint8_t *msg;
- msg = verifyembedded(pubkeyfile, sigfile, quiet, &msglen);
+ msg = verifyembedded(pubkeyfile, sigfile, quiet, &msglen, NULL);
verifychecksums((char *)msg, argc, argv, quiet);
free(msg);
}
+
+void *
+verifyzdata(uint8_t *zdata, unsigned long long zdatalen,
+ const char *filename, const char *pubkeyfile, const char *keytype)
+{
+ struct sig sig;
+ char sigcomment[COMMENTMAXLEN];
+ unsigned long long siglen;
+ struct pubkey pubkey;
+
+ if (zdatalen < sizeof(sig))
+ errx(1, "signature too short in %s", filename);
+ siglen = parseb64file(filename, zdata, &sig, sizeof(sig),
+ sigcomment);
+ readpubkey(pubkeyfile, &pubkey, sigcomment, keytype);
+ zdata += siglen;
+ zdatalen -= siglen;
+ verifymsg(&pubkey, zdata, zdatalen, &sig, 1);
+ return zdata;
+}
#endif
int
@@ -651,9 +751,11 @@ main(int argc, char **argv)
*sigfile = NULL;
char sigfilebuf[PATH_MAX];
const char *comment = "signify";
+ char *keytype = NULL;
int ch, rounds;
int embedded = 0;
int quiet = 0;
+ int gzip = 0;
enum {
NONE,
CHECK,
@@ -667,7 +769,7 @@ main(int argc, char **argv)
rounds = 42;
- while ((ch = getopt(argc, argv, "CGSVc:em:np:qs:x:")) != -1) {
+ while ((ch = getopt(argc, argv, "CGSVzc:em:np:qs:t:x:")) != -1) {
switch (ch) {
#ifndef VERIFYONLY
case 'C':
@@ -685,6 +787,9 @@ main(int argc, char **argv)
usage(NULL);
verb = SIGN;
break;
+ case 'z':
+ gzip = 1;
+ break;
#endif
case 'V':
if (verb)
@@ -712,6 +817,9 @@ main(int argc, char **argv)
case 's':
seckeyfile = optarg;
break;
+ case 't':
+ keytype = optarg;
+ break;
case 'x':
sigfile = optarg;
break;
@@ -723,35 +831,16 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ if (embedded && gzip)
+ errx(1, "can't combine -e and -z options");
+
if (setvbuf(stdout, NULL, _IOLBF, 0) != 0)
err(1, "setvbuf");
- switch (verb) {
- case GENERATE:
- case SIGN:
- /* keep it all */
- break;
- case CHECK:
- if (pledge("stdio rpath", NULL) == -1)
- err(1, "pledge");
- break;
- case VERIFY:
- if (embedded && (!msgfile || strcmp(msgfile, "-") != 0)) {
- if (pledge("stdio rpath wpath cpath", NULL) == -1)
- err(1, "pledge");
- } else {
- if (pledge("stdio rpath", NULL) == -1)
- err(1, "pledge");
- }
- break;
- default:
- if (pledge("stdio", NULL) == -1)
- err(1, "pledge");
- break;
- }
-
#ifndef VERIFYONLY
if (verb == CHECK) {
+ if (pledge("stdio rpath", NULL) == -1)
+ err(1, "pledge");
if (!sigfile)
usage("must specify sigfile");
check(pubkeyfile, sigfile, quiet, argc, argv);
@@ -766,8 +855,9 @@ main(int argc, char **argv)
int nr;
if (strcmp(msgfile, "-") == 0)
usage("must specify sigfile with - message");
- if ((nr = snprintf(sigfilebuf, sizeof(sigfilebuf), "%s.sig",
- msgfile)) == -1 || nr >= sizeof(sigfilebuf))
+ nr = snprintf(sigfilebuf, sizeof(sigfilebuf),
+ "%s.sig", msgfile);
+ if (nr == -1 || nr >= sizeof(sigfilebuf))
errx(1, "path too long");
sigfile = sigfilebuf;
}
@@ -775,22 +865,47 @@ main(int argc, char **argv)
switch (verb) {
#ifndef VERIFYONLY
case GENERATE:
+ /* no pledge */
if (!pubkeyfile || !seckeyfile)
usage("must specify pubkey and seckey");
+ check_keyname_compliance(pubkeyfile, seckeyfile);
generate(pubkeyfile, seckeyfile, rounds, comment);
break;
case SIGN:
- if (!msgfile || !seckeyfile)
- usage("must specify message and seckey");
- sign(seckeyfile, msgfile, sigfile, embedded);
+ /* no pledge */
+ if (gzip) {
+ if (!msgfile || !seckeyfile || !sigfile)
+ usage("must specify message sigfile seckey");
+ zsign(seckeyfile, msgfile, sigfile);
+ } else {
+ if (!msgfile || !seckeyfile)
+ usage("must specify message and seckey");
+ sign(seckeyfile, msgfile, sigfile, embedded);
+ }
break;
#endif
case VERIFY:
- if (!msgfile)
- usage("must specify message");
- verify(pubkeyfile, msgfile, sigfile, embedded, quiet);
+ if ((embedded || gzip) &&
+ (msgfile && strcmp(msgfile, "-") != 0)) {
+ /* will need to create output file */
+ if (pledge("stdio rpath wpath cpath", NULL) == -1)
+ err(1, "pledge");
+ } else {
+ if (pledge("stdio rpath", NULL) == -1)
+ err(1, "pledge");
+ }
+ if (gzip) {
+ zverify(pubkeyfile, msgfile, sigfile, keytype);
+ } else {
+ if (!msgfile)
+ usage("must specify message");
+ verify(pubkeyfile, msgfile, sigfile, embedded,
+ quiet, keytype);
+ }
break;
default:
+ if (pledge("stdio", NULL) == -1)
+ err(1, "pledge");
usage(NULL);
break;
}
diff --git a/orig/signify.h b/orig/signify.h
new file mode 100644
index 0000000..6edb6a4
--- /dev/null
+++ b/orig/signify.h
@@ -0,0 +1,33 @@
+/* $OpenBSD: signify.h,v 1.1 2016/09/02 16:10:56 espie Exp $ */
+/*
+ * Copyright (c) 2016 Marc Espie <espie@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* common interface to signify.c/zsig.c */
+#ifndef signify_h
+#define signify_h
+extern void zverify(const char *, const char *, const char *, const char *);
+extern void zsign(const char *, const char *, const char *);
+
+extern void *xmalloc(size_t);
+extern void writeall(int, const void *, size_t, const char *);
+extern int xopen(const char *, int, mode_t);
+extern void *verifyzdata(uint8_t *, unsigned long long,
+ const char *, const char *, const char *);
+extern uint8_t *createsig(const char *, const char *, uint8_t *,
+ unsigned long long);
+
+
+#endif
diff --git a/orig/zsig.c b/orig/zsig.c
new file mode 100644
index 0000000..38092be
--- /dev/null
+++ b/orig/zsig.c
@@ -0,0 +1,313 @@
+/* $OpenBSD: zsig.c,v 1.14 2016/10/04 14:40:41 espie Exp $ */
+/*
+ * Copyright (c) 2016 Marc Espie <espie@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef VERIFYONLY
+#include <stdint.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sha2.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <fcntl.h>
+#include "signify.h"
+
+struct gzheader {
+ uint8_t flg;
+ uint32_t mtime;
+ uint8_t xflg;
+ uint8_t os;
+ uint8_t *name;
+ uint8_t *comment;
+ uint8_t *endcomment;
+ unsigned long long headerlength;
+ uint8_t *buffer;
+};
+
+#define FTEXT_FLAG 1
+#define FHCRC_FLAG 2
+#define FEXTRA_FLAG 4
+#define FNAME_FLAG 8
+#define FCOMMENT_FLAG 16
+
+#define GZHEADERLENGTH 10
+#define MYBUFSIZE 65536LU
+
+
+static uint8_t fake[10] = { 0x1f, 0x8b, 8, FCOMMENT_FLAG, 0, 0, 0, 0, 0, 3 };
+
+static uint8_t *
+readgz_header(struct gzheader *h, int fd)
+{
+ size_t sz = 1024;
+ uint8_t *p;
+ size_t pos = 0;
+ size_t len = 0;
+ int state = 0;
+ ssize_t n;
+ uint8_t *buf;
+
+ buf = xmalloc(sz);
+
+ while (1) {
+ if (len == sz) {
+ sz *= 2;
+ buf = realloc(buf, sz);
+ if (!buf)
+ err(1, "realloc");
+ }
+ n = read(fd, buf+len, sz-len);
+ if (n == -1)
+ err(1, "read");
+ /* incomplete info */
+ if (n == 0)
+ errx(1, "gzheader truncated");
+ len += n;
+ h->comment = NULL;
+ h->name = NULL;
+
+ switch(state) {
+ case 0: /* check header proper */
+ /* need ten bytes */
+ if (len < GZHEADERLENGTH)
+ continue;
+ h->flg = buf[3];
+ h->mtime = buf[4] | (buf[5] << 8U) | (buf[6] << 16U) |
+ (buf[7] << 24U);
+ h->xflg = buf[8];
+ h->os = buf[9];
+ /* magic gzip header */
+ if (buf[0] != 0x1f || buf[1] != 0x8b || buf[2] != 8)
+ err(1, "invalid magic in gzheader");
+ /* XXX special code that only caters to our needs */
+ if (h->flg & ~ (FCOMMENT_FLAG | FNAME_FLAG))
+ err(1, "invalid flags in gzheader");
+ pos = GZHEADERLENGTH;
+ state++;
+ /*FALLTHRU*/
+ case 1:
+ if (h->flg & FNAME_FLAG) {
+ p = memchr(buf+pos, 0, len - pos);
+ if (!p)
+ continue;
+ pos = (p - buf) + 1;
+ }
+ state++;
+ /*FALLTHRU*/
+ case 2:
+ if (h->flg & FCOMMENT_FLAG) {
+ p = memchr(buf+pos, 0, len - pos);
+ if (!p)
+ continue;
+ h->comment = buf + pos;
+ h->endcomment = p;
+ pos = (p - buf) + 1;
+ }
+ if (h->flg & FNAME_FLAG)
+ h->name = buf + GZHEADERLENGTH;
+ h->headerlength = pos;
+ h->buffer = buf;
+ return buf + len;
+ }
+
+ }
+}
+
+static void
+copy_blocks(int fdout, int fdin, const char *sha, const char *endsha,
+ size_t bufsize, uint8_t *bufend)
+{
+ uint8_t *buffer;
+ uint8_t *residual;
+ uint8_t output[SHA512_256_DIGEST_STRING_LENGTH];
+
+ buffer = xmalloc(bufsize);
+ residual = (uint8_t *)endsha + 1;
+
+ while (1) {
+ /* get the next block */
+ size_t n = 0;
+ /* if we have residual data, we use it */
+ if (residual != bufend) {
+ /* how much can we copy */
+ size_t len = bufend - residual;
+ n = len >= bufsize ? bufsize : len;
+ memcpy(buffer, residual, n);
+ residual += n;
+ }
+ /* if we're not done yet, try to obtain more until EOF */
+ while (n != bufsize) {
+ ssize_t more = read(fdin, buffer+n, bufsize-n);
+ if (more == -1)
+ err(1, "read");
+ n += more;
+ if (more == 0)
+ break;
+ }
+ SHA512_256Data(buffer, n, output);
+ if (endsha - sha < SHA512_256_DIGEST_STRING_LENGTH-1)
+ errx(4, "signature truncated");
+ if (memcmp(output, sha, SHA512_256_DIGEST_STRING_LENGTH-1) != 0)
+ errx(4, "signature mismatch");
+ if (sha[SHA512_256_DIGEST_STRING_LENGTH-1] != '\n')
+ errx(4, "signature mismatch");
+ sha += SHA512_256_DIGEST_STRING_LENGTH;
+ writeall(fdout, buffer, n, "stdout");
+ if (n != bufsize)
+ break;
+ }
+ free(buffer);
+}
+
+void
+zverify(const char *pubkeyfile, const char *msgfile, const char *sigfile,
+ const char *keytype)
+{
+ struct gzheader h;
+ size_t bufsize;
+ char *p, *meta;
+ uint8_t *bufend;
+ int fdin, fdout;
+
+ /* by default, verification will love pipes */
+ if (!sigfile)
+ sigfile = "-";
+ if (!msgfile)
+ msgfile = "-";
+
+ fdin = xopen(sigfile, O_RDONLY | O_NOFOLLOW, 0);
+
+ bufend = readgz_header(&h, fdin);
+ if (!(h.flg & FCOMMENT_FLAG))
+ errx(1, "unsigned gzip archive");
+ fake[8] = h.xflg;
+
+ p = verifyzdata(h.comment, h.endcomment-h.comment, sigfile,
+ pubkeyfile, keytype);
+
+ bufsize = MYBUFSIZE;
+
+ meta = p;
+#define BEGINS_WITH(x, y) memcmp((x), (y), sizeof(y)-1) == 0
+
+ while (BEGINS_WITH(p, "algorithm=SHA512/256") ||
+ BEGINS_WITH(p, "date=") ||
+ BEGINS_WITH(p, "key=") ||
+ sscanf(p, "blocksize=%zu\n", &bufsize) > 0) {
+ while (*(p++) != '\n')
+ continue;
+ }
+
+ if (*p != '\n')
+ errx(1, "invalid signature");
+ *(p++) = 0;
+
+ fdout = xopen(msgfile, O_CREAT|O_TRUNC|O_NOFOLLOW|O_WRONLY, 0666);
+ /* we don't actually copy the header, but put in a fake one with about
+ * zero useful information.
+ */
+ writeall(fdout, fake, sizeof fake, msgfile);
+ writeall(fdout, meta, p - meta, msgfile);
+ copy_blocks(fdout, fdin, p, h.endcomment, bufsize, bufend);
+ free(h.buffer);
+ close(fdout);
+ close(fdin);
+}
+
+void
+zsign(const char *seckeyfile, const char *msgfile, const char *sigfile)
+{
+ size_t bufsize = MYBUFSIZE;
+ int fdin, fdout;
+ struct gzheader h;
+ struct stat sb;
+ size_t space;
+ char *msg;
+ char *p;
+ uint8_t *buffer;
+ uint8_t *sighdr;
+ char date[80];
+ time_t clock;
+
+ fdin = xopen(msgfile, O_RDONLY, 0);
+ if (fstat(fdin, &sb) == -1 || !S_ISREG(sb.st_mode))
+ errx(1, "Sorry can only sign regular files");
+
+ readgz_header(&h, fdin);
+ /* we don't care about the header, actually */
+ free(h.buffer);
+
+ if (lseek(fdin, h.headerlength, SEEK_SET) == -1)
+ err(1, "seek in %s", msgfile);
+
+ space = (sb.st_size / MYBUFSIZE+1) * SHA512_256_DIGEST_STRING_LENGTH +
+ 1024; /* long enough for extra header information */
+
+ msg = xmalloc(space);
+ buffer = xmalloc(bufsize);
+ time(&clock);
+ strftime(date, sizeof date, "%Y-%m-%dT%H:%M:%SZ", gmtime(&clock));
+ snprintf(msg, space,
+ "date=%s\n"
+ "key=%s\n"
+ "algorithm=SHA512/256\n"
+ "blocksize=%zu\n\n",
+ date, seckeyfile, bufsize);
+ p = strchr(msg, 0);
+
+ while (1) {
+ size_t n = read(fdin, buffer, bufsize);
+ if (n == -1)
+ err(1, "read from %s", msgfile);
+ if (n == 0)
+ break;
+ SHA512_256Data(buffer, n, p);
+ p += SHA512_256_DIGEST_STRING_LENGTH;
+ p[-1] = '\n';
+ if (msg + space < p)
+ errx(1, "file too long %s", msgfile);
+ }
+ *p = 0;
+
+ fdout = xopen(sigfile, O_CREAT|O_TRUNC|O_NOFOLLOW|O_WRONLY, 0666);
+ sighdr = createsig(seckeyfile, msgfile, msg, p-msg);
+ fake[8] = h.xflg;
+
+ writeall(fdout, fake, sizeof fake, sigfile);
+ writeall(fdout, sighdr, strlen(sighdr), sigfile);
+ free(sighdr);
+ /* need the 0 ! */
+ writeall(fdout, msg, p - msg + 1, sigfile);
+ free(msg);
+
+ if (lseek(fdin, h.headerlength, SEEK_SET) == -1)
+ err(1, "seek in %s", msgfile);
+
+ while (1) {
+ size_t n = read(fdin, buffer, bufsize);
+ if (n == -1)
+ err(1, "read from %s", msgfile);
+ if (n == 0)
+ break;
+ writeall(fdout, buffer, n, sigfile);
+ }
+ free(buffer);
+ close(fdout);
+}
+#endif