summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
authoragc <agc@pkgsrc.org>2014-02-04 02:11:18 +0000
committeragc <agc@pkgsrc.org>2014-02-04 02:11:18 +0000
commita145a45761dc7d12bd7a4c8f68d50f2fcfcb7fd1 (patch)
treec57375724b589f375d29b5f60052936a55ece8dd /security
parent5466d91855ee1f75903d32b0ba24be1cb9b38f83 (diff)
downloadpkgsrc-a145a45761dc7d12bd7a4c8f68d50f2fcfcb7fd1.tar.gz
Update security/netpgpverify to version 20140202
Changes from previous version: Add the ability for netpgpverify to verify ssh-pub-key-based signatures. It is much more likely for ssh (rather than pgp) keys to be available, and used, as a source of authentication data. These changes add the ability for netpgpverify(1) -- the standalone, zero-prereq utility - to verify signatures made by netpgp when using ssh keys. Running the regression tests in WRKDIR gives the following output: % mk -f *.bsd tst ./netpgpverify -k pubring.gpg NetBSD-6.0_RC1_hashes.asc Good signature for NetBSD-6.0_RC1_hashes.asc made Thu Aug 23 11:47:50 2012 signature 4096/RSA (Encrypt or Sign) 064973ac4c4a706e 2009-06-23 fingerprint ddee 2bdb 9c98 a0d1 d4fb dbf7 0649 73ac 4c4a 706e uid NetBSD Security Officer <security-officer@NetBSD.org> ./netpgpverify -k pubring.gpg NetBSD-6.0_RC1_hashes.gpg Good signature for NetBSD-6.0_RC1_hashes.gpg made Thu Mar 14 13:32:59 2013 signature 4096/RSA (Encrypt or Sign) 064973ac4c4a706e 2009-06-23 fingerprint ddee 2bdb 9c98 a0d1 d4fb dbf7 0649 73ac 4c4a 706e uid NetBSD Security Officer <security-officer@NetBSD.org> ./netpgpverify -v netpgpverify portable 20140202 ./netpgpverify -S sshtest-20140202.pub data.gpg Good signature for data.gpg made Mon Feb 3 17:54:21 2014 signature 4096/RSA (Encrypt or Sign) 4d129225945bbb8f 1970-01-01 fingerprint 874b 75de d6a3 341f 2d5a 2219 4d12 9225 945b bb8f uid netbsd-001.cupertino.alistaircrooks.com (sshtest-20140202.pub) <agc@netbsd-001.cupertino.alistaircrooks.com> ./netpgpverify -S sshtest-20140202.pub data.sig Good signature for data.sig made Sun Feb 2 21:45:05 2014 signature 4096/RSA (Encrypt or Sign) 4d129225945bbb8f 1970-01-01 fingerprint 874b 75de d6a3 341f 2d5a 2219 4d12 9225 945b bb8f uid netbsd-001.cupertino.alistaircrooks.com (sshtest-20140202.pub) <agc@netbsd-001.cupertino.alistaircrooks.com> expected failure, to check bad signatures fail to verify sed -e 's|A|B|' data.gpg | ./netpgpverify -S sshtest-20140202.pub Signature did not match contents -- Signature on data did not match *** Error code 1 (ignored) % A new HOWTO file is provided in the sources (files/HOWTO) to show how to sign data using ssh keys and netpgp(1).
Diffstat (limited to 'security')
-rw-r--r--security/netpgpverify/Makefile6
-rw-r--r--security/netpgpverify/files/Makefile.bsd23
-rw-r--r--security/netpgpverify/files/Makefile.in9
-rw-r--r--security/netpgpverify/files/bignum.c2
-rw-r--r--security/netpgpverify/files/bufgap.c508
-rw-r--r--security/netpgpverify/files/bufgap.h88
-rwxr-xr-xsecurity/netpgpverify/files/chk.sh119
-rw-r--r--security/netpgpverify/files/data28
-rw-r--r--security/netpgpverify/files/data.gpgbin0 -> 1056 bytes
-rw-r--r--security/netpgpverify/files/data.sigbin0 -> 549 bytes
-rw-r--r--security/netpgpverify/files/defs.h92
-rw-r--r--security/netpgpverify/files/libverify.c389
-rw-r--r--security/netpgpverify/files/main.c34
-rw-r--r--security/netpgpverify/files/netpgpverify.128
-rw-r--r--security/netpgpverify/files/pubring.gpgbin19264 -> 2009747 bytes
-rw-r--r--security/netpgpverify/files/sshtest-2014020251
-rw-r--r--security/netpgpverify/files/sshtest-20140202.pub1
-rw-r--r--security/netpgpverify/files/verify.h10
18 files changed, 1324 insertions, 64 deletions
diff --git a/security/netpgpverify/Makefile b/security/netpgpverify/Makefile
index 0d7c4cd454b..c7682b3793f 100644
--- a/security/netpgpverify/Makefile
+++ b/security/netpgpverify/Makefile
@@ -1,13 +1,13 @@
-# $NetBSD: Makefile,v 1.4 2013/12/20 17:16:48 agc Exp $
+# $NetBSD: Makefile,v 1.5 2014/02/04 02:11:18 agc Exp $
-DISTNAME= netpgpverify-20131219
+DISTNAME= netpgpverify-20140202
CATEGORIES= security
MASTER_SITES= # empty
DISTFILES= # empty
MAINTAINER= agc@NetBSD.org
HOMEPAGE= http://www.NetBSD.org/
-COMMENT= Standalone PGP signature verification utility
+COMMENT= Standalone PGP and ssh signature verification utility
LICENSE= modified-bsd
AUTO_MKDIRS= yes
diff --git a/security/netpgpverify/files/Makefile.bsd b/security/netpgpverify/files/Makefile.bsd
index 95a445a4181..327bc74e877 100644
--- a/security/netpgpverify/files/Makefile.bsd
+++ b/security/netpgpverify/files/Makefile.bsd
@@ -1,23 +1,32 @@
-# $NetBSD: Makefile.bsd,v 1.1 2013/03/16 07:32:34 agc Exp $
+# $NetBSD: Makefile.bsd,v 1.2 2014/02/04 02:11:18 agc Exp $
PROG=netpgpverify
-SRCS= b64.c bignum.c digest.c
+SRCS= b64.c bignum.c bufgap.c digest.c
SRCS+= libverify.c main.c misc.c
SRCS+= pgpsum.c rsa.c
-SRCS+= tiger.c
SRCS+= bzlib.c zlib.c
-SRCS+= sha1.c sha2.c md5c.c rmd160.c
+SRCS+= md5c.c rmd160.c sha1.c sha2.c tiger.c
-MAN=netpgpverify.1
+CPPFLAGS+=-I.
-WARNS=5
+.ifndef PRODUCTION
+CPPFLAGS+=-g -O0
+LDFLAGS+=-g -O0
+.endif
+
+MAN= netpgpverify.1
+WARNS= 6
.include <bsd.prog.mk>
-t: ${PROG}
+tst:
./${PROG} -k pubring.gpg NetBSD-6.0_RC1_hashes.asc
./${PROG} -k pubring.gpg NetBSD-6.0_RC1_hashes.gpg
./${PROG} -v
+ ./${PROG} -S sshtest-20140202.pub data.gpg
+ ./${PROG} -S sshtest-20140202.pub data.sig
+ @echo "expected failure, to check bad signatures fail to verify"
+ -sed -e 's|A|B|' data.gpg | ./${PROG} -S sshtest-20140202.pub
diff --git a/security/netpgpverify/files/Makefile.in b/security/netpgpverify/files/Makefile.in
index e04f7f40d3e..b5556238865 100644
--- a/security/netpgpverify/files/Makefile.in
+++ b/security/netpgpverify/files/Makefile.in
@@ -1,15 +1,14 @@
-# $NetBSD: Makefile.in,v 1.1 2013/03/16 07:32:34 agc Exp $
+# $NetBSD: Makefile.in,v 1.2 2014/02/04 02:11:18 agc Exp $
PROG=netpgpverify
-OBJS= b64.o bignum.o digest.o
+OBJS= b64.o bignum.o bufgap.o digest.o
OBJS+= libverify.o main.o misc.o
OBJS+= pgpsum.o rsa.o
-OBJS+= tiger.o
OBJS+= bzlib.o zlib.o
-OBJS+= sha1.o sha2.o md5c.o rmd160.o
+OBJS+= sha1.o sha2.o md5c.o rmd160.o tiger.o
PREFIX=@PREFIX@
MANDIR=@MANDIR@
@@ -27,6 +26,8 @@ tst:
./${PROG} -k pubring.gpg NetBSD-6.0_RC1_hashes.asc
./${PROG} -k pubring.gpg NetBSD-6.0_RC1_hashes.gpg
./${PROG} -v
+ ./${PROG} -S testkey.pub data.gpg
+ ./${PROG} -S testkey.pub data.sig
clean:
rm -rf *.core ${OBJS} ${PROG}
diff --git a/security/netpgpverify/files/bignum.c b/security/netpgpverify/files/bignum.c
index e983005328a..c825b30c501 100644
--- a/security/netpgpverify/files/bignum.c
+++ b/security/netpgpverify/files/bignum.c
@@ -5157,7 +5157,7 @@ getbn(BIGNUM **a, const char *str, int radix)
if (mp_getradix_num(*a, radix, __UNCONST(str)) != MP_OKAY) {
return 0;
}
- mp_radix_size(__UNCONST(*a), radix, &len);
+ mp_radix_size(__UNCONST(a), radix, &len);
return len - 1;
}
diff --git a/security/netpgpverify/files/bufgap.c b/security/netpgpverify/files/bufgap.c
new file mode 100644
index 00000000000..66a30ec5dcd
--- /dev/null
+++ b/security/netpgpverify/files/bufgap.c
@@ -0,0 +1,508 @@
+/* $NetBSD: bufgap.c,v 1.1 2014/02/04 02:11:18 agc Exp $ */
+
+/*-
+ * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (agc@NetBSD.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bufgap.h"
+#include "defs.h"
+
+/* macros to get subscripts in buffer */
+#define AFTSUB(bp, n) ((bp)->buf[(int)n])
+#define BEFSUB(bp, n) ((bp)->buf[(int)((bp)->size - (n) - 1)])
+
+/* initial allocation size */
+#ifndef CHUNKSIZE
+#define CHUNKSIZE 256
+#endif
+
+#ifndef KiB
+#define KiB(x) ((x) * 1024)
+#endif
+
+#define BGCHUNKSIZE KiB(4)
+
+#ifndef __UNCONST
+#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
+#endif
+
+#ifndef USE_UTF
+#define USE_UTF 0
+#endif
+
+#if !USE_UTF
+#define Rune char
+#define utfbytes(x) strlen(x)
+#define utfrune(a, b) strchr(a, b)
+#define utfnlen(a, b) bounded_strlen(a, b)
+
+static size_t
+bounded_strlen(const char *s, size_t maxlen)
+{
+ size_t n;
+
+ for (n = 0 ; n < maxlen && s[n] != 0x0 ; n++) {
+ }
+ return n;
+}
+
+static int
+chartorune(Rune *rp, char *s)
+{
+ *rp = s[0];
+ return 1;
+}
+
+static int
+priorrune(Rune *rp, char *s)
+{
+ *rp = s[0];
+ return 1;
+}
+#else
+#include "ure.h"
+#endif
+
+/* save `n' chars of `s' in malloc'd memory */
+static char *
+strnsave(char *s, int n)
+{
+ char *cp;
+
+ if (n < 0) {
+ n = (int)strlen(s);
+ }
+ NEWARRAY(char, cp, n + 1, "strnsave", return NULL);
+ (void) memcpy(cp, s, (size_t)n);
+ cp[n] = 0x0;
+ return cp;
+}
+
+/* open a file in a buffer gap structure */
+int
+bufgap_open(bufgap_t *bp, const char *f)
+{
+ struct stat s;
+ int64_t cc;
+ FILE *filep;
+ char *cp;
+
+ (void) memset(bp, 0x0, sizeof(*bp));
+ filep = NULL;
+ if (f != NULL && (filep = fopen(f, "r")) == NULL) {
+ return 0;
+ }
+ if (f == NULL) {
+ bp->size = BGCHUNKSIZE;
+ NEWARRAY(char, bp->buf, bp->size, "f_open", return 0);
+ } else {
+ (void) fstat(fileno(filep), &s);
+ bp->size = (int) ((s.st_size / BGCHUNKSIZE) + 1) * BGCHUNKSIZE;
+ NEWARRAY(char, bp->buf, bp->size, "f_open", return 0);
+ cc = fread(&BEFSUB(bp, s.st_size), sizeof(char),
+ (size_t)s.st_size, filep);
+ (void) fclose(filep);
+ if (cc != s.st_size) {
+ FREE(bp->buf);
+ FREE(bp);
+ return 0;
+ }
+ bp->name = strnsave(__UNCONST(f), (int)utfbytes(__UNCONST(f)));
+ bp->bbc = s.st_size;
+ cp = &BEFSUB(bp, cc);
+ for (;;) {
+ if ((cp = utfrune(cp, '\n')) == NULL) {
+ break;
+ }
+ bp->blc++;
+ cp++;
+ }
+ bp->bcc = utfnlen(&BEFSUB(bp, cc), (size_t)cc);
+ }
+ return 1;
+}
+
+/* close a buffer gapped file */
+void
+bufgap_close(bufgap_t *bp)
+{
+ FREE(bp->buf);
+}
+
+/* move forwards `n' chars/bytes in a buffer gap */
+int
+bufgap_forwards(bufgap_t *bp, uint64_t n, int type)
+{
+ Rune r;
+ int rlen;
+
+ switch(type) {
+ case BGChar:
+ if (bp->bcc >= n) {
+ while (n-- > 0) {
+ rlen = chartorune(&r, &BEFSUB(bp, bp->bbc));
+ if (rlen == 1) {
+ AFTSUB(bp, bp->abc) = BEFSUB(bp, bp->bbc);
+ } else {
+ (void) memmove(&AFTSUB(bp, bp->abc),
+ &BEFSUB(bp, bp->bbc),
+ (size_t)rlen);
+ }
+ bp->acc++;
+ bp->bcc--;
+ bp->abc += rlen;
+ bp->bbc -= rlen;
+ if (r == '\n') {
+ bp->alc++;
+ bp->blc--;
+ }
+ }
+ return 1;
+ }
+ break;
+ case BGByte:
+ if (bp->bbc >= n) {
+ for ( ; n > 0 ; n -= rlen) {
+ rlen = chartorune(&r, &BEFSUB(bp, bp->bbc));
+ if (rlen == 1) {
+ AFTSUB(bp, bp->abc) = BEFSUB(bp, bp->bbc);
+ } else {
+ (void) memmove(&AFTSUB(bp, bp->abc),
+ &BEFSUB(bp, bp->bbc),
+ (size_t)rlen);
+ }
+ bp->acc++;
+ bp->bcc--;
+ bp->abc += rlen;
+ bp->bbc -= rlen;
+ if (r == '\n') {
+ bp->alc++;
+ bp->blc--;
+ }
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* move backwards `n' chars in a buffer gap */
+int
+bufgap_backwards(bufgap_t *bp, uint64_t n, int type)
+{
+ Rune r;
+ int rlen;
+
+ switch(type) {
+ case BGChar:
+ if (bp->acc >= n) {
+ while (n-- > 0) {
+ rlen = priorrune(&r, &AFTSUB(bp, bp->abc));
+ bp->bcc++;
+ bp->acc--;
+ bp->bbc += rlen;
+ bp->abc -= rlen;
+ if (rlen == 1) {
+ BEFSUB(bp, bp->bbc) = AFTSUB(bp, bp->abc);
+ } else {
+ (void) memmove(&BEFSUB(bp, bp->bbc),
+ &AFTSUB(bp, bp->abc),
+ (size_t)rlen);
+ }
+ if (r == '\n') {
+ bp->blc++;
+ bp->alc--;
+ }
+ }
+ return 1;
+ }
+ break;
+ case BGByte:
+ if (bp->acc >= n) {
+ for ( ; n > 0 ; n -= rlen) {
+ rlen = priorrune(&r, &AFTSUB(bp, bp->abc));
+ bp->bcc++;
+ bp->acc--;
+ bp->bbc += rlen;
+ bp->abc -= rlen;
+ if (rlen == 1) {
+ BEFSUB(bp, bp->bbc) = AFTSUB(bp, bp->abc);
+ } else {
+ (void) memmove(&BEFSUB(bp, bp->bbc),
+ &AFTSUB(bp, bp->abc),
+ (size_t)rlen);
+ }
+ if (r == '\n') {
+ bp->blc++;
+ bp->alc--;
+ }
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* move within a buffer gap */
+int
+bufgap_seek(bufgap_t *bp, int64_t off, int whence, int type)
+{
+ switch(type) {
+ case BGLine:
+ switch(whence) {
+ case BGFromBOF:
+ if (off < 0 || off > (int64_t)(bp->alc + bp->blc)) {
+ return 0;
+ }
+ if (off < (int64_t)bp->alc) {
+ while (off <= (int64_t)bp->alc && bufgap_backwards(bp, 1, BGChar)) {
+ }
+ if (off > 0) {
+ (void) bufgap_forwards(bp, 1, BGChar);
+ }
+ } else if (off > (int64_t)bp->alc) {
+ while (off > (int64_t)bp->alc && bufgap_forwards(bp, 1, BGChar)) {
+ }
+ }
+ return 1;
+ case BGFromHere:
+ return bufgap_seek(bp, (int64_t)(bp->alc + off), BGFromBOF, BGLine);
+ case BGFromEOF:
+ return bufgap_seek(bp, (int64_t)(bp->alc + bp->blc + off), BGFromBOF, BGLine);
+ }
+ break;
+ case BGChar:
+ switch(whence) {
+ case BGFromBOF:
+ if (off < 0 || off > (int64_t)(bp->acc + bp->bcc)) {
+ return 0;
+ }
+ if (off < (int64_t)bp->acc) {
+ return bufgap_backwards(bp, bp->acc - off, BGChar);
+ } else if (off > (int64_t)bp->acc) {
+ return bufgap_forwards(bp, off - bp->acc, BGChar);
+ }
+ return 1;
+ case BGFromHere:
+ return bufgap_seek(bp, (int64_t)(bp->acc + off), BGFromBOF, BGChar);
+ case BGFromEOF:
+ return bufgap_seek(bp, (int64_t)(bp->acc + bp->bcc + off), BGFromBOF, BGChar);
+ }
+ break;
+ case BGByte:
+ switch(whence) {
+ case BGFromBOF:
+ if (off < 0 || off > (int64_t)(bp->abc + bp->bbc)) {
+ return 0;
+ }
+ if (off < (int64_t)bp->abc) {
+ return bufgap_backwards(bp, bp->abc - off, BGByte);
+ } else if (off > (int64_t)bp->abc) {
+ return bufgap_forwards(bp, off - bp->abc, BGByte);
+ }
+ return 1;
+ case BGFromHere:
+ return bufgap_seek(bp, (int64_t)(bp->abc + off), BGFromBOF, BGByte);
+ case BGFromEOF:
+ return bufgap_seek(bp, (int64_t)(bp->abc + bp->bbc + off), BGFromBOF, BGByte);
+ }
+ break;
+ }
+ return 0;
+}
+
+/* return a pointer to the text in the buffer gap */
+char *
+bufgap_getstr(bufgap_t *bp)
+{
+ return &BEFSUB(bp, bp->bbc);
+}
+
+/* return the binary text in the buffer gap */
+int
+bufgap_getbin(bufgap_t *bp, void *dst, size_t len)
+{
+ int cc;
+
+ cc = (bp->bcc < len) ? (int)bp->bcc : (int)len;
+ (void) memcpy(dst, &BEFSUB(bp, bp->bbc), len);
+ return cc;
+}
+
+/* return offset (from beginning/end) in a buffer gap */
+int64_t
+bufgap_tell(bufgap_t *bp, int whence, int type)
+{
+ switch(whence) {
+ case BGFromBOF:
+ return (type == BGLine) ? bp->alc :
+ (type == BGByte) ? bp->abc : bp->acc;
+ case BGFromEOF:
+ return (type == BGLine) ? bp->blc :
+ (type == BGByte) ? bp->bbc : bp->bcc;
+ default:
+ (void) fprintf(stderr, "weird whence in bufgap_tell\n");
+ break;
+ }
+ return (int64_t)0;
+}
+
+/* return size of buffer gap */
+int64_t
+bufgap_size(bufgap_t *bp, int type)
+{
+ return (type == BGLine) ? bp->alc + bp->blc :
+ (type == BGChar) ? bp->acc + bp->bcc :
+ bp->abc + bp->bbc;
+}
+
+/* insert `n' chars of `s' in a buffer gap */
+int
+bufgap_insert(bufgap_t *bp, const char *s, int n)
+{
+ int64_t off;
+ Rune r;
+ int rlen;
+ int i;
+
+ if (n < 0) {
+ n = (int)strlen(s);
+ }
+ for (i = 0 ; i < n ; i += rlen) {
+ if (bp->bbc + bp->abc == bp->size) {
+ off = bufgap_tell(bp, BGFromBOF, BGChar);
+ (void) bufgap_seek(bp, 0, BGFromEOF, BGChar);
+ bp->size *= 2;
+ RENEW(char, bp->buf, bp->size, "bufgap_insert", return 0);
+ (void) bufgap_seek(bp, off, BGFromBOF, BGChar);
+ }
+ if ((rlen = chartorune(&r, __UNCONST(s))) == 1) {
+ AFTSUB(bp, bp->abc) = *s;
+ } else {
+ (void) memmove(&AFTSUB(bp, bp->abc), s, (size_t)rlen);
+ }
+ if (r == '\n') {
+ bp->alc++;
+ }
+ bp->modified = 1;
+ bp->abc += rlen;
+ bp->acc++;
+ s += rlen;
+ }
+ return 1;
+}
+
+/* delete `n' bytes from the buffer gap */
+int
+bufgap_delete(bufgap_t *bp, uint64_t n)
+{
+ uint64_t i;
+ Rune r;
+ int rlen;
+
+ if (n <= bp->bbc) {
+ for (i = 0 ; i < n ; i += rlen) {
+ rlen = chartorune(&r, &BEFSUB(bp, bp->bbc));
+ if (r == '\n') {
+ bp->blc--;
+ }
+ bp->bbc -= rlen;
+ bp->bcc--;
+ bp->modified = 1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/* look at a character in a buffer gap `delta' UTF chars away */
+int
+bufgap_peek(bufgap_t *bp, int64_t delta)
+{
+ int ch;
+
+ if (delta != 0) {
+ if (!bufgap_seek(bp, delta, BGFromHere, BGChar)) {
+ return -1;
+ }
+ }
+ ch = BEFSUB(bp, bp->bbc);
+ if (delta != 0) {
+ (void) bufgap_seek(bp, -delta, BGFromHere, BGChar);
+ }
+ return ch;
+}
+
+/* return, in malloc'd storage, text from the buffer gap */
+char *
+bufgap_gettext(bufgap_t *bp, int64_t from, int64_t to)
+{
+ int64_t off;
+ int64_t n;
+ char *text;
+
+ off = bufgap_tell(bp, BGFromBOF, BGChar);
+ NEWARRAY(char, text, (to - from + 1), "bufgap_gettext", return NULL);
+ (void) bufgap_seek(bp, from, BGFromBOF, BGChar);
+ for (n = 0 ; n < to - from ; n++) {
+ text[(int)n] = BEFSUB(bp, bp->bbc - n);
+ }
+ text[(int)n] = 0x0;
+ (void) bufgap_seek(bp, off, BGFromBOF, BGChar);
+ return text;
+}
+
+/* return 1 if we wrote the file correctly */
+int
+bufgap_write(bufgap_t *bp, FILE *filep)
+{
+ if (fwrite(bp->buf, sizeof(char), (size_t)bp->abc, filep) != (size_t)bp->abc) {
+ return 0;
+ }
+ if (fwrite(&BEFSUB(bp, bp->bbc), sizeof(char), (size_t)bp->bbc, filep) != (size_t)bp->bbc) {
+ return 0;
+ }
+ return 1;
+}
+
+/* tell if the buffer gap is dirty - has been modified */
+int
+bufgap_dirty(bufgap_t *bp)
+{
+ return (int)bp->modified;
+}
diff --git a/security/netpgpverify/files/bufgap.h b/security/netpgpverify/files/bufgap.h
new file mode 100644
index 00000000000..1ad24679cc6
--- /dev/null
+++ b/security/netpgpverify/files/bufgap.h
@@ -0,0 +1,88 @@
+/* $NetBSD: bufgap.h,v 1.1 2014/02/04 02:11:18 agc Exp $ */
+
+/*-
+ * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (agc@NetBSD.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef BUFGAP_H_
+#define BUFGAP_H_ 20091023
+
+#include <sys/types.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#ifndef BUFGAP_VERSION_STRING
+#define BUFGAP_VERSION_STRING "20091022"
+#endif
+
+#ifndef BUFGAP_AUTHOR_STRING
+#define BUFGAP_AUTHOR_STRING "Alistair Crooks (agc@netbsd.org)"
+#endif
+
+/* Constants for Buffer Gap routines */
+enum {
+ BGByte,
+ BGChar,
+ BGLine,
+
+ BGFromBOF,
+ BGFromHere,
+ BGFromEOF
+};
+
+/* this struct describes a file in memory */
+typedef struct bufgap_t {
+ uint64_t size; /* size of file */
+ uint64_t abc; /* # of bytes after the gap */
+ uint64_t bbc; /* # of bytes before the gap */
+ uint64_t acc; /* # of utf chars after the gap */
+ uint64_t bcc; /* # of utf chars before the gap */
+ uint64_t alc; /* # of records after the gap */
+ uint64_t blc; /* # of records before the gap */
+ char *name; /* file name - perhaps null */
+ char *buf; /* buffer-gap buffer */
+ char modified; /* file has been modified */
+} bufgap_t;
+
+int bufgap_open(bufgap_t *, const char *);
+void bufgap_close(bufgap_t *);
+int bufgap_forwards(bufgap_t *, uint64_t, int);
+int bufgap_backwards(bufgap_t *, uint64_t, int);
+int bufgap_seek(bufgap_t *, int64_t, int, int);
+char *bufgap_getstr(bufgap_t *);
+int bufgap_getbin(bufgap_t *, void *, size_t);
+int64_t bufgap_tell(bufgap_t *, int, int);
+int64_t bufgap_size(bufgap_t *, int);
+int bufgap_insert(bufgap_t *, const char *, int);
+int bufgap_delete(bufgap_t *, uint64_t);
+int bufgap_peek(bufgap_t *, int64_t);
+char *bufgap_gettext(bufgap_t *, int64_t, int64_t);
+int bufgap_write(bufgap_t *, FILE *);
+int bufgap_dirty(bufgap_t *);
+
+#endif /* !BUFGAP_H_ */
diff --git a/security/netpgpverify/files/chk.sh b/security/netpgpverify/files/chk.sh
new file mode 100755
index 00000000000..8af99f1a360
--- /dev/null
+++ b/security/netpgpverify/files/chk.sh
@@ -0,0 +1,119 @@
+#! /bin/sh
+
+# $NetBSD: chk.sh,v 1.1 2014/02/04 02:11:18 agc Exp $
+
+# Copyright (c) 2013,2014 Alistair Crooks <agc@NetBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+die() {
+ echo "$*" >&2
+ exit 1
+}
+
+os=EdgeBSD
+osrev=6
+arch=amd64
+pkgsrc=pkgsrc-2013Q2
+keyring=""
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --arch|-a) arch=$2; shift ;;
+ --keyring|-k) keyring=$2; shift ;;
+ --os|-o) os=$2; shift ;;
+ --pkgsrc) pkgsrc=$2; shift ;;
+ -v) set -x ;;
+ *) break ;;
+ esac
+ shift
+done
+
+case "${keyring}" in
+"") keyring=$HOME/.gnupg/pubring.gpg ;;
+esac
+
+#fetch file
+repo=ftp://ftp.edgebsd.org/pub/pkgsrc/packages/${os}/${arch}/${os}-${osrev}/${pkgsrc}/All/
+
+if [ ! -f $1 ]; then
+ case "${repo}" in
+ */) remote=${repo}$1 ;;
+ *) remote=${repo}/$1 ;;
+ esac
+ ftp ${remote}
+fi
+
+name=$(basename $1 .tgz)
+dir=$(mktemp -d /tmp/chk.XXXXXX)
+here=$(pwd)
+case "$1" in
+/*) archive=$1 ;;
+*) archive=${here}/$1 ;;
+esac
+(cd ${dir} && ar x ${archive})
+
+# grab values from already calculated hashes
+digest=$(awk '$1 ~ /algorithm:/ { print $2 }' ${dir}/+PKG_HASH)
+blocksize=$(awk '/^block size:/ { print $3 }' ${dir}/+PKG_HASH)
+
+# check the hashes in +PKG_HASH match the original archive
+size=$(ls -l ${dir}/$1 | awk '{ print $5 }')
+printf "pkgsrc signature\n\nversion: 1\n" > ${dir}/calc
+printf "pkgname: %s\n" ${name} >> ${dir}/calc
+printf "algorithm: ${digest}\n" >> ${dir}/calc
+printf "block size: ${blocksize}\n" >> ${dir}/calc
+printf "file size: %s\n\n" ${size} >> ${dir}/calc
+off=0
+n=0
+while [ ${off} -lt ${size} ]; do
+ rm -f ${dir}/in
+ dd if=${dir}/$1 of=${dir}/in bs=${blocksize} count=1 skip=${n} 2>/dev/null
+ digest ${digest} < ${dir}/in >> ${dir}/calc
+ off=$(( off + ${blocksize} ))
+ n=$(( n + 1 ))
+done
+printf "end pkgsrc signature\n" >> ${dir}/calc
+
+# make sure what was signed is what we have
+diff ${dir}/+PKG_HASH ${dir}/calc || die "Bad hashes generated"
+
+# use netpgpverify to verify the signature
+if [ -x /usr/pkg/bin/netpgpverify ]; then
+ # check the signature in +PKG_GPG_SIGNATURE
+ cp ${keyring} ${dir}/pubring.gpg
+ # calculate the sig file we want to verify
+ echo "-----BEGIN PGP SIGNED MESSAGE-----" > ${dir}/${name}.sig
+ echo "Hash: ${digest}" >> ${dir}/${name}.sig
+ echo "" >> ${dir}/${name}.sig
+ cat ${dir}/+PKG_HASH ${dir}/+PKG_GPG_SIGNATURE >> ${dir}/${name}.sig
+ (cd ${dir} && netpgpverify -k pubring.gpg ${name}.sig) || die "Bad signature"
+else
+ gpg --recv 0x6F3AF5E2
+ (cd ${dir} && gpg --verify --homedir=${dir} ./+PKG_GPG_SIGNATURE ./+PKG_HASH) || die "Bad signature"
+fi
+echo "Signatures match on ${name} package"
+
+# clean up
+rm -rf ${dir}
+
+exit 0
diff --git a/security/netpgpverify/files/data b/security/netpgpverify/files/data
new file mode 100644
index 00000000000..5e8b66cf701
--- /dev/null
+++ b/security/netpgpverify/files/data
@@ -0,0 +1,28 @@
+# $NetBSD: data,v 1.1 2014/02/04 02:11:18 agc Exp $
+
+PROG=netpgpverify
+
+SRCS= b64.c bignum.c digest.c
+SRCS+= libverify.c main.c misc.c
+SRCS+= pgpsum.c rsa.c
+
+SRCS+= bzlib.c zlib.c
+
+SRCS+= sha1.c sha2.c md5c.c rmd160.c tiger.c
+
+CPPFLAGS+=-I.
+
+.ifndef PRODUCTION
+CPPFLAGS+=-g -O0
+LDFLAGS+=-g -O0
+.endif
+
+MAN= netpgpverify.1
+WARNS= 6
+
+.include <bsd.prog.mk>
+
+tst:
+ ./${PROG} -k pubring.gpg NetBSD-6.0_RC1_hashes.asc
+ ./${PROG} -k pubring.gpg NetBSD-6.0_RC1_hashes.gpg
+ ./${PROG} -v
diff --git a/security/netpgpverify/files/data.gpg b/security/netpgpverify/files/data.gpg
new file mode 100644
index 00000000000..77b8460c0fe
--- /dev/null
+++ b/security/netpgpverify/files/data.gpg
Binary files differ
diff --git a/security/netpgpverify/files/data.sig b/security/netpgpverify/files/data.sig
new file mode 100644
index 00000000000..a5c6443ac20
--- /dev/null
+++ b/security/netpgpverify/files/data.sig
Binary files differ
diff --git a/security/netpgpverify/files/defs.h b/security/netpgpverify/files/defs.h
new file mode 100644
index 00000000000..db51ecb7b41
--- /dev/null
+++ b/security/netpgpverify/files/defs.h
@@ -0,0 +1,92 @@
+/* $NetBSD: defs.h,v 1.1 2014/02/04 02:11:18 agc Exp $ */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Alistair Crooks (agc@NetBSD.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DEFS_H_
+#define DEFS_H_
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define NEWARRAY(type,ptr,size,where,action) do { \
+ if ((ptr = calloc(sizeof(type), (unsigned)(size))) == NULL) { \
+ (void) fprintf(stderr, "%s: can't allocate %lu bytes\n", \
+ where, (unsigned long)(size * sizeof(type))); \
+ action; \
+ } \
+} while( /* CONSTCOND */ 0)
+
+#define RENEW(type,ptr,size,where,action) do { \
+ type *_newptr; \
+ _newptr = realloc(ptr, (size_t)(sizeof(type) * (size))); \
+ if (_newptr == NULL) { \
+ (void) fprintf(stderr, "%s: can't realloc %lu bytes\n", \
+ where, (unsigned long)(size * sizeof(type))); \
+ action; \
+ } else { \
+ ptr = _newptr; \
+ } \
+} while( /* CONSTCOND */ 0)
+
+#define NEW(type, ptr, where, action) NEWARRAY(type, ptr, 1, where, action)
+
+#define FREE(ptr) (void) free(ptr)
+
+#define ALLOC(type, v, size, c, init, incr, where, action) do { \
+ uint32_t _newsize = size; \
+ if (size == 0) { \
+ _newsize = init; \
+ NEWARRAY(type, v, _newsize, where ": new", action); \
+ } else if (c == size) { \
+ _newsize = size + incr; \
+ RENEW(type, v, _newsize, where ": renew", action); \
+ } \
+ size = _newsize; \
+} while( /* CONSTCOND */ 0)
+
+#define DEFINE_ARRAY(name, type) \
+typedef struct name { \
+ uint32_t c; \
+ uint32_t size; \
+ type *v; \
+} name
+
+#endif /* !DEFS_H_ */
diff --git a/security/netpgpverify/files/libverify.c b/security/netpgpverify/files/libverify.c
index 571085a39ff..9437855c3eb 100644
--- a/security/netpgpverify/files/libverify.c
+++ b/security/netpgpverify/files/libverify.c
@@ -43,8 +43,9 @@
#include "zlib.h"
#include "array.h"
-#include "bn.h"
#include "b64.h"
+#include "bn.h"
+#include "bufgap.h"
#include "digest.h"
#include "pgpsum.h"
#include "rsa.h"
@@ -151,7 +152,6 @@
static int read_all_packets(pgpv_t */*pgp*/, pgpv_mem_t */*mem*/, const char */*op*/);
static int read_binary_file(pgpv_t */*pgp*/, const char */*op*/, const char */*fmt*/, ...);
static int read_binary_memory(pgpv_t */*pgp*/, const char */*op*/, const void */*memory*/, size_t /*size*/);
-static int pgpv_find_keyid(pgpv_t */*pgp*/, const char */*strkeyid*/, uint8_t */*keyid*/);
/* read a file into the pgpv_mem_t struct */
static int
@@ -296,6 +296,68 @@ get_pkt_len(uint8_t newfmt, uint8_t *p, size_t filesize, int isprimary)
}
}
+static const uint8_t base64s[] =
+/* 000 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 016 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 032 */ "\0\0\0\0\0\0\0\0\0\0\0?\0\0\0@"
+/* 048 */ "56789:;<=>\0\0\0\0\0\0"
+/* 064 */ "\0\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"
+/* 080 */ "\20\21\22\23\24\25\26\27\30\31\32\0\0\0\0\0"
+/* 096 */ "\0\33\34\35\36\37 !\"#$%&'()"
+/* 112 */ "*+,-./01234\0\0\0\0\0"
+/* 128 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 144 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 160 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 176 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 192 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 208 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 224 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+/* 240 */ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+
+/* short function to decode from base64 */
+/* inspired by an ancient copy of b64.c, then rewritten, the bugs are all mine */
+static int
+frombase64(char *dst, const char *src, size_t size, int flag)
+{
+ uint8_t out[3];
+ uint8_t in[4];
+ uint8_t b;
+ size_t srcc;
+ int dstc;
+ int gotc;
+ int i;
+
+ USE_ARG(flag);
+ for (dstc = 0, srcc = 0 ; srcc < size; ) {
+ for (gotc = 0, i = 0; i < 4 && srcc < size; i++) {
+ for (b = 0x0; srcc < size && b == 0x0 ; ) {
+ b = base64s[(unsigned)src[srcc++]];
+ }
+ if (srcc < size) {
+ gotc += 1;
+ if (b) {
+ in[i] = (uint8_t)(b - 1);
+ }
+ } else {
+ in[i] = 0x0;
+ }
+ }
+ if (gotc) {
+ out[0] = (uint8_t)((unsigned)in[0] << 2 |
+ (unsigned)in[1] >> 4);
+ out[1] = (uint8_t)((unsigned)in[1] << 4 |
+ (unsigned)in[2] >> 2);
+ out[2] = (uint8_t)(((in[2] << 6) & 0xc0) | in[3]);
+ for (i = 0; i < gotc - 1; i++) {
+ *dst++ = out[i];
+ }
+ dstc += gotc - 1;
+ }
+ }
+ return dstc;
+}
+
/* get the length of the packet length field */
static unsigned
get_pkt_len_len(uint8_t newfmt, uint8_t *p, int isprimary)
@@ -403,8 +465,8 @@ fmt_key_mpis(pgpv_pubkey_t *pubkey, uint8_t *buf, size_t size)
cc = 0;
buf[cc++] = pubkey->version;
- cc += fmt_32(&buf[cc], (uint32_t)pubkey->birth);
- buf[cc++] = pubkey->keyalg;
+ cc += fmt_32(&buf[cc], (uint32_t)pubkey->birth); /* XXX - do this portably! */
+ buf[cc++] = pubkey->keyalg; /* XXX - sign, or encrypt and sign? */
switch(pubkey->keyalg) {
case PUBKEY_RSA_ENCRYPT_OR_SIGN:
case PUBKEY_RSA_ENCRYPT:
@@ -429,7 +491,7 @@ fmt_key_mpis(pgpv_pubkey_t *pubkey, uint8_t *buf, size_t size)
/* calculate the fingerprint, RFC 4880, section 12.2 */
static int
-pgpv_calc_fingerprint(pgpv_fingerprint_t *fingerprint, pgpv_pubkey_t *pubkey)
+pgpv_calc_fingerprint(pgpv_fingerprint_t *fingerprint, pgpv_pubkey_t *pubkey, const char *hashtype)
{
digest_t fphash;
uint16_t cc;
@@ -440,7 +502,7 @@ pgpv_calc_fingerprint(pgpv_fingerprint_t *fingerprint, pgpv_pubkey_t *pubkey)
memset(&fphash, 0x0, sizeof(fphash));
if (pubkey->version == 4) {
/* v4 keys */
- fingerprint->hashalg = digest_get_alg("sha1");
+ fingerprint->hashalg = digest_get_alg(hashtype);
digest_init(&fphash, (unsigned)fingerprint->hashalg);
cc = fmt_key_mpis(pubkey, buf, sizeof(buf));
digest_update(&fphash, &ch, 1);
@@ -493,9 +555,9 @@ fmt_fingerprint(char *s, size_t size, pgpv_fingerprint_t *fingerprint, const cha
/* calculate keyid from a pubkey */
static int
-pgpv_calc_keyid(pgpv_pubkey_t *key)
+calc_keyid(pgpv_pubkey_t *key, const char *hashtype)
{
- pgpv_calc_fingerprint(&key->fingerprint, key);
+ pgpv_calc_fingerprint(&key->fingerprint, key, hashtype);
memcpy(key->keyid, &key->fingerprint.v[key->fingerprint.len - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
return 1;
}
@@ -1387,22 +1449,45 @@ fmt_userid(char *s, size_t size, pgpv_primarykey_t *primary, uint8_t u)
(userid->revoked) ? " [REVOKED]" : "");
}
+/* format a trust sig - used to order the userids when formatting */
+static size_t
+fmt_trust(char *s, size_t size, pgpv_signed_userid_t *userid, uint32_t u)
+{
+ pgpv_signature_t *sig;
+ size_t cc;
+
+ sig = &ARRAY_ELEMENT(userid->sigs, u);
+ cc = snprintf(s, size, "trust ");
+ cc += fmt_binary(&s[cc], size - cc, sig->signer, 8);
+ return cc + snprintf(&s[cc], size - cc, "\n");
+}
+
/* print a primary key, per RFC 4880 */
static size_t
-fmt_primary(char *s, size_t size, pgpv_primarykey_t *primary, int dosubkeys)
+fmt_primary(char *s, size_t size, pgpv_primarykey_t *primary, const char *modifiers)
{
- unsigned i;
- size_t cc;
+ pgpv_signed_userid_t *userid;
+ unsigned i;
+ unsigned j;
+ size_t cc;
cc = fmt_pubkey(s, size, &primary->primary, "signature ");
cc += fmt_userid(&s[cc], size - cc, primary, primary->primary_userid);
for (i = 0 ; i < ARRAY_COUNT(primary->signed_userids) ; i++) {
if (i != primary->primary_userid) {
cc += fmt_userid(&s[cc], size - cc, primary, i);
+ if (strcasecmp(modifiers, "trust") == 0) {
+ userid = &ARRAY_ELEMENT(primary->signed_userids, i);
+ for (j = 0 ; j < ARRAY_COUNT(userid->sigs) ; j++) {
+ cc += fmt_trust(&s[cc], size - cc, userid, j);
+ }
+ }
}
}
- for (i = 0 ; dosubkeys && i < ARRAY_COUNT(primary->signed_subkeys) ; i++) {
- cc += fmt_pubkey(&s[cc], size - cc, &ARRAY_ELEMENT(primary->signed_subkeys, i).subkey, "encryption");
+ if (strcasecmp(modifiers, "subkeys") == 0) {
+ for (i = 0 ; i < ARRAY_COUNT(primary->signed_subkeys) ; i++) {
+ cc += fmt_pubkey(&s[cc], size - cc, &ARRAY_ELEMENT(primary->signed_subkeys, i).subkey, "encryption");
+ }
}
cc += snprintf(&s[cc], size - cc, "\n");
return cc;
@@ -2028,7 +2113,7 @@ recog_primary_key(pgpv_t *pgp, pgpv_primarykey_t *primary)
printf("recog_primary_key: not signed public subkey\n");
return 0;
}
- pgpv_calc_keyid(&subkey.subkey);
+ calc_keyid(&subkey.subkey, "sha1");
ARRAY_APPEND(primary->signed_subkeys, subkey);
}
} while (pgp->pkt < ARRAY_COUNT(pgp->pkts) && pkt_is(pgp, USERID_PKT));
@@ -2061,7 +2146,7 @@ read_all_packets(pgpv_t *pgp, pgpv_mem_t *mem, const char *op)
}
if (strcmp(op, "pubring") == 0) {
for (pgp->pkt = 0; pgp->pkt < ARRAY_COUNT(pgp->pkts) && recog_primary_key(pgp, &primary) ; ) {
- pgpv_calc_keyid(&primary.primary);
+ calc_keyid(&primary.primary, "sha1");
ARRAY_APPEND(pgp->primaries, primary);
}
if (pgp->pkt < ARRAY_COUNT(pgp->pkts)) {
@@ -2088,6 +2173,194 @@ read_binary_file(pgpv_t *pgp, const char *op, const char *fmt, ...)
return read_all_packets(pgp, &ARRAY_LAST(pgp->areas), op);
}
+/* get a bignum from the buffer gap */
+static int
+getbignum(pgpv_bignum_t *bignum, bufgap_t *bg, char *buf, const char *header)
+{
+ uint32_t len;
+
+ (void) bufgap_getbin(bg, &len, sizeof(len));
+ len = ntohl(len);
+ (void) bufgap_seek(bg, sizeof(len), BGFromHere, BGByte);
+ (void) bufgap_getbin(bg, buf, len);
+ bignum->bn = BN_bin2bn((const uint8_t *)buf, (int)len, NULL);
+ bignum->bits = BN_num_bits(bignum->bn);
+ (void) bufgap_seek(bg, len, BGFromHere, BGByte);
+ return 1;
+}
+
+/* structure for searching for constant strings */
+typedef struct str_t {
+ const char *s; /* string */
+ size_t len; /* its length */
+ int type; /* return type */
+} str_t;
+
+static str_t pkatypes[] = {
+ { "ssh-rsa", 7, PUBKEY_RSA_SIGN },
+ { "ssh-dss", 7, PUBKEY_DSA },
+ { "ssh-dsa", 7, PUBKEY_DSA },
+ { NULL, 0, 0 }
+};
+
+/* look for a string in the given array */
+static int
+findstr(str_t *array, const char *name)
+{
+ str_t *sp;
+
+ for (sp = array ; sp->s ; sp++) {
+ if (strncmp(name, sp->s, sp->len) == 0) {
+ return sp->type;
+ }
+ }
+ return -1;
+}
+
+/* read public key from the ssh pubkey file */
+static int
+read_ssh_file(pgpv_t *pgp, pgpv_primarykey_t *primary, const char *fmt, ...)
+{
+ pgpv_signed_userid_t userid;
+ pgpv_pubkey_t *pubkey;
+ struct stat st;
+ bufgap_t bg;
+ uint32_t len;
+ int64_t off;
+ va_list args;
+ char hostname[256];
+ char owner[256];
+ char *space;
+ char *buf;
+ char *bin;
+ char f[1024];
+ int ok;
+ int cc;
+
+ memset(primary, 0x0, sizeof(*primary));
+ (void) memset(&bg, 0x0, sizeof(bg));
+ va_start(args, fmt);
+ vsnprintf(f, sizeof(f), fmt, args);
+ va_end(args);
+ if (!bufgap_open(&bg, f)) {
+ (void) fprintf(stderr, "pgp_ssh2pubkey: can't open '%s'\n", f);
+ return 0;
+ }
+ (void)stat(f, &st);
+ if ((buf = calloc(1, (size_t)st.st_size)) == NULL) {
+ (void) fprintf(stderr, "can't calloc %zu bytes for '%s'\n", (size_t)st.st_size, f);
+ bufgap_close(&bg);
+ return 0;
+ }
+ if ((bin = calloc(1, (size_t)st.st_size)) == NULL) {
+ (void) fprintf(stderr, "can't calloc %zu bytes for '%s'\n", (size_t)st.st_size, f);
+ (void) free(buf);
+ bufgap_close(&bg);
+ return 0;
+ }
+
+ /* move past ascii type of key */
+ while (bufgap_peek(&bg, 0) != ' ') {
+ if (!bufgap_seek(&bg, 1, BGFromHere, BGByte)) {
+ (void) fprintf(stderr, "bad key file '%s'\n", f);
+ (void) free(buf);
+ bufgap_close(&bg);
+ return 0;
+ }
+ }
+ if (!bufgap_seek(&bg, 1, BGFromHere, BGByte)) {
+ (void) fprintf(stderr, "bad key file '%s'\n", f);
+ (void) free(buf);
+ bufgap_close(&bg);
+ return 0;
+ }
+ off = bufgap_tell(&bg, BGFromBOF, BGByte);
+
+ if (bufgap_size(&bg, BGByte) - off < 10) {
+ (void) fprintf(stderr, "bad key file '%s'\n", f);
+ (void) free(buf);
+ bufgap_close(&bg);
+ return 0;
+ }
+
+ /* convert from base64 to binary */
+ cc = bufgap_getbin(&bg, buf, (size_t)bg.bcc);
+ if ((space = strchr(buf, ' ')) != NULL) {
+ cc = (int)(space - buf);
+ }
+ cc = frombase64(bin, buf, (size_t)cc, 0);
+ bufgap_delete(&bg, (uint64_t)bufgap_tell(&bg, BGFromEOF, BGByte));
+ bufgap_insert(&bg, bin, cc);
+ bufgap_seek(&bg, off, BGFromBOF, BGByte);
+
+ /* get the type of key */
+ (void) bufgap_getbin(&bg, &len, sizeof(len));
+ len = ntohl(len);
+ if (len >= st.st_size) {
+ (void) fprintf(stderr, "bad public key file '%s'\n", f);
+ return 0;
+ }
+ (void) bufgap_seek(&bg, sizeof(len), BGFromHere, BGByte);
+ (void) bufgap_getbin(&bg, buf, len);
+ (void) bufgap_seek(&bg, len, BGFromHere, BGByte);
+
+ pubkey = &primary->primary;
+ pubkey->hashalg = digest_get_alg("sha256"); /* gets fixed up later */
+ pubkey->version = 4;
+ pubkey->birth = 0; /* gets fixed up later */
+ /* get key type */
+ ok = 1;
+ switch (pubkey->keyalg = findstr(pkatypes, buf)) {
+ case PUBKEY_RSA_ENCRYPT_OR_SIGN:
+ case PUBKEY_RSA_SIGN:
+ getbignum(&pubkey->bn[RSA_E], &bg, buf, "RSA E");
+ getbignum(&pubkey->bn[RSA_N], &bg, buf, "RSA N");
+ break;
+ case PUBKEY_DSA:
+ getbignum(&pubkey->bn[DSA_P], &bg, buf, "DSA P");
+ getbignum(&pubkey->bn[DSA_Q], &bg, buf, "DSA Q");
+ getbignum(&pubkey->bn[DSA_G], &bg, buf, "DSA G");
+ getbignum(&pubkey->bn[DSA_Y], &bg, buf, "DSA Y");
+ break;
+ default:
+ (void) fprintf(stderr, "Unrecognised pubkey type %d for '%s'\n",
+ pubkey->keyalg, f);
+ ok = 0;
+ break;
+ }
+
+ /* check for stragglers */
+ if (ok && bufgap_tell(&bg, BGFromEOF, BGByte) > 0) {
+ printf("%"PRIi64" bytes left\n", bufgap_tell(&bg, BGFromEOF, BGByte));
+ printf("[%s]\n", bufgap_getstr(&bg));
+ ok = 0;
+ }
+ if (ok) {
+ memset(&userid, 0x0, sizeof(userid));
+ (void) gethostname(hostname, sizeof(hostname));
+ if (strlen(space + 1) - 1 == 0) {
+ (void) snprintf(owner, sizeof(owner), "<root@%s>",
+ hostname);
+ } else {
+ (void) snprintf(owner, sizeof(owner), "<%.*s>",
+ (int)strlen(space + 1) - 1,
+ space + 1);
+ }
+ calc_keyid(pubkey, "sha1");
+ userid.userid.size = asprintf((char **)(void *)&userid.userid.data,
+ "%s (%s) %s",
+ hostname,
+ f,
+ owner);
+ ARRAY_APPEND(primary->signed_userids, userid);
+ primary->fmtsize = estimate_primarykey_size(primary) + 1024;
+ }
+ (void) free(bin);
+ (void) free(buf);
+ bufgap_close(&bg);
+ return ok;
+}
+
/* parse memory according to "op" */
static int
read_binary_memory(pgpv_t *pgp, const char *op, const void *memory, size_t size)
@@ -2234,7 +2507,7 @@ pgpv_close(pgpv_t *pgp)
/* return the formatted entry for the primary key desired */
size_t
-pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **ret)
+pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **ret, const char *modifiers)
{
size_t cc;
@@ -2243,15 +2516,36 @@ pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **ret)
}
*ret = NULL;
cc = ARRAY_ELEMENT(pgp->primaries, ent).fmtsize;
+ if (modifiers == NULL || (strcasecmp(modifiers, "trust") != 0 && strcasecmp(modifiers, "subkeys") != 0)) {
+ modifiers = "no-subkeys";
+ }
+ if (strcasecmp(modifiers, "trust") == 0) {
+ cc *= 2048;
+ }
if ((*ret = calloc(1, cc)) == NULL) {
return 0;
}
- return fmt_primary(*ret, cc, &ARRAY_ELEMENT(pgp->primaries, ent), NO_SUBKEYS);
+ return fmt_primary(*ret, cc, &ARRAY_ELEMENT(pgp->primaries, ent), modifiers);
+}
+
+/* fixup key id, with birth, keyalg and hashalg value from signature */
+static int
+fixup_ssh_keyid(pgpv_t *pgp, pgpv_signature_t *signature, const char *hashtype)
+{
+ pgpv_pubkey_t *pubkey;
+ unsigned i;
+
+ for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) {
+ pubkey = &ARRAY_ELEMENT(pgp->primaries, i).primary;
+ pubkey->keyalg = signature->keyalg;
+ calc_keyid(pubkey, hashtype);
+ }
+ return 1;
}
/* find key id */
-int
-pgpv_find_keyid(pgpv_t *pgp, const char *strkeyid, uint8_t *keyid)
+static int
+find_keyid(pgpv_t *pgp, const char *strkeyid, uint8_t *keyid)
{
unsigned i;
uint8_t binkeyid[PGPV_KEYID_LEN];
@@ -2277,6 +2571,21 @@ pgpv_find_keyid(pgpv_t *pgp, const char *strkeyid, uint8_t *keyid)
return -1;
}
+/* match the signature with the id indexed by 'primary' */
+static int
+match_sig_id(pgpv_cursor_t *cursor, pgpv_signature_t *signature, pgpv_litdata_t *litdata, unsigned primary)
+{
+ pgpv_pubkey_t *pubkey;
+ uint8_t *data;
+ size_t insize;
+
+ pubkey = &ARRAY_ELEMENT(cursor->pgp->primaries, primary).primary;
+ cursor->sigtime = signature->birth;
+ /* calc hash on data packet */
+ data = get_literal_data(cursor, litdata, &insize);
+ return match_sig(cursor, signature, pubkey, data, insize);
+}
+
/* verify the signed packets we have */
size_t
pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
@@ -2284,12 +2593,9 @@ pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
pgpv_signature_t *signature;
pgpv_onepass_t *onepass;
pgpv_litdata_t *litdata;
- pgpv_pubkey_t *pubkey;
- unsigned primary;
- uint8_t *data;
size_t pkt;
- size_t insize;
char strkeyid[PGPV_STR_KEYID_LEN];
+ int found;
int j;
if (cursor == NULL || pgp == NULL || p == NULL) {
@@ -2336,21 +2642,21 @@ pgpv_verify(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
signature->keyalg, onepass->keyalg);
return 0;
}
- if ((j = pgpv_find_keyid(cursor->pgp, NULL, onepass->keyid)) < 0) {
+ if (cursor->pgp->ssh) {
+ fixup_ssh_keyid(cursor->pgp, signature, "sha1");
+ }
+ if (ARRAY_COUNT(cursor->pgp->primaries) == 1) {
+ j = 0;
+ } else if ((j = find_keyid(cursor->pgp, NULL, onepass->keyid)) < 0) {
fmt_binary(strkeyid, sizeof(strkeyid), onepass->keyid, (unsigned)sizeof(onepass->keyid));
snprintf(cursor->why, sizeof(cursor->why), "Signature key id %s not found ", strkeyid);
return 0;
}
- primary = (unsigned)j;
- pubkey = &ARRAY_ELEMENT(cursor->pgp->primaries, primary).primary;
- cursor->sigtime = signature->birth;
- /* calc hash on data packet */
- data = get_literal_data(cursor, litdata, &insize);
- if (!match_sig(cursor, signature, pubkey, data, insize)) {
+ if (!match_sig_id(cursor, signature, litdata, (unsigned)j)) {
return 0;
}
ARRAY_APPEND(cursor->datacookies, pkt);
- ARRAY_APPEND(cursor->found, primary);
+ ARRAY_APPEND(cursor->found, j);
return pkt + 1;
}
@@ -2369,6 +2675,27 @@ pgpv_read_pubring(pgpv_t *pgp, const void *keyring, ssize_t size)
return read_binary_file(pgp, "pubring", "%s/%s", nonnull_getenv("HOME"), ".gnupg/pubring.gpg");
}
+/* set up the pubkey keyring from ssh pub key */
+int
+pgpv_read_ssh_pubkeys(pgpv_t *pgp, const void *keyring, ssize_t size)
+{
+ pgpv_primarykey_t primary;
+
+ if (pgp == NULL) {
+ return 0;
+ }
+ if (keyring) {
+ if (!read_ssh_file(pgp, &primary, "%s", keyring)) {
+ return 0;
+ }
+ } else if (!read_ssh_file(pgp, &primary, "pubring", "%s/%s", nonnull_getenv("HOME"), ".ssh/id_rsa.pub")) {
+ return 0;
+ }
+ ARRAY_APPEND(pgp->primaries, primary);
+ pgp->ssh = 1;
+ return 1;
+}
+
/* get verified data as a string, return its size */
size_t
pgpv_get_verified(pgpv_cursor_t *cursor, size_t cookie, char **ret)
diff --git a/security/netpgpverify/files/main.c b/security/netpgpverify/files/main.c
index 793f5355cdb..40cc1755c49 100644
--- a/security/netpgpverify/files/main.c
+++ b/security/netpgpverify/files/main.c
@@ -49,11 +49,11 @@ ptime(int64_t secs)
/* print entry n */
static void
-pentry(pgpv_t *pgp, int n)
+pentry(pgpv_t *pgp, int n, const char *modifiers)
{
char *s;
- pgpv_get_entry(pgp, (unsigned)n, &s);
+ pgpv_get_entry(pgp, (unsigned)n, &s, modifiers);
printf("%s", s);
free(s);
}
@@ -91,6 +91,7 @@ static int
verify_data(pgpv_t *pgp, const char *cmd, const char *inname, char *in, ssize_t cc)
{
pgpv_cursor_t cursor;
+ const char *modifiers;
size_t size;
size_t cookie;
char *data;
@@ -103,16 +104,17 @@ verify_data(pgpv_t *pgp, const char *cmd, const char *inname, char *in, ssize_t
}
return 1;
}
- } else if (strcasecmp(cmd, "verify") == 0) {
+ } else if (strcasecmp(cmd, "verify") == 0 || strcasecmp(cmd, "trust") == 0) {
+ modifiers = (strcasecmp(cmd, "trust") == 0) ? "trust" : NULL;
if (pgpv_verify(&cursor, pgp, in, cc)) {
printf("Good signature for %s made ", inname);
ptime(cursor.sigtime);
- pentry(pgp, ARRAY_ELEMENT(cursor.found, 0));
+ pentry(pgp, ARRAY_ELEMENT(cursor.found, 0), modifiers);
return 1;
}
- fprintf(stderr, "Signature did not match contents -- %s", cursor.why);
+ fprintf(stderr, "Signature did not match contents -- %s\n", cursor.why);
} else {
- fprintf(stderr, "unrecognised command \"%s\"", cmd);
+ fprintf(stderr, "unrecognised command \"%s\"\n", cmd);
}
return 0;
}
@@ -120,21 +122,29 @@ verify_data(pgpv_t *pgp, const char *cmd, const char *inname, char *in, ssize_t
int
main(int argc, char **argv)
{
+ const char *modifiers;
const char *keyring;
const char *cmd;
ssize_t cc;
size_t size;
pgpv_t pgp;
char *in;
+ int ssh;
int ok;
int i;
memset(&pgp, 0x0, sizeof(pgp));
keyring = NULL;
+ ssh = 0;
ok = 1;
cmd = "verify";
- while ((i = getopt(argc, argv, "c:k:v")) != -1) {
+ modifiers = NULL;
+ while ((i = getopt(argc, argv, "S:c:k:v")) != -1) {
switch(i) {
+ case 'S':
+ ssh = 1;
+ keyring = optarg;
+ break;
case 'c':
cmd = optarg;
break;
@@ -148,8 +158,14 @@ main(int argc, char **argv)
break;
}
}
- if (!pgpv_read_pubring(&pgp, keyring, -1)) {
- errx(EXIT_FAILURE, "can't read keyring");
+ if (ssh) {
+ if (!pgpv_read_ssh_pubkeys(&pgp, keyring, -1)) {
+ fprintf(stderr, "can't read ssh keyring\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if (!pgpv_read_pubring(&pgp, keyring, -1)) {
+ fprintf(stderr, "can't read keyring\n");
+ exit(EXIT_FAILURE);
}
if (optind == argc) {
in = getstdin(&cc, &size);
diff --git a/security/netpgpverify/files/netpgpverify.1 b/security/netpgpverify/files/netpgpverify.1
index cb33c4412e8..a23c9104687 100644
--- a/security/netpgpverify/files/netpgpverify.1
+++ b/security/netpgpverify/files/netpgpverify.1
@@ -1,6 +1,6 @@
-.\" $NetBSD: netpgpverify.1,v 1.2 2013/07/20 21:50:54 wiz Exp $
+.\" $NetBSD: netpgpverify.1,v 1.3 2014/02/04 02:11:18 agc Exp $
.\"
-.\" Copyright (c) 2013 Alistair Crooks <agc@NetBSD.org>
+.\" Copyright (c) 2013,2014 Alistair Crooks <agc@NetBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -23,7 +23,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd March 15, 2013
+.Dd February 2, 2014
.Dt NETPGPVERIFY 1
.Os
.Sh NAME
@@ -32,6 +32,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl v
+.Op Fl S Ar ssh-pub-key-file
.Op Fl c Ar command
.Op Fl k Ar keyring
.Ar file ...
@@ -87,6 +88,24 @@ will also verify the signature on the data, and, if
successfully verified, will display the verified
data on
.Dv stdout .
+The
+.Fl S
+argument allows an ssh public key file to be used as the source of
+truth for the key.
+This ssh-key-based signature can be created using the
+.Xr netpgp 1
+utility.
+.Pp
+If a detached signature
+.Dq .sig
+is given on the command line, the signing information will be retrieved
+from that file, and the original data is expected to be found in a file in the same
+directory with the same name with the
+.Dq .sig
+suffix removed.
+.Pp
+Both text mode signatures, and binary signatures, can be verified by
+.Nm
.Sh SIGNING AND VERIFICATION
Verification of a file's signature is best viewed using the following example:
.Bd -literal
@@ -106,7 +125,6 @@ or 2 if any other error occurs.
.Sh SEE ALSO
.Xr netpgp 1 ,
.\" .Xr libbz2 3 ,
-.Xr libnetpgp 3 ,
.Xr zlib 3
.Sh STANDARDS
The
@@ -118,4 +136,4 @@ The
command first appeared in
.Nx 7.0 .
.Sh AUTHORS
-.An Alistair Crooks Aq Mt agc@NetBSD.org .
+.An Alistair Crooks Aq agc@NetBSD.org .
diff --git a/security/netpgpverify/files/pubring.gpg b/security/netpgpverify/files/pubring.gpg
index 796a40a1398..113e332c1e5 100644
--- a/security/netpgpverify/files/pubring.gpg
+++ b/security/netpgpverify/files/pubring.gpg
Binary files differ
diff --git a/security/netpgpverify/files/sshtest-20140202 b/security/netpgpverify/files/sshtest-20140202
new file mode 100644
index 00000000000..68ac811d2e8
--- /dev/null
+++ b/security/netpgpverify/files/sshtest-20140202
@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/security/netpgpverify/files/sshtest-20140202.pub b/security/netpgpverify/files/sshtest-20140202.pub
new file mode 100644
index 00000000000..865d17203ad
--- /dev/null
+++ b/security/netpgpverify/files/sshtest-20140202.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9GQFh9ZovYFZ+alATAZX9un7IlwstYzvFRjsuu0vhOrdh5WyU9fIyWQL9ZTIv8JTIDx9DfPnqb5LuFmpe2l5ZtgZDo7un8EV4xx5knph2GZJMMokLs64XhWc2pgbkterCV6cUR7gtO3v281JkSQFyyG5Gz3EWnq+tCub4ulMcqhcqX9Q+x/Ury4Bahz+Y9MyrIh0nHppRdDR/DAWj+3wTjtTAthCTcEViVj1HRx61UBcIKi1OZzleeYolHpgpQDrQWBTi+T7HkiBKm42gy+6EM9ptoClAsfDXf0R+a6XOzMGlXi4SWdcHDkJ1D9E/2be91p+NueUrcPGDFtTd5G9QUhuSN27mqLptuXGpJ5/Uxv8HDY6p7AU0ybdlDXtXceoCZgYEHAHZ6H9ypGUJFxh68DZvIzrV1MzRe3m8HNvE1ZbpZ4mYP6hg/6CVhFGYri4l54o4VJaoOFtKPoR9gf5QW7SJXjITEoZ5UoFPCF+l5y66xXvdrBheLC1Ko/XZSNGhOlh9dseW+l4yHIHDSgpaN5neSjgouFXOOgtPxulJshJojwaJUFYJywxmaZn8+QYMD47w16S1nlP3OW1aWxe58dVDnHYGJ8rAasiCHUlLfxR2DAhBUVP/r2nlxyv9o+5MgBDHvtfNHNN0R5aW7LZyjBkXl+70dDk7338yLrVzuQ== agc@netbsd-001.cupertino.alistaircrooks.com
diff --git a/security/netpgpverify/files/verify.h b/security/netpgpverify/files/verify.h
index 11f0345ebc3..2cdc732261d 100644
--- a/security/netpgpverify/files/verify.h
+++ b/security/netpgpverify/files/verify.h
@@ -23,9 +23,9 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef NETPGP_VERIFY_H_
-#define NETPGP_VERIFY_H_ 20131219
+#define NETPGP_VERIFY_H_ 20140202
-#define NETPGPVERIFY_VERSION "netpgpverify portable 20131219"
+#define NETPGPVERIFY_VERSION "netpgpverify portable 20140202"
#include <sys/types.h>
@@ -49,7 +49,7 @@ typedef struct pgpv_bignum_t {
} pgpv_bignum_t;
/* right now, our max binary digest length is 20 bytes */
-#define PGPV_MAX_HASH_LEN 20
+#define PGPV_MAX_HASH_LEN 64
/* fingerprint */
typedef struct pgpv_fingerprint_t {
@@ -251,6 +251,7 @@ typedef struct pgpv_t {
PGPV_ARRAY(size_t, datastarts); /* starts of data packets */
size_t pkt; /* when parsing, current pkt number */
const char *op; /* the operation we're doing */
+ unsigned ssh; /* using ssh keys */
} pgpv_t;
#define PGPV_REASON_LEN 128
@@ -281,11 +282,12 @@ typedef struct pgpv_cursor_t {
__BEGIN_DECLS
int pgpv_read_pubring(pgpv_t */*pgp*/, const void */*keyringfile/mem*/, ssize_t /*size*/);
+int pgpv_read_ssh_pubkeys(pgpv_t */*pgp*/, const void */*keyring*/, ssize_t /*size*/);
size_t pgpv_verify(pgpv_cursor_t */*cursor*/, pgpv_t */*pgp*/, const void */*mem/file*/, ssize_t /*size*/);
size_t pgpv_get_verified(pgpv_cursor_t */*cursor*/, size_t /*cookie*/, char **/*ret*/);
-size_t pgpv_get_entry(pgpv_t */*pgp*/, unsigned /*ent*/, char **/*ret*/);
+size_t pgpv_get_entry(pgpv_t */*pgp*/, unsigned /*ent*/, char **/*ret*/, const char */*modifiers*/);
int pgpv_close(pgpv_t */*pgp*/);