summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoragc <agc>2013-02-23 21:04:26 +0000
committeragc <agc>2013-02-23 21:04:26 +0000
commita41731b02dae971a8ebfb976b85651092dc03fbe (patch)
tree994f4dd8a27ce6e42df2deef99ac67744b16f050
parent9fa74edf2c6216192fbad505a61b6991755595c9 (diff)
downloadpkgsrc-a41731b02dae971a8ebfb976b85651092dc03fbe.tar.gz
Initial import of libnetpgpverify-20120928, a library to verify PGP
signatures. This library has no pre-requisites other than -lz and -lbz2. This is libnetpgpverify, a standalone library to verify PGP signatures. It uses its own internal MPI/BIGNUM functions, which are a vastly cut-down version of libtommath. For this reason, utilities and other libraries can embed PGP signature verification, using a BSD-licensed library.
-rw-r--r--security/libnetpgpverify/DESCR7
-rw-r--r--security/libnetpgpverify/Makefile31
-rw-r--r--security/libnetpgpverify/PLIST4
-rw-r--r--security/libnetpgpverify/buildlink3.mk13
-rw-r--r--security/libnetpgpverify/distinfo1
-rw-r--r--security/libnetpgpverify/files/Makefile40
-rw-r--r--security/libnetpgpverify/files/Makefile.bsd24
-rw-r--r--security/libnetpgpverify/files/shlib_version2
-rw-r--r--security/libnetpgpverify/files/src/libbn/Makefile13
-rw-r--r--security/libnetpgpverify/files/src/libbn/bignum.c5637
-rw-r--r--security/libnetpgpverify/files/src/libbn/bn.h146
-rw-r--r--security/libnetpgpverify/files/src/libbn/libnetpgpbn.3304
-rw-r--r--security/libnetpgpverify/files/src/libbn/misc.c82
-rw-r--r--security/libnetpgpverify/files/src/libbn/misc.h53
-rw-r--r--security/libnetpgpverify/files/src/libbn/rand.c60
-rw-r--r--security/libnetpgpverify/files/src/libbn/rand.h44
-rw-r--r--security/libnetpgpverify/files/src/libbn/stubs.c217
-rw-r--r--security/libnetpgpverify/files/src/libbn/stubs.h94
-rw-r--r--security/libnetpgpverify/files/src/libdigest/Makefile16
-rw-r--r--security/libnetpgpverify/files/src/libdigest/digest.c383
-rw-r--r--security/libnetpgpverify/files/src/libdigest/digest.h109
-rw-r--r--security/libnetpgpverify/files/src/libdigest/tiger.3219
-rw-r--r--security/libnetpgpverify/files/src/libdigest/tiger.c906
-rw-r--r--security/libnetpgpverify/files/src/libdigest/tiger.h65
-rw-r--r--security/libnetpgpverify/files/src/librsa/Makefile10
-rw-r--r--security/libnetpgpverify/files/src/librsa/libnetpgprsa.3113
-rw-r--r--security/libnetpgpverify/files/src/librsa/rsa.c696
-rw-r--r--security/libnetpgpverify/files/src/librsa/rsa.h155
-rw-r--r--security/libnetpgpverify/files/src/librsa/rsastubs.c83
-rw-r--r--security/libnetpgpverify/files/src/librsa/rsastubs.h25
-rw-r--r--security/libnetpgpverify/files/src/libverify/Makefile71
-rw-r--r--security/libnetpgpverify/files/src/libverify/array.h82
-rw-r--r--security/libnetpgpverify/files/src/libverify/b64.c355
-rw-r--r--security/libnetpgpverify/files/src/libverify/b64.h32
-rw-r--r--security/libnetpgpverify/files/src/libverify/dump.c88
-rw-r--r--security/libnetpgpverify/files/src/libverify/libnetpgpverify.3139
-rw-r--r--security/libnetpgpverify/files/src/libverify/libverify.c2366
-rw-r--r--security/libnetpgpverify/files/src/libverify/pgpsum.c192
-rw-r--r--security/libnetpgpverify/files/src/libverify/pgpsum.h35
-rw-r--r--security/libnetpgpverify/files/src/libverify/verify.h292
40 files changed, 13204 insertions, 0 deletions
diff --git a/security/libnetpgpverify/DESCR b/security/libnetpgpverify/DESCR
new file mode 100644
index 00000000000..23f05090d1f
--- /dev/null
+++ b/security/libnetpgpverify/DESCR
@@ -0,0 +1,7 @@
+This is libnetpgpverify, a standalone library to verify PGP
+signatures.
+
+It uses its own internal MPI/BIGNUM functions, which are a vastly
+cut-down version of libtommath. For this reason, utilities and other
+libraries can embed PGP signature verification, using a BSD-licensed
+library.
diff --git a/security/libnetpgpverify/Makefile b/security/libnetpgpverify/Makefile
new file mode 100644
index 00000000000..0e379639329
--- /dev/null
+++ b/security/libnetpgpverify/Makefile
@@ -0,0 +1,31 @@
+# $NetBSD: Makefile,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+
+DISTNAME= libnetpgpverify-${VERSION}
+CATEGORIES= security
+MASTER_SITES= # empty
+DISTFILES= # empty
+
+MAINTAINER= agc@NetBSD.org
+HOMEPAGE= http://www.NetBSD.org/
+COMMENT= PGP signature verification library
+LICENSE= modified-bsd
+
+USE_LIBTOOL= yes
+AUTO_MKDIRS= yes
+
+.include "../../mk/bsd.prefs.mk"
+
+VERSION!= ${AWK} '/\#define.*NETPGP_VERIFY_H_/ {print $$3}' ${FILESDIR}/src/libverify/verify.h
+
+do-extract:
+ @${CP} -R ${FILESDIR} ${WRKSRC}
+
+do-install:
+ libtool --mode=install ${INSTALL_LIB} ${WRKSRC}/libnetpgpverify.la ${DESTDIR}${PREFIX}/lib
+ ${INSTALL_DATA} ${WRKSRC}/src/libverify/verify.h ${DESTDIR}${PREFIX}/include/netpgp
+ ${INSTALL_DATA} ${WRKSRC}/src/libverify/libnetpgpverify.3 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man3
+
+.include "../../archivers/bzip2/buildlink3.mk"
+.include "../../devel/zlib/buildlink3.mk"
+
+.include "../../mk/bsd.pkg.mk"
diff --git a/security/libnetpgpverify/PLIST b/security/libnetpgpverify/PLIST
new file mode 100644
index 00000000000..9ad7d7d3aff
--- /dev/null
+++ b/security/libnetpgpverify/PLIST
@@ -0,0 +1,4 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+include/netpgp/verify.h
+lib/libnetpgpverify.la
+man/man3/libnetpgpverify.3
diff --git a/security/libnetpgpverify/buildlink3.mk b/security/libnetpgpverify/buildlink3.mk
new file mode 100644
index 00000000000..f380c80ac1b
--- /dev/null
+++ b/security/libnetpgpverify/buildlink3.mk
@@ -0,0 +1,13 @@
+# $NetBSD: buildlink3.mk,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+
+BUILDLINK_TREE+= libnetpgpverify
+
+.if !defined(LIBNETPGPVERIFY_BUILDLINK3_MK)
+LIBNETPGPVERIFY_BUILDLINK3_MK:=
+
+BUILDLINK_API_DEPENDS.libnetpgpverify+= libnetpgpverify>=20120928
+BUILDLINK_PKGSRCDIR.libnetpgpverify?= ../../security/libnetpgpverify
+
+.endif # LIBNETPGPVERIFY_BUILDLINK3_MK
+
+BUILDLINK_TREE+= -libnetpgpverify
diff --git a/security/libnetpgpverify/distinfo b/security/libnetpgpverify/distinfo
new file mode 100644
index 00000000000..8fc306ad2e7
--- /dev/null
+++ b/security/libnetpgpverify/distinfo
@@ -0,0 +1 @@
+$NetBSD: distinfo,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
diff --git a/security/libnetpgpverify/files/Makefile b/security/libnetpgpverify/files/Makefile
new file mode 100644
index 00000000000..8f60ac2fa5e
--- /dev/null
+++ b/security/libnetpgpverify/files/Makefile
@@ -0,0 +1,40 @@
+# $NetBSD: Makefile,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+
+# Makefile for libnetpgpverify
+SRCS=libverify.c b64.c pgpsum.c
+SRCS+=digest.c tiger.c
+SRCS+=bignum.c misc.c
+
+CFLAGS+=-I${EXTDIST}/src/libbn
+CFLAGS+=-I${EXTDIST}/src/libdigest
+CFLAGS+=-I${EXTDIST}/src/librsa
+
+OBJS=libverify.o b64.o pgpsum.o
+OBJS+=digest.o tiger.o
+OBJS+=bignum.o misc.o
+
+EXTDIST=${.CURDIR}
+.PATH: ${EXTDIST}/src/libverify ${EXTDIST}/src/libdigest ${EXTDIST}/src/libbn ${EXTDIST}/src/librsa
+
+INCS=verify.h
+INCSDIR=${PREFIX}/include/netpgp
+
+libverify.o: src/libverify/libverify.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libverify/libverify.c
+b64.o: src/libverify/b64.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libverify/b64.c
+pgpsum.o: src/libverify/pgpsum.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libverify/pgpsum.c
+digest.o: src/libdigest/digest.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libdigest/digest.c
+tiger.o: src/libdigest/tiger.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libdigest/tiger.c
+bignum.o: src/libbn/bignum.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libbn/bignum.c
+misc.o: src/libbn/misc.c
+ libtool --mode=compile --tag=CC ${CC} ${CFLAGS} -c src/libbn/misc.c
+
+libnetpgpverify.a: ${OBJS}
+ libtool --mode=link --tag=CC cc -o ${.TARGET:.a=.la} ${OBJS:.o=.lo} -rpath ${PREFIX}/lib -version-info 0:0
+
+all: libnetpgpverify.a
diff --git a/security/libnetpgpverify/files/Makefile.bsd b/security/libnetpgpverify/files/Makefile.bsd
new file mode 100644
index 00000000000..fa5bd95b802
--- /dev/null
+++ b/security/libnetpgpverify/files/Makefile.bsd
@@ -0,0 +1,24 @@
+# $NetBSD: Makefile.bsd,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+
+LIB=netpgpverify
+SRCS=libverify.c b64.c pgpsum.c
+SRCS+=digest.c tiger.c
+SRCS+=bignum.c misc.c
+CPPFLAGS+=-I${EXTDIST}/src/libbn
+CPPFLAGS+=-I${EXTDIST}/src/libdigest
+CPPFLAGS+=-I${EXTDIST}/src/librsa
+MAN=libnetpgpverify.3
+WARNS=5
+
+EXTDIST=${.CURDIR}
+.PATH: ${EXTDIST}/src/libverify ${EXTDIST}/src/libdigest ${EXTDIST}/src/libbn ${EXTDIST}/src/librsa
+
+INCS=verify.h
+INCSDIR=${PREFIX}/include/netpgp
+
+.include <bsd.lib.mk>
+
+.if ${HAVE_GCC:U} == "45" && ${MACHINE_CPU} == "ia64"
+COPTS.bignum.c+= ${${ACTIVE_CC} == "gcc" :? -O1 :}
+.endif
+
diff --git a/security/libnetpgpverify/files/shlib_version b/security/libnetpgpverify/files/shlib_version
new file mode 100644
index 00000000000..d9961ea9fef
--- /dev/null
+++ b/security/libnetpgpverify/files/shlib_version
@@ -0,0 +1,2 @@
+major=4
+minor=0
diff --git a/security/libnetpgpverify/files/src/libbn/Makefile b/security/libnetpgpverify/files/src/libbn/Makefile
new file mode 100644
index 00000000000..4c7c15c274c
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/Makefile
@@ -0,0 +1,13 @@
+LIB=netbn
+SRCS= bignum.c digest.c misc.c rand.c
+SRCS+= stubs.c
+MKMAN=no
+WARNS=4
+CPPFLAGS+=-I${EXTDIST}
+
+INCS=bn.h digest.h
+INCSDIR=/usr/include/netpgp
+
+EXTDIST= ${.CURDIR}/../cipher
+
+.include <bsd.lib.mk>
diff --git a/security/libnetpgpverify/files/src/libbn/bignum.c b/security/libnetpgpverify/files/src/libbn/bignum.c
new file mode 100644
index 00000000000..341468ec0da
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/bignum.c
@@ -0,0 +1,5637 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+
+#ifdef _KERNEL
+# include <sys/kmem.h>
+#else
+# include <arpa/inet.h>
+# include <ctype.h>
+# include <inttypes.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <unistd.h>
+#endif
+
+#include "misc.h"
+#include "bn.h"
+#include "digest.h"
+
+/**************************************************************************/
+
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
+ */
+
+#define MP_PREC 32
+#define DIGIT_BIT 28
+#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+
+#define MP_WARRAY /*LINTED*/(1U << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT) + 1)))
+
+#define MP_NO 0
+#define MP_YES 1
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+#ifndef __arraycount
+#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0]))
+#endif
+
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+
+typedef int mp_err;
+
+static int mp_mul(mp_int * a, mp_int * b, mp_int * c);
+static int mp_sqr(mp_int * a, mp_int * b);
+
+static int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* set to zero */
+static void
+mp_zero(mp_int *a)
+{
+ int n;
+ mp_digit *tmp;
+
+ a->sign = MP_ZPOS;
+ a->used = 0;
+
+ tmp = a->dp;
+ /* XXX - memset */
+ for (n = 0; n < a->alloc; n++) {
+ *tmp++ = 0;
+ }
+}
+
+/* grow as required */
+static int
+mp_grow(mp_int *a, int size)
+{
+ int i;
+ mp_digit *tmp;
+
+ /* if the alloc size is smaller alloc more ram */
+ if (a->alloc < size) {
+ /* ensure there are always at least MP_PREC digits extra on top */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* reallocate the array a->dp
+ *
+ * We store the return in a temporary variable
+ * in case the operation failed we don't want
+ * to overwrite the dp member of a.
+ */
+ tmp = realloc(a->dp, sizeof(*tmp) * size);
+ if (tmp == NULL) {
+ /* reallocation failed but "a" is still valid [can be freed] */
+ return MP_MEM;
+ }
+
+ /* reallocation succeeded so set a->dp */
+ a->dp = tmp;
+
+ /* zero excess digits */
+ i = a->alloc;
+ a->alloc = size;
+ for (; i < a->alloc; i++) {
+ a->dp[i] = 0;
+ }
+ }
+ return MP_OKAY;
+}
+
+/* shift left a certain amount of digits */
+static int
+mp_lshd (mp_int * a, int b)
+{
+ int x, res;
+
+ /* if its less than zero return */
+ if (b <= 0) {
+ return MP_OKAY;
+ }
+
+ /* grow to fit the new digits */
+ if (a->alloc < a->used + b) {
+ if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ {
+ mp_digit *top, *bottom;
+
+ /* increment the used by the shift amount then copy upwards */
+ a->used += b;
+
+ /* top */
+ top = a->dp + a->used - 1;
+
+ /* base */
+ bottom = a->dp + a->used - 1 - b;
+
+ /* much like mp_rshd this is implemented using a sliding window
+ * except the window goes the otherway around. Copying from
+ * the bottom to the top. see bn_mp_rshd.c for more info.
+ */
+ for (x = a->used - 1; x >= b; x--) {
+ *top-- = *bottom--;
+ }
+
+ /* zero the lower digits */
+ top = a->dp;
+ for (x = 0; x < b; x++) {
+ *top++ = 0;
+ }
+ }
+ return MP_OKAY;
+}
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast. Also fixes the sign if there
+ * are no more leading digits
+ */
+static void
+mp_clamp (mp_int * a)
+{
+ /* decrease used while the most significant digit is
+ * zero.
+ */
+ while (a->used > 0 && a->dp[a->used - 1] == 0) {
+ --(a->used);
+ }
+
+ /* reset the sign flag if used == 0 */
+ if (a->used == 0) {
+ a->sign = MP_ZPOS;
+ }
+}
+
+/* copy, b = a */
+static int
+mp_copy(BIGNUM *a, BIGNUM *b)
+{
+ int res, n;
+
+ /* if dst == src do nothing */
+ if (a == b) {
+ return MP_OKAY;
+ }
+ if (a == NULL || b == NULL) {
+ return MP_VAL;
+ }
+
+ /* grow dest */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero b and copy the parameters over */
+ {
+ mp_digit *tmpa, *tmpb;
+
+ /* pointer aliases */
+
+ /* source */
+ tmpa = a->dp;
+
+ /* destination */
+ tmpb = b->dp;
+
+ /* copy all the digits */
+ for (n = 0; n < a->used; n++) {
+ *tmpb++ = *tmpa++;
+ }
+
+ /* clear high digits */
+ for (; n < b->used; n++) {
+ *tmpb++ = 0;
+ }
+ }
+
+ /* copy used count and sign */
+ b->used = a->used;
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+
+/* shift left by a certain bit count */
+static int
+mp_mul_2d(mp_int *a, int b, mp_int *c)
+{
+ mp_digit d;
+ int res;
+
+ /* copy */
+ if (a != c) {
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+ if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ d = (mp_digit) (b % DIGIT_BIT);
+ if (d != 0) {
+ mp_digit *tmpc, shift, mask, r, rr;
+ int x;
+
+ /* bitmask for carries */
+ mask = (((mp_digit)1) << d) - 1;
+
+ /* shift for msbs */
+ shift = DIGIT_BIT - d;
+
+ /* alias */
+ tmpc = c->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < c->used; x++) {
+ /* get the higher bits of the current word */
+ rr = (*tmpc >> shift) & mask;
+
+ /* shift the current word and OR in the carry */
+ *tmpc = ((*tmpc << d) | r) & MP_MASK;
+ ++tmpc;
+
+ /* set the carry to the carry bits of the current word */
+ r = rr;
+ }
+
+ /* set final carry */
+ if (r != 0) {
+ c->dp[(c->used)++] = r;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+static int
+mp_read_unsigned_bin(mp_int *a, const uint8_t *b, int c)
+{
+ int res;
+
+ /* make sure there are at least two digits */
+ if (a->alloc < 2) {
+ if ((res = mp_grow(a, 2)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* zero the int */
+ mp_zero (a);
+
+ /* read the bytes in */
+ while (c-- > 0) {
+ if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+ return res;
+ }
+
+ a->dp[0] |= *b++;
+ a->used += 1;
+ }
+ mp_clamp (a);
+ return MP_OKAY;
+}
+
+/* returns the number of bits in an int */
+static int
+mp_count_bits(const mp_int *a)
+{
+ int r;
+ mp_digit q;
+
+ /* shortcut */
+ if (a->used == 0) {
+ return 0;
+ }
+
+ /* get number of digits and add that */
+ r = (a->used - 1) * DIGIT_BIT;
+
+ /* take the last digit and count the bits in it */
+ q = a->dp[a->used - 1];
+ while (q > ((mp_digit) 0)) {
+ ++r;
+ q >>= ((mp_digit) 1);
+ }
+ return r;
+}
+
+/* compare maginitude of two ints (unsigned) */
+static int
+mp_cmp_mag (mp_int * a, mp_int * b)
+{
+ int n;
+ mp_digit *tmpa, *tmpb;
+
+ /* compare based on # of non-zero digits */
+ if (a->used > b->used) {
+ return MP_GT;
+ }
+
+ if (a->used < b->used) {
+ return MP_LT;
+ }
+
+ /* alias for a */
+ tmpa = a->dp + (a->used - 1);
+
+ /* alias for b */
+ tmpb = b->dp + (a->used - 1);
+
+ /* compare based on digits */
+ for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+ if (*tmpa > *tmpb) {
+ return MP_GT;
+ }
+
+ if (*tmpa < *tmpb) {
+ return MP_LT;
+ }
+ }
+ return MP_EQ;
+}
+
+/* compare two ints (signed)*/
+static int
+mp_cmp (mp_int * a, mp_int * b)
+{
+ /* compare based on sign */
+ if (a->sign != b->sign) {
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ } else {
+ return MP_GT;
+ }
+ }
+
+ /* compare digits */
+ if (a->sign == MP_NEG) {
+ /* if negative compare opposite direction */
+ return mp_cmp_mag(b, a);
+ } else {
+ return mp_cmp_mag(a, b);
+ }
+}
+
+/* get the size for an unsigned equivalent */
+static int
+mp_unsigned_bin_size (mp_int * a)
+{
+ int size = mp_count_bits (a);
+ return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+/* init a new mp_int */
+static int
+mp_init (mp_int * a)
+{
+ int i;
+
+ /* allocate memory required and clear it */
+ a->dp = netpgp_allocate(1, sizeof (*a->dp) * MP_PREC);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the digits to zero */
+ for (i = 0; i < MP_PREC; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* set the used to zero, allocated digits to the default precision
+ * and sign to positive */
+ a->used = 0;
+ a->alloc = MP_PREC;
+ a->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+
+/* clear one (frees) */
+static void
+mp_clear (mp_int * a)
+{
+ int i;
+
+ /* only do anything if a hasn't been freed previously */
+ if (a->dp != NULL) {
+ /* first zero the digits */
+ for (i = 0; i < a->used; i++) {
+ a->dp[i] = 0;
+ }
+
+ /* free ram */
+ netpgp_deallocate(a->dp, (size_t)a->alloc);
+
+ /* reset members to make debugging easier */
+ a->dp = NULL;
+ a->alloc = a->used = 0;
+ a->sign = MP_ZPOS;
+ }
+}
+
+static int
+mp_init_multi(mp_int *mp, ...)
+{
+ mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
+ int n = 0; /* Number of ok inits */
+ mp_int* cur_arg = mp;
+ va_list args;
+
+ va_start(args, mp); /* init args to next argument from caller */
+ while (cur_arg != NULL) {
+ if (mp_init(cur_arg) != MP_OKAY) {
+ /* Oops - error! Back-track and mp_clear what we already
+ succeeded in init-ing, then return error.
+ */
+ va_list clean_args;
+
+ /* end the current list */
+ va_end(args);
+
+ /* now start cleaning up */
+ cur_arg = mp;
+ va_start(clean_args, mp);
+ while (n--) {
+ mp_clear(cur_arg);
+ cur_arg = va_arg(clean_args, mp_int*);
+ }
+ va_end(clean_args);
+ res = MP_MEM;
+ break;
+ }
+ n++;
+ cur_arg = va_arg(args, mp_int*);
+ }
+ va_end(args);
+ return res; /* Assumed ok, if error flagged above. */
+}
+
+/* init an mp_init for a given size */
+static int
+mp_init_size (mp_int * a, int size)
+{
+ int x;
+
+ /* pad size so there are always extra digits */
+ size += (MP_PREC * 2) - (size % MP_PREC);
+
+ /* alloc mem */
+ a->dp = netpgp_allocate (1, sizeof (*a->dp) * size);
+ if (a->dp == NULL) {
+ return MP_MEM;
+ }
+
+ /* set the members */
+ a->used = 0;
+ a->alloc = size;
+ a->sign = MP_ZPOS;
+
+ /* zero the digits */
+ for (x = 0; x < size; x++) {
+ a->dp[x] = 0;
+ }
+
+ return MP_OKAY;
+}
+
+/* creates "a" then copies b into it */
+static int mp_init_copy (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_init (a)) != MP_OKAY) {
+ return res;
+ }
+ return mp_copy (b, a);
+}
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+static int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int *x;
+ int olduse, res, min, max;
+
+ /* find sizes, we let |a| <= |b| which means we have to sort
+ * them. "x" will point to the input with the most digits
+ */
+ if (a->used > b->used) {
+ min = b->used;
+ max = a->used;
+ x = a;
+ } else {
+ min = a->used;
+ max = b->used;
+ x = b;
+ }
+
+ /* init result */
+ if (c->alloc < max + 1) {
+ if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get old used digit count and set new one */
+ olduse = c->used;
+ c->used = max + 1;
+
+ {
+ mp_digit u, *tmpa, *tmpb, *tmpc;
+ int i;
+
+ /* alias for digit pointers */
+
+ /* first input */
+ tmpa = a->dp;
+
+ /* second input */
+ tmpb = b->dp;
+
+ /* destination */
+ tmpc = c->dp;
+
+ /* zero the carry */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+ *tmpc = *tmpa++ + *tmpb++ + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, that is in A+B
+ * if A or B has more digits add those in
+ */
+ if (min != max) {
+ for (; i < max; i++) {
+ /* T[i] = X[i] + U */
+ *tmpc = x->dp[i] + u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+ /* take away carry bit from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* add carry */
+ *tmpc++ = u;
+
+ /* clear digits above oldused */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+static int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int olduse, res, min, max;
+
+ /* find sizes */
+ min = b->used;
+ max = a->used;
+
+ /* init result */
+ if (c->alloc < max) {
+ if ((res = mp_grow (c, max)) != MP_OKAY) {
+ return res;
+ }
+ }
+ olduse = c->used;
+ c->used = max;
+
+ {
+ mp_digit u, *tmpa, *tmpb, *tmpc;
+ int i;
+
+ /* alias for digit pointers */
+ tmpa = a->dp;
+ tmpb = b->dp;
+ tmpc = c->dp;
+
+ /* set carry to zero */
+ u = 0;
+ for (i = 0; i < min; i++) {
+ /* T[i] = A[i] - B[i] - U */
+ *tmpc = *tmpa++ - *tmpb++ - u;
+
+ /* U = carry bit of T[i]
+ * Note this saves performing an AND operation since
+ * if a carry does occur it will propagate all the way to the
+ * MSB. As a result a single shift is enough to get the carry
+ */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* now copy higher words if any, e.g. if A has more digits than B */
+ for (; i < max; i++) {
+ /* T[i] = A[i] - U */
+ *tmpc = *tmpa++ - u;
+
+ /* U = carry bit of T[i] */
+ u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+ /* Clear carry from T[i] */
+ *tmpc++ &= MP_MASK;
+ }
+
+ /* clear digits above used (since we may not have grown result above) */
+ for (i = c->used; i < olduse; i++) {
+ *tmpc++ = 0;
+ }
+ }
+
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+/* high level subtraction (handles signs) */
+static int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ sa = a->sign;
+ sb = b->sign;
+
+ if (sa != sb) {
+ /* subtract a negative from a positive, OR */
+ /* subtract a positive from a negative. */
+ /* In either case, ADD their magnitudes, */
+ /* and use the sign of the first number. */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* subtract a positive from a positive, OR */
+ /* subtract a negative from a negative. */
+ /* First, take the difference between their */
+ /* magnitudes, then... */
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ /* Copy the sign from the first */
+ c->sign = sa;
+ /* The first has a larger or equal magnitude */
+ res = s_mp_sub (a, b, c);
+ } else {
+ /* The result has the *opposite* sign from */
+ /* the first number. */
+ c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+ /* The second has a larger magnitude */
+ res = s_mp_sub (b, a, c);
+ }
+ }
+ return res;
+}
+
+/* shift right a certain amount of digits */
+static int mp_rshd (mp_int * a, int b)
+{
+ int x;
+
+ /* if b <= 0 then ignore it */
+ if (b <= 0) {
+ return 0;
+ }
+
+ /* if b > used then simply zero it and return */
+ if (a->used <= b) {
+ mp_zero (a);
+ return 0;
+ }
+
+ {
+ mp_digit *bottom, *top;
+
+ /* shift the digits down */
+
+ /* bottom */
+ bottom = a->dp;
+
+ /* top [offset into digits] */
+ top = a->dp + b;
+
+ /* this is implemented as a sliding window where
+ * the window is b-digits long and digits from
+ * the top of the window are copied to the bottom
+ *
+ * e.g.
+
+ b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
+ /\ | ---->
+ \-------------------/ ---->
+ */
+ for (x = 0; x < (a->used - b); x++) {
+ *bottom++ = *top++;
+ }
+
+ /* zero the top digits */
+ for (; x < a->used; x++) {
+ *bottom++ = 0;
+ }
+ }
+
+ /* remove excess digits */
+ a->used -= b;
+ return 1;
+}
+
+/* multiply by a digit */
+static int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+ mp_digit u, *tmpa, *tmpc;
+ mp_word r;
+ int ix, res, olduse;
+
+ /* make sure c is big enough to hold a*b */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* get the original destinations used count */
+ olduse = c->used;
+
+ /* set the sign */
+ c->sign = a->sign;
+
+ /* alias for a->dp [source] */
+ tmpa = a->dp;
+
+ /* alias for c->dp [dest] */
+ tmpc = c->dp;
+
+ /* zero carry */
+ u = 0;
+
+ /* compute columns */
+ for (ix = 0; ix < a->used; ix++) {
+ /* compute product and carry sum for this term */
+ r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+ /* mask off higher bits to get a single digit */
+ *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* send carry into next iteration */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+
+ /* store final carry [if any] and increment ix offset */
+ *tmpc++ = u;
+ ++ix;
+
+ /* now zero digits above the top */
+ while (ix++ < olduse) {
+ *tmpc++ = 0;
+ }
+
+ /* set used count */
+ c->used = a->used + 1;
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+/* high level addition (handles signs) */
+static int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+ int sa, sb, res;
+
+ /* get sign of both inputs */
+ sa = a->sign;
+ sb = b->sign;
+
+ /* handle two cases, not four */
+ if (sa == sb) {
+ /* both positive or both negative */
+ /* add their magnitudes, copy the sign */
+ c->sign = sa;
+ res = s_mp_add (a, b, c);
+ } else {
+ /* one positive, the other negative */
+ /* subtract the one with the greater magnitude from */
+ /* the one of the lesser magnitude. The result gets */
+ /* the sign of the one with the greater magnitude. */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ c->sign = sb;
+ res = s_mp_sub (b, a, c);
+ } else {
+ c->sign = sa;
+ res = s_mp_sub (a, b, c);
+ }
+ }
+ return res;
+}
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+static void
+mp_exch(mp_int *a, mp_int *b)
+{
+ mp_int t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+}
+
+/* calc a value mod 2**b */
+static int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+ int x, res;
+
+ /* if b is <= 0 then zero the int */
+ if (b <= 0) {
+ mp_zero (c);
+ return MP_OKAY;
+ }
+
+ /* if the modulus is larger than the value than return */
+ if (b >= (int) (a->used * DIGIT_BIT)) {
+ res = mp_copy (a, c);
+ return res;
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ return res;
+ }
+
+ /* zero digits above the last digit of the modulus */
+ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+ c->dp[x] = 0;
+ }
+ /* clear the digit that is not completely outside/inside the modulus */
+ c->dp[b / DIGIT_BIT] &=
+ (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+static int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+ mp_digit D, r, rr;
+ int x, res;
+ mp_int t;
+
+
+ /* if the shift count is <= 0 then we do no work */
+ if (b <= 0) {
+ res = mp_copy (a, c);
+ if (d != NULL) {
+ mp_zero (d);
+ }
+ return res;
+ }
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ /* get the remainder */
+ if (d != NULL) {
+ if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ }
+
+ /* copy */
+ if ((res = mp_copy (a, c)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ /* shift by as many digits in the bit count */
+ if (b >= (int)DIGIT_BIT) {
+ mp_rshd (c, b / DIGIT_BIT);
+ }
+
+ /* shift any bit count < DIGIT_BIT */
+ D = (mp_digit) (b % DIGIT_BIT);
+ if (D != 0) {
+ mp_digit *tmpc, mask, shift;
+
+ /* mask */
+ mask = (((mp_digit)1) << D) - 1;
+
+ /* shift for lsb */
+ shift = DIGIT_BIT - D;
+
+ /* alias */
+ tmpc = c->dp + (c->used - 1);
+
+ /* carry */
+ r = 0;
+ for (x = c->used - 1; x >= 0; x--) {
+ /* get the lower bits of this word in a temp */
+ rr = *tmpc & mask;
+
+ /* shift the current word and mix in the carry bits from the previous word */
+ *tmpc = (*tmpc >> D) | (r << shift);
+ --tmpc;
+
+ /* set the carry to the carry bits of the current word found above */
+ r = rr;
+ }
+ }
+ mp_clamp (c);
+ if (d != NULL) {
+ mp_exch (&t, d);
+ }
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+/* integer signed division.
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly
+ * incomplete. For example, it doesn't consider
+ * the case where digits are removed from 'x' in
+ * the inner loop. It also doesn't consider the
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+static int
+mp_div(mp_int *c, mp_int *d, mp_int *a, mp_int *b)
+{
+ mp_int q, x, y, t1, t2;
+ int res, n, t, i, norm, neg;
+
+ /* is divisor zero ? */
+ if (BN_is_zero (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if a < b then q=0, r = a */
+ if (mp_cmp_mag (a, b) == MP_LT) {
+ if (d != NULL) {
+ res = mp_copy (a, d);
+ } else {
+ res = MP_OKAY;
+ }
+ if (c != NULL) {
+ mp_zero (c);
+ }
+ return res;
+ }
+
+ if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+ return res;
+ }
+ q.used = a->used + 2;
+
+ if ((res = mp_init (&t1)) != MP_OKAY) {
+ goto LBL_Q;
+ }
+
+ if ((res = mp_init (&t2)) != MP_OKAY) {
+ goto LBL_T1;
+ }
+
+ if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+ goto LBL_T2;
+ }
+
+ if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+ goto LBL_X;
+ }
+
+ /* fix the sign */
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+ x.sign = y.sign = MP_ZPOS;
+
+ /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+ norm = mp_count_bits(&y) % DIGIT_BIT;
+ if (norm < (int)(DIGIT_BIT-1)) {
+ norm = (DIGIT_BIT-1) - norm;
+ if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ } else {
+ norm = 0;
+ }
+
+ /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+ n = x.used - 1;
+ t = y.used - 1;
+
+ /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+ if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+ goto LBL_Y;
+ }
+
+ while (mp_cmp (&x, &y) != MP_LT) {
+ ++(q.dp[n - t]);
+ if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ }
+
+ /* reset y by shifting it back down */
+ mp_rshd (&y, n - t);
+
+ /* step 3. for i from n down to (t + 1) */
+ for (i = n; i >= (t + 1); i--) {
+ if (i > x.used) {
+ continue;
+ }
+
+ /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
+ * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+ if (x.dp[i] == y.dp[t]) {
+ q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+ } else {
+ mp_word tmp;
+ tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+ tmp |= ((mp_word) x.dp[i - 1]);
+ tmp /= ((mp_word) y.dp[t]);
+ if (tmp > (mp_word) MP_MASK)
+ tmp = MP_MASK;
+ q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+ }
+
+ /* while (q{i-t-1} * (yt * b + y{t-1})) >
+ xi * b**2 + xi-1 * b + xi-2
+
+ do q{i-t-1} -= 1;
+ */
+ q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+ do {
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+ /* find left hand */
+ mp_zero (&t1);
+ t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+ t1.dp[1] = y.dp[t];
+ t1.used = 2;
+ if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* find right hand */
+ t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+ t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+ t2.dp[2] = x.dp[i];
+ t2.used = 3;
+ } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+ /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+ if (x.sign == MP_NEG) {
+ if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+ if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+ }
+ }
+
+ /* now q is the quotient and x is the remainder
+ * [which we have to normalize]
+ */
+
+ /* get sign before writing to c */
+ x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+ if (c != NULL) {
+ mp_clamp (&q);
+ mp_exch (&q, c);
+ c->sign = neg;
+ }
+
+ if (d != NULL) {
+ mp_div_2d (&x, norm, &x, NULL);
+ mp_exch (&x, d);
+ }
+
+ res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+ return res;
+}
+
+/* c = a mod b, 0 <= c < b */
+static int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int t;
+ int res;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_div (NULL, &t, a, b)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+
+ if (t.sign != b->sign) {
+ res = mp_add (b, &t, c);
+ } else {
+ res = MP_OKAY;
+ mp_exch (&t, c);
+ }
+
+ mp_clear (&t);
+ return res;
+}
+
+/* set to a digit */
+static void mp_set (mp_int * a, mp_digit b)
+{
+ mp_zero (a);
+ a->dp[0] = b & MP_MASK;
+ a->used = (a->dp[0] != 0) ? 1 : 0;
+}
+
+/* b = a/2 */
+static int mp_div_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* copy */
+ if (b->alloc < a->used) {
+ if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+ {
+ mp_digit r, rr, *tmpa, *tmpb;
+
+ /* source alias */
+ tmpa = a->dp + b->used - 1;
+
+ /* dest alias */
+ tmpb = b->dp + b->used - 1;
+
+ /* carry */
+ r = 0;
+ for (x = b->used - 1; x >= 0; x--) {
+ /* get the carry for the next iteration */
+ rr = *tmpa & 1;
+
+ /* shift the current digit, add in carry and store */
+ *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+ /* forward carry to next iteration */
+ r = rr;
+ }
+
+ /* zero excess digits */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ mp_clamp (b);
+ return MP_OKAY;
+}
+
+/* compare a digit */
+static int mp_cmp_d(mp_int * a, mp_digit b)
+{
+ /* compare based on sign */
+ if (a->sign == MP_NEG) {
+ return MP_LT;
+ }
+
+ /* compare based on magnitude */
+ if (a->used > 1) {
+ return MP_GT;
+ }
+
+ /* compare the only digit of a to b */
+ if (a->dp[0] > b) {
+ return MP_GT;
+ } else if (a->dp[0] < b) {
+ return MP_LT;
+ } else {
+ return MP_EQ;
+ }
+}
+
+static void mp_clear_multi(mp_int *mp, ...)
+{
+ mp_int* next_mp = mp;
+ va_list args;
+ va_start(args, mp);
+ while (next_mp != NULL) {
+ mp_clear(next_mp);
+ next_mp = va_arg(args, mp_int*);
+ }
+ va_end(args);
+}
+
+/* computes the modular inverse via binary extended euclidean algorithm,
+ * that is c = 1/a mod b
+ *
+ * Based on slow invmod except this is optimized for the case where b is
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+static int
+fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, B, D;
+ int res, neg;
+
+ /* 2. [modified] b must be odd */
+ if (BN_is_even (b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init all our temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x == modulus, y == value to invert */
+ if ((res = mp_copy (b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* we need y = |a| */
+ if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (BN_is_even (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if B is odd then */
+ if (BN_is_odd (&B) == 1) {
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* B = B/2 */
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (BN_is_even (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if D is odd then */
+ if (BN_is_odd (&D) == 1) {
+ /* D = (D-x)/2 */
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* D = D/2 */
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (BN_is_zero (&u) == 0) {
+ goto top;
+ }
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* b is now the inverse */
+ neg = a->sign;
+ while (D.sign == MP_NEG) {
+ if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ mp_exch (&D, c);
+ c->sign = neg;
+ res = MP_OKAY;
+
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+ return res;
+}
+
+/* hac 14.61, pp608 */
+static int
+mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x, y, u, v, A, B, C, D;
+ int res;
+
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || BN_is_zero(b) == 1) {
+ return MP_VAL;
+ }
+
+ /* init temps */
+ if ((res = mp_init_multi(&x, &y, &u, &v,
+ &A, &B, &C, &D, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* x = a, y = b */
+ if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (b, &y)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ /* 2. [modified] if x,y are both even then return an error! */
+ if (BN_is_even (&x) == 1 && BN_is_even (&y) == 1) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+ if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ mp_set (&A, 1);
+ mp_set (&D, 1);
+
+top:
+ /* 4. while u is even do */
+ while (BN_is_even (&u) == 1) {
+ /* 4.1 u = u/2 */
+ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 4.2 if A or B is odd then */
+ if (BN_is_odd (&A) == 1 || BN_is_odd (&B) == 1) {
+ /* A = (A+y)/2, B = (B-x)/2 */
+ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* A = A/2, B = B/2 */
+ if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 5. while v is even do */
+ while (BN_is_even (&v) == 1) {
+ /* 5.1 v = v/2 */
+ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ /* 5.2 if C or D is odd then */
+ if (BN_is_odd (&C) == 1 || BN_is_odd (&D) == 1) {
+ /* C = (C+y)/2, D = (D-x)/2 */
+ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+ /* C = C/2, D = D/2 */
+ if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* 6. if u >= v then */
+ if (mp_cmp (&u, &v) != MP_LT) {
+ /* u = u - v, A = A - C, B = B - D */
+ if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ } else {
+ /* v - v - u, C = C - A, D = D - B */
+ if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+
+ if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* if not zero goto step 4 */
+ if (BN_is_zero (&u) == 0)
+ goto top;
+
+ /* now a = C, b = D, gcd == g*v */
+
+ /* if v != 1 then there is no inverse */
+ if (mp_cmp_d (&v, 1) != MP_EQ) {
+ res = MP_VAL;
+ goto LBL_ERR;
+ }
+
+ /* if its too low */
+ while (mp_cmp_d(&C, 0) == MP_LT) {
+ if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* too big */
+ while (mp_cmp_mag(&C, b) != MP_LT) {
+ if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+ goto LBL_ERR;
+ }
+ }
+
+ /* C is now the inverse */
+ mp_exch (&C, c);
+ res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+ return res;
+}
+
+static int
+mp_invmod(mp_int *c, mp_int *a, mp_int *b)
+{
+ /* b cannot be negative */
+ if (b->sign == MP_NEG || BN_is_zero(b) == 1) {
+ return MP_VAL;
+ }
+
+ /* if the modulus is odd we can use a faster routine instead */
+ if (BN_is_odd (b) == 1) {
+ return fast_mp_invmod(a, b, c);
+ }
+
+ return mp_invmod_slow(a, b, c);
+
+ /*NOTREACHED*/
+ return MP_VAL;
+}
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+static int
+mp_abs (mp_int * a, mp_int * b)
+{
+ int res;
+
+ /* copy a to b */
+ if (a != b) {
+ if ((res = mp_copy (a, b)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* force the sign of b to positive */
+ b->sign = MP_ZPOS;
+
+ return MP_OKAY;
+}
+
+/* determines if reduce_2k_l can be used */
+static int mp_reduce_is_2k_l(mp_int *a)
+{
+ int ix, iy;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ /* if more than half of the digits are -1 we're sold */
+ for (iy = ix = 0; ix < a->used; ix++) {
+ if (a->dp[ix] == MP_MASK) {
+ ++iy;
+ }
+ }
+ return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+
+ }
+ return MP_NO;
+}
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+static int
+mp_2expt (mp_int * a, int b)
+{
+ int res;
+
+ /* zero a as per default */
+ mp_zero (a);
+
+ /* grow a to accomodate the single bit */
+ if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* set the used count of where the bit will go */
+ a->used = b / DIGIT_BIT + 1;
+
+ /* put the single bit in its place */
+ a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+ return MP_OKAY;
+}
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+static int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+ int res;
+
+ if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+ return res;
+ }
+ return mp_div (a, NULL, a, b);
+}
+
+/* b = a*2 */
+static int mp_mul_2(mp_int * a, mp_int * b)
+{
+ int x, res, oldused;
+
+ /* grow to accomodate result */
+ if (b->alloc < a->used + 1) {
+ if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ oldused = b->used;
+ b->used = a->used;
+
+ {
+ mp_digit r, rr, *tmpa, *tmpb;
+
+ /* alias for source */
+ tmpa = a->dp;
+
+ /* alias for dest */
+ tmpb = b->dp;
+
+ /* carry */
+ r = 0;
+ for (x = 0; x < a->used; x++) {
+
+ /* get what will be the *next* carry bit from the
+ * MSB of the current digit
+ */
+ rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+ /* now shift up this digit, add in the carry [from the previous] */
+ *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+ /* copy the carry that would be from the source
+ * digit into the next iteration
+ */
+ r = rr;
+ }
+
+ /* new leading digit? */
+ if (r != 0) {
+ /* add a MSB which is always 1 at this point */
+ *tmpb = 1;
+ ++(b->used);
+ }
+
+ /* now zero any excess digits on the destination
+ * that we didn't write to
+ */
+ tmpb = b->dp + b->used;
+ for (x = b->used; x < oldused; x++) {
+ *tmpb++ = 0;
+ }
+ }
+ b->sign = a->sign;
+ return MP_OKAY;
+}
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+static int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+ mp_int q;
+ mp_word w, t;
+ mp_digit b;
+ int res, ix;
+
+ /* b = 2**DIGIT_BIT / 3 */
+ b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= 3) {
+ /* multiply w by [1/3] */
+ t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+ /* now subtract 3 * [w/3] from w, to get the remainder */
+ w -= t+t+t;
+
+ /* fixup the remainder as required since
+ * the optimization is not exact.
+ */
+ while (w >= 3) {
+ t += 1;
+ w -= 3;
+ }
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ /* [optional] store the remainder */
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ /* [optional] store the quotient */
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+/* multiplication using the Toom-Cook 3-way algorithm
+ *
+ * Much more complicated than Karatsuba but has a lower
+ * asymptotic running time of O(N**1.464). This algorithm is
+ * only particularly useful on VERY large inputs
+ * (we're talking 1000s of digits here...).
+*/
+static int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = MIN(a->used, b->used) / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* b = b2 * B**2 + b1 * B + b0 */
+ if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b1, B);
+ mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+ if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&b2, B*2);
+
+ /* w0 = a0*b0 */
+ if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * b2 */
+ if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts,
+ 2 small divisions and 1 small multiplication
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4,
+ &a0, &a1, &a2, &b0, &b1,
+ &b2, &tmp1, &tmp2, NULL);
+ return res;
+}
+
+#define TOOM_MUL_CUTOFF 350
+#define KARATSUBA_MUL_CUTOFF 80
+
+/* c = |a| * |b| using Karatsuba Multiplication using
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and
+ * let n represent half of the number of digits in
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b =>
+ a1b1 * B**2n + ((a1 + a0)(b1 + b0) - (a0b0 + a1b1)) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be
+ * computed once. So in total three half size (half # of
+ * digit) multiplications are performed, a0b0, a1b1 and
+ * (a1+b1)(a0+b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in
+ * total after one call 25% of the single precision multiplications
+ * are saved. Note also that the call to mp_mul can end up back
+ * in this function if the a0, a1, b0, or b1 are above the threshold.
+ * This is known as divide-and-conquer and leads to the famous
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than
+ * the standard O(N**2) that the baseline/comba methods use.
+ * Generally though the overhead of this method doesn't pay off
+ * until a certain size (N ~ 80) is reached.
+ */
+static int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+ mp_int x0, x1, y0, y1, t1, x0y0, x1y1;
+ int B;
+ int err;
+
+ /* default the return code to an error */
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = MIN (a->used, b->used);
+
+ /* now divide in two */
+ B = (int)((unsigned)B >> 1);
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+ if (mp_init_size (&y0, B) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+ goto Y0;
+
+ /* init temps */
+ if (mp_init_size (&t1, B * 2) != MP_OKAY)
+ goto Y1;
+ if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+ goto X0Y0;
+
+ /* now shift the digits */
+ x0.used = y0.used = B;
+ x1.used = a->used - B;
+ y1.used = b->used - B;
+
+ {
+ int x;
+ mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+ /* we copy the digits directly instead of using higher level functions
+ * since we also need to shift the digits
+ */
+ tmpa = a->dp;
+ tmpb = b->dp;
+
+ tmpx = x0.dp;
+ tmpy = y0.dp;
+ for (x = 0; x < B; x++) {
+ *tmpx++ = *tmpa++;
+ *tmpy++ = *tmpb++;
+ }
+
+ tmpx = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *tmpx++ = *tmpa++;
+ }
+
+ tmpy = y1.dp;
+ for (x = B; x < b->used; x++) {
+ *tmpy++ = *tmpb++;
+ }
+ }
+
+ /* only need to clamp the lower words since by definition the
+ * upper words x1/y1 must have a known number of digits
+ */
+ mp_clamp (&x0);
+ mp_clamp (&y0);
+
+ /* now calc the products x0y0 and x1y1 */
+ /* after this x0 is no longer required, free temp [x0==t2]! */
+ if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)
+ goto X1Y1; /* x0y0 = x0*y0 */
+ if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1*y1 */
+
+ /* now calc x1+x0 and y1+y0 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x1 - x0 */
+ if (s_mp_add (&y1, &y0, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = y1 - y0 */
+ if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1 + x0) * (y1 + y0) */
+
+ /* add x0y0 */
+ if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+ goto X1Y1; /* t2 = x0y0 + x1y1 */
+ if (s_mp_sub (&t1, &x0, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+ if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+ goto X1Y1; /* x1y1 = x1y1 << 2*B */
+
+ if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 */
+ if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+ goto X1Y1; /* t1 = x0y0 + t1 + x1y1 */
+
+ /* Algorithm succeeded set the return code to MP_OKAY */
+ err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier. It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards. This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ /*LINTED*/
+ mp_digit W[MP_WARRAY];
+ mp_word _W;
+
+ /* grow the destination as required */
+ if (c->alloc < digs) {
+ if ((res = mp_grow (c, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = MIN(digs, a->used + b->used);
+
+ /* clear the carry */
+ _W = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty;
+ int iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; ++iz) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ mp_digit *tmpc;
+ tmpc = c->dp;
+ for (ix = 0; ix < pa+1; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_fast_s_mp_mul_digs.c,v $ */
+/* Revision: 1.2 $ */
+/* Date: 2011/03/18 16:22:09 $ */
+
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12 Modified so you can control how
+ * many digits of output are created.
+ */
+static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+ if (((unsigned)(digs) < MP_WARRAY) &&
+ MIN (a->used, b->used) <
+ (1 << (unsigned)((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_digs (a, b, c, digs);
+ }
+
+ if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+ return res;
+ }
+ t.used = digs;
+
+ /* compute the digits of the product directly */
+ pa = a->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* set the carry to zero */
+ u = 0;
+
+ /* limit ourselves to making digs digits of output */
+ pb = MIN (b->used, digs - ix);
+
+ /* setup some aliases */
+ /* copy of the digit from a used within the nested loop */
+ tmpx = a->dp[ix];
+
+ /* an alias for the destination shifted ix places */
+ tmpt = t.dp + ix;
+
+ /* an alias for the digits of b */
+ tmpy = b->dp;
+
+ /* compute the columns of the output and propagate the carry */
+ for (iy = 0; iy < pb; iy++) {
+ /* compute the column as a mp_word */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* the new column is the lower part of the result */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry word from the result */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ /* set carry if it is placed below digs */
+ if (ix + iy < digs) {
+ *tmpt = u;
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, c);
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_s_mp_mul_digs.c,v $ */
+/* Revision: 1.3 $ */
+/* Date: 2011/03/18 16:43:04 $ */
+
+/* high level multiplication (handles sign) */
+static int
+mp_mul(mp_int * a, mp_int * b, mp_int * c)
+{
+ int res, neg;
+ neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+ /* use Toom-Cook? */
+ if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+ res = mp_toom_mul(a, b, c);
+ } else
+ /* use Karatsuba? */
+ if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+ res = mp_karatsuba_mul (a, b, c);
+ } else
+ {
+ /* can we use the fast multiplier?
+ *
+ * The fast multiplier can be used if the output will
+ * have less than MP_WARRAY digits and the number of
+ * digits won't affect carry propagation
+ */
+ int digs = a->used + b->used + 1;
+
+ if (((unsigned)digs < MP_WARRAY) &&
+ MIN(a->used, b->used) <=
+ (1 << (unsigned)((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ res = fast_s_mp_mul_digs (a, b, c, digs);
+ } else
+ res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+
+ }
+ c->sign = (c->used > 0) ? neg : MP_ZPOS;
+ return res;
+}
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs. See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed. This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+static int
+fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY];
+ mp_word _W;
+
+ /* grow the destination as required */
+ pa = a->used + b->used;
+ if (c->alloc < pa) {
+ if ((res = mp_grow (c, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ pa = a->used + b->used;
+ _W = 0;
+ for (ix = digs; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_digit *tmpx, *tmpy;
+
+ /* get offsets into the two bignums */
+ ty = MIN(b->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = b->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially its
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* store term */
+ W[ix] = ((mp_digit)_W) & MP_MASK;
+
+ /* make next carry */
+ _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = c->used;
+ c->used = pa;
+
+ {
+ mp_digit *tmpc;
+
+ tmpc = c->dp + digs;
+ for (ix = digs; ix < pa; ix++) {
+ /* now extract the previous digit [below the carry] */
+ *tmpc++ = W[ix];
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpc++ = 0;
+ }
+ }
+ mp_clamp (c);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_fast_s_mp_mul_high_digs.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+static int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+ mp_int t;
+ int res, pa, pb, ix, iy;
+ mp_digit u;
+ mp_word r;
+ mp_digit tmpx, *tmpt, *tmpy;
+
+ /* can we use the fast multiplier? */
+ if (((unsigned)(a->used + b->used + 1) < MP_WARRAY)
+ && MIN (a->used, b->used) < (1 << (unsigned)((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_s_mp_mul_high_digs (a, b, c, digs);
+ }
+
+ if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ t.used = a->used + b->used + 1;
+
+ pa = a->used;
+ pb = b->used;
+ for (ix = 0; ix < pa; ix++) {
+ /* clear the carry */
+ u = 0;
+
+ /* left hand side of A[ix] * B[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias to the address of where the digits will be stored */
+ tmpt = &(t.dp[digs]);
+
+ /* alias for where to read the right hand side from */
+ tmpy = b->dp + (digs - ix);
+
+ for (iy = digs - ix; iy < pb; iy++) {
+ /* calculate the double precision result */
+ r = ((mp_word)*tmpt) +
+ ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+ ((mp_word) u);
+
+ /* get the lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* carry the carry */
+ u = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+ }
+ *tmpt = u;
+ }
+ mp_clamp (&t);
+ mp_exch (&t, c);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_s_mp_mul_high_digs.c,v $ */
+/* Revision: 1.3 $ */
+/* Date: 2011/03/18 16:43:04 $ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+static int
+mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+ mp_int q;
+ int res, um = m->used;
+
+ /* q = x */
+ if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+ return res;
+ }
+
+ /* q1 = x / b**(k-1) */
+ mp_rshd (&q, um - 1);
+
+ /* according to HAC this optimization is ok */
+ if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+ if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ } else {
+ if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ }
+
+ /* q3 = q2 / b**(k+1) */
+ mp_rshd (&q, um + 1);
+
+ /* x = x mod b**(k+1), quick (no division) */
+ if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* q = q * m mod b**(k+1), quick (no division) */
+ if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* x = x - q */
+ if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+
+ /* If x < 0, add b**(k+1) to it */
+ if (mp_cmp_d (x, 0) == MP_LT) {
+ mp_set (&q, 1);
+ if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+ goto CLEANUP;
+ if ((res = mp_add (x, &q, x)) != MP_OKAY)
+ goto CLEANUP;
+ }
+
+ /* Back off if it's too big */
+ while (mp_cmp (x, m) != MP_LT) {
+ if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+ goto CLEANUP;
+ }
+ }
+
+CLEANUP:
+ mp_clear (&q);
+
+ return res;
+}
+
+/* determines the setup value */
+static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+ int res;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear(&tmp);
+ return res;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_reduce_2k_setup_l.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* reduces a modulo n where n is of the form 2**p - d
+ This differs from reduce_2k since "d" can be larger
+ than a single digit.
+*/
+static int
+mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* q = q * d */
+ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_reduce_2k_l.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* squaring using Toom-Cook 3-way algorithm */
+static int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+ mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+ int res, B;
+
+ /* init temps */
+ if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+ return res;
+ }
+
+ /* B */
+ B = a->used / 3;
+
+ /* a = a2 * B**2 + a1 * B + a0 */
+ if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a1, B);
+ mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+ if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+ goto ERR;
+ }
+ mp_rshd(&a2, B*2);
+
+ /* w0 = a0*a0 */
+ if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w4 = a2 * a2 */
+ if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w1 = (a2 + 2(a1 + 2a0))**2 */
+ if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* w3 = (a0 + 2(a1 + 2a2))**2 */
+ if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+
+
+ /* w2 = (a2 + a1 + a0)**2 */
+ if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* now solve the matrix
+
+ 0 0 0 0 1
+ 1 2 4 8 16
+ 1 1 1 1 1
+ 16 8 4 2 1
+ 1 0 0 0 0
+
+ using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+ */
+
+ /* r1 - r4 */
+ if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r0 */
+ if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/2 */
+ if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/2 */
+ if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r2 - r0 - r4 */
+ if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - 8r0 */
+ if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - 8r4 */
+ if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* 3r2 - r1 - r3 */
+ if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1 - r2 */
+ if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3 - r2 */
+ if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r1/3 */
+ if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+ /* r3/3 */
+ if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ /* at this point shift W[n] by B*n */
+ if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+ goto ERR;
+ }
+ if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ERR:
+ mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+ return res;
+}
+
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_toom_sqr.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* Karatsuba squaring, computes b = a*a using three
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details. It
+ * is essentially the same algorithm but merely
+ * tuned to perform recursive squarings.
+ */
+static int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+ mp_int x0, x1, t1, t2, x0x0, x1x1;
+ int B, err;
+
+ err = MP_MEM;
+
+ /* min # of digits */
+ B = a->used;
+
+ /* now divide in two */
+ B = (unsigned)B >> 1;
+
+ /* init copy all the temps */
+ if (mp_init_size (&x0, B) != MP_OKAY)
+ goto ERR;
+ if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+ goto X0;
+
+ /* init temps */
+ if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+ goto X1;
+ if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+ goto T1;
+ if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+ goto T2;
+ if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+ goto X0X0;
+
+ {
+ int x;
+ mp_digit *dst, *src;
+
+ src = a->dp;
+
+ /* now shift the digits */
+ dst = x0.dp;
+ for (x = 0; x < B; x++) {
+ *dst++ = *src++;
+ }
+
+ dst = x1.dp;
+ for (x = B; x < a->used; x++) {
+ *dst++ = *src++;
+ }
+ }
+
+ x0.used = B;
+ x1.used = a->used - B;
+
+ mp_clamp (&x0);
+
+ /* now calc the products x0*x0 and x1*x1 */
+ if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+ goto X1X1; /* x0x0 = x0*x0 */
+ if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1*x1 */
+
+ /* now calc (x1+x0)**2 */
+ if (s_mp_add (&x1, &x0, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x1 - x0 */
+ if (mp_sqr (&t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */
+
+ /* add x0y0 */
+ if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+ goto X1X1; /* t2 = x0x0 + x1x1 */
+ if (s_mp_sub (&t1, &t2, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = (x1+x0)**2 - (x0x0 + x1x1) */
+
+ /* shift by B */
+ if (mp_lshd (&t1, B) != MP_OKAY)
+ goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+ if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+ goto X1X1; /* x1x1 = x1x1 << 2*B */
+
+ if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 */
+ if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+ goto X1X1; /* t1 = x0x0 + t1 + x1x1 */
+
+ err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+ return err;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_karatsuba_sqr.c,v $ */
+/* Revision: 1.2 $ */
+/* Date: 2011/03/12 23:43:54 $ */
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens. You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+static int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+ int olduse, res, pa, ix, iz;
+ mp_digit W[MP_WARRAY], *tmpx;
+ mp_word W1;
+
+ /* grow the destination as required */
+ pa = a->used + a->used;
+ if (b->alloc < pa) {
+ if ((res = mp_grow (b, pa)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* number of output digits to produce */
+ W1 = 0;
+ for (ix = 0; ix < pa; ix++) {
+ int tx, ty, iy;
+ mp_word _W;
+ mp_digit *tmpy;
+
+ /* clear counter */
+ _W = 0;
+
+ /* get offsets into the two bignums */
+ ty = MIN(a->used-1, ix);
+ tx = ix - ty;
+
+ /* setup temp aliases */
+ tmpx = a->dp + tx;
+ tmpy = a->dp + ty;
+
+ /* this is the number of times the loop will iterrate, essentially
+ while (tx++ < a->used && ty-- >= 0) { ... }
+ */
+ iy = MIN(a->used-tx, ty+1);
+
+ /* now for squaring tx can never equal ty
+ * we halve the distance since they approach at a rate of 2x
+ * and we have to round because odd cases need to be executed
+ */
+ iy = MIN(iy, (int)((unsigned)(ty-tx+1)>>1));
+
+ /* execute loop */
+ for (iz = 0; iz < iy; iz++) {
+ _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+ }
+
+ /* double the inner product and add carry */
+ _W = _W + _W + W1;
+
+ /* even columns have the square term in them */
+ if ((ix&1) == 0) {
+ _W += ((mp_word)a->dp[(unsigned)ix>>1])*((mp_word)a->dp[(unsigned)ix>>1]);
+ }
+
+ /* store it */
+ W[ix] = (mp_digit)(_W & MP_MASK);
+
+ /* make next carry */
+ W1 = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+ /* setup dest */
+ olduse = b->used;
+ b->used = a->used+a->used;
+
+ {
+ mp_digit *tmpb;
+ tmpb = b->dp;
+ for (ix = 0; ix < pa; ix++) {
+ *tmpb++ = W[ix] & MP_MASK;
+ }
+
+ /* clear unused digits [that existed in the old copy of c] */
+ for (; ix < olduse; ix++) {
+ *tmpb++ = 0;
+ }
+ }
+ mp_clamp (b);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_fast_s_mp_sqr.c,v $ */
+/* Revision: 1.3 $ */
+/* Date: 2011/03/18 16:43:04 $ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+static int
+s_mp_sqr (mp_int * a, mp_int * b)
+{
+ mp_int t;
+ int res, ix, iy, pa;
+ mp_word r;
+ mp_digit u, tmpx, *tmpt;
+
+ pa = a->used;
+ if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+ return res;
+ }
+
+ /* default used is maximum possible size */
+ t.used = 2*pa + 1;
+
+ for (ix = 0; ix < pa; ix++) {
+ /* first calculate the digit at 2*ix */
+ /* calculate double precision result */
+ r = ((mp_word) t.dp[2*ix]) +
+ ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+ /* store lower part in result */
+ t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get the carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* left hand side of A[ix] * A[iy] */
+ tmpx = a->dp[ix];
+
+ /* alias for where to store the results */
+ tmpt = t.dp + (2*ix + 1);
+
+ for (iy = ix + 1; iy < pa; iy++) {
+ /* first calculate the product */
+ r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+ /* now calculate the double precision result, note we use
+ * addition instead of *2 since it's easier to optimize
+ */
+ r = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+ /* store lower part */
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ /* propagate upwards */
+ while (u != ((mp_digit) 0)) {
+ r = ((mp_word) *tmpt) + ((mp_word) u);
+ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+ }
+ }
+
+ mp_clamp (&t);
+ mp_exch (&t, b);
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_s_mp_sqr.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+#define TOOM_SQR_CUTOFF 400
+#define KARATSUBA_SQR_CUTOFF 120
+
+/* computes b = a*a */
+static int
+mp_sqr (mp_int * a, mp_int * b)
+{
+ int res;
+
+ /* use Toom-Cook? */
+ if (a->used >= TOOM_SQR_CUTOFF) {
+ res = mp_toom_sqr(a, b);
+ /* Karatsuba? */
+ } else
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+ res = mp_karatsuba_sqr (a, b);
+ } else
+ {
+ /* can we use the fast comba multiplier? */
+ if (((unsigned)a->used * 2 + 1) < MP_WARRAY &&
+ a->used <
+ (1 << (unsigned)(sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+ res = fast_s_mp_sqr (a, b);
+ } else
+ res = s_mp_sqr (a, b);
+ }
+ b->sign = MP_ZPOS;
+ return res;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_sqr.c,v $ */
+/* Revision: 1.3 $ */
+/* Date: 2011/03/18 16:43:04 $ */
+
+#define TAB_SIZE 256
+
+static int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res, mu;
+ mp_digit buf;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+ int (*redux)(mp_int*,mp_int*,mp_int*);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* create mu, used for Barrett reduction */
+ if ((err = mp_init (&mu)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ if (redmode == 0) {
+ if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce;
+ } else {
+ if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ redux = mp_reduce_2k_l;
+ }
+
+ /* create M table
+ *
+ * The M table contains powers of the base,
+ * e.g. M[x] = G**x mod P
+ *
+ * The first half of the table is not
+ * computed though accept for M[0] and M[1]
+ */
+ if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring
+ * M[1] (winsize-1) times
+ */
+ if ((err = mp_copy ( &M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ /* square it */
+ if ((err = mp_sqr (&M[1 << (winsize - 1)],
+ &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+
+ /* reduce modulo P */
+ if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+ * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+ */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_MU;
+ }
+ mp_set (&res, 1);
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset the bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int) DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (unsigned)(buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+
+/* determines if a number is a valid DR modulus */
+static int
+mp_dr_is_modulus(mp_int *a)
+{
+ int ix;
+
+ /* must be at least two digits */
+ if (a->used < 2) {
+ return 0;
+ }
+
+ /* must be of the form b**k - a [a <= b] so all
+ * but the first digit must be equal to -1 (mod b).
+ */
+ for (ix = 1; ix < a->used; ix++) {
+ if (a->dp[ix] != MP_MASK) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_dr_is_modulus.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* determines if mp_reduce_2k can be used */
+static int mp_reduce_is_2k(mp_int *a)
+{
+ int ix, iy, iw;
+ mp_digit iz;
+
+ if (a->used == 0) {
+ return MP_NO;
+ } else if (a->used == 1) {
+ return MP_YES;
+ } else if (a->used > 1) {
+ iy = mp_count_bits(a);
+ iz = 1;
+ iw = 1;
+
+ /* Test every bit from the second digit up, must be 1 */
+ for (ix = DIGIT_BIT; ix < iy; ix++) {
+ if ((a->dp[iw] & iz) == 0) {
+ return MP_NO;
+ }
+ iz <<= 1;
+ if (iz > (mp_digit)MP_MASK) {
+ ++iw;
+ iz = 1;
+ }
+ }
+ }
+ return MP_YES;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_reduce_is_2k.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+
+/* d = a * b (mod c) */
+static int
+mp_mulmod (mp_int *d, mp_int * a, mp_int * b, mp_int * c)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_mulmod.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* setups the montgomery reduction stuff */
+static int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+ mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n)
+ * => 2*X*A - X*X*A*A = 1
+ * => 2*(1) - (1) = 1
+ */
+ b = n->dp[0];
+
+ if ((b & 1) == 0) {
+ return MP_VAL;
+ }
+
+ x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**8 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**16 */
+ x *= 2 - b * x; /* here x*a==1 mod 2**32 */
+ if (/*CONSTCOND*/sizeof(mp_digit) == 8) {
+ x *= 2 - b * x; /* here x*a==1 mod 2**64 */
+ }
+
+ /* rho = -1/m mod b */
+ *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_montgomery_setup.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+static int
+fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, olduse;
+ /*LINTED*/
+ mp_word W[MP_WARRAY];
+
+ /* get old used count */
+ olduse = x->used;
+
+ /* grow a as required */
+ if (x->alloc < n->used + 1) {
+ if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* first we have to get the digits of the input into
+ * an array of double precision words W[...]
+ */
+ {
+ mp_word *_W;
+ mp_digit *tmpx;
+
+ /* alias for the W[] array */
+ _W = W;
+
+ /* alias for the digits of x*/
+ tmpx = x->dp;
+
+ /* copy the digits of a into W[0..a->used-1] */
+ for (ix = 0; ix < x->used; ix++) {
+ *_W++ = *tmpx++;
+ }
+
+ /* zero the high words of W[a->used..m->used*2] */
+ for (; ix < n->used * 2 + 1; ix++) {
+ *_W++ = 0;
+ }
+ }
+
+ /* now we proceed to zero successive digits
+ * from the least significant upwards
+ */
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * m' mod b
+ *
+ * We avoid a double precision multiplication (which isn't required)
+ * by casting the value down to a mp_digit. Note this requires
+ * that W[ix-1] have the carry cleared (see after the inner loop)
+ */
+ mp_digit mu;
+ mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i
+ *
+ * This is computed in place and on the fly. The multiplication
+ * by b**i is handled by offseting which columns the results
+ * are added to.
+ *
+ * Note the comba method normally doesn't handle carries in the
+ * inner loop In this case we fix the carry from the previous
+ * column since the Montgomery reduction requires digits of the
+ * result (so far) [see above] to work. This is
+ * handled by fixing up one carry after the inner loop. The
+ * carry fixups are done in order so after these loops the
+ * first m->used words of W[] have the carries fixed
+ */
+ {
+ int iy;
+ mp_digit *tmpn;
+ mp_word *_W;
+
+ /* alias for the digits of the modulus */
+ tmpn = n->dp;
+
+ /* Alias for the columns set by an offset of ix */
+ _W = W + ix;
+
+ /* inner loop */
+ for (iy = 0; iy < n->used; iy++) {
+ *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+ }
+ }
+
+ /* now fix carry for next digit, W[ix+1] */
+ W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* now we have to propagate the carries and
+ * shift the words downward [all those least
+ * significant digits we zeroed].
+ */
+ {
+ mp_digit *tmpx;
+ mp_word *_W, *_W1;
+
+ /* nox fix rest of carries */
+
+ /* alias for current word */
+ _W1 = W + ix;
+
+ /* alias for next word, where the carry goes */
+ _W = W + ++ix;
+
+ for (; ix <= n->used * 2 + 1; ix++) {
+ *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+ }
+
+ /* copy out, A = A/b**n
+ *
+ * The result is A/b**n but instead of converting from an
+ * array of mp_word to mp_digit than calling mp_rshd
+ * we just copy them in the right order
+ */
+
+ /* alias for destination word */
+ tmpx = x->dp;
+
+ /* alias for shifted double precision result */
+ _W = W + n->used;
+
+ for (ix = 0; ix < n->used + 1; ix++) {
+ *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+ }
+
+ /* zero oldused digits, if the input a was larger than
+ * m->used+1 we'll have to clear the digits
+ */
+ for (; ix < olduse; ix++) {
+ *tmpx++ = 0;
+ }
+ }
+
+ /* set the max used and clamp */
+ x->used = n->used + 1;
+ mp_clamp (x);
+
+ /* if A >= m then A = A - m */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_fast_mp_montgomery_reduce.c,v $ */
+/* Revision: 1.2 $ */
+/* Date: 2011/03/18 16:22:09 $ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+static int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+ int ix, res, digs;
+ mp_digit mu;
+
+ /* can the fast reduction [comba] method be used?
+ *
+ * Note that unlike in mul you're safely allowed *less*
+ * than the available columns [255 per default] since carries
+ * are fixed up in the inner loop.
+ */
+ digs = n->used * 2 + 1;
+ if (((unsigned)digs < MP_WARRAY) &&
+ n->used <
+ (1 << (unsigned)((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ return fast_mp_montgomery_reduce (x, n, rho);
+ }
+
+ /* grow the input as required */
+ if (x->alloc < digs) {
+ if ((res = mp_grow (x, digs)) != MP_OKAY) {
+ return res;
+ }
+ }
+ x->used = digs;
+
+ for (ix = 0; ix < n->used; ix++) {
+ /* mu = ai * rho mod b
+ *
+ * The value of rho must be precalculated via
+ * montgomery_setup() such that
+ * it equals -1/n0 mod b this allows the
+ * following inner loop to reduce the
+ * input one digit at a time
+ */
+ mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+ /* a = a + mu * m * b**i */
+ {
+ int iy;
+ mp_digit *tmpn, *tmpx, u;
+ mp_word r;
+
+ /* alias for digits of the modulus */
+ tmpn = n->dp;
+
+ /* alias for the digits of x [the input] */
+ tmpx = x->dp + ix;
+
+ /* set the carry to zero */
+ u = 0;
+
+ /* Multiply and add in place */
+ for (iy = 0; iy < n->used; iy++) {
+ /* compute product and sum */
+ r = ((mp_word)mu) * ((mp_word)*tmpn++) +
+ ((mp_word) u) + ((mp_word) * tmpx);
+
+ /* get carry */
+ u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+ /* fix digit */
+ *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+ }
+ /* At this point the ix'th digit of x should be zero */
+
+
+ /* propagate carries upwards as required*/
+ while (u) {
+ *tmpx += u;
+ u = *tmpx >> DIGIT_BIT;
+ *tmpx++ &= MP_MASK;
+ }
+ }
+ }
+
+ /* at this point the n.used'th least
+ * significant digits of x are all zero
+ * which means we can shift x to the
+ * right by n.used digits and the
+ * residue is unchanged.
+ */
+
+ /* x = x/b**n.used */
+ mp_clamp(x);
+ mp_rshd (x, n->used);
+
+ /* if x >= n then x = x - n */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ return s_mp_sub (x, n, x);
+ }
+
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_montgomery_reduce.c,v $ */
+/* Revision: 1.3 $ */
+/* Date: 2011/03/18 16:43:04 $ */
+
+/* determines the setup value */
+static void
+mp_dr_setup(mp_int *a, mp_digit *d)
+{
+ /* the casts are required if DIGIT_BIT is one less than
+ * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+ */
+ *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) -
+ ((mp_word)a->dp[0]));
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_dr_setup.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ * Chae Hoon Lim, Pil Joong Lee,
+ * POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+static int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+ int err, i, m;
+ mp_word r;
+ mp_digit mu, *tmpx1, *tmpx2;
+
+ /* m = digits in modulus */
+ m = n->used;
+
+ /* ensure that "x" has at least 2m digits */
+ if (x->alloc < m + m) {
+ if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+ return err;
+ }
+ }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+ /* aliases for digits */
+ /* alias for lower half of x */
+ tmpx1 = x->dp;
+
+ /* alias for upper half of x, or x/B**m */
+ tmpx2 = x->dp + m;
+
+ /* set carry to zero */
+ mu = 0;
+
+ /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+ for (i = 0; i < m; i++) {
+ r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+ *tmpx1++ = (mp_digit)(r & MP_MASK);
+ mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+ }
+
+ /* set final carry */
+ *tmpx1++ = mu;
+
+ /* zero words above m */
+ for (i = m + 1; i < x->used; i++) {
+ *tmpx1++ = 0;
+ }
+
+ /* clamp, sub and return */
+ mp_clamp (x);
+
+ /* if x >= n then subtract and reduce again
+ * Each successive "recursion" makes the input smaller and smaller.
+ */
+ if (mp_cmp_mag (x, n) != MP_LT) {
+ s_mp_sub(x, n, x);
+ goto top;
+ }
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_dr_reduce.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* determines the setup value */
+static int
+mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+ int res, p;
+ mp_int tmp;
+
+ if ((res = mp_init(&tmp)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(a);
+ if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+ mp_clear(&tmp);
+ return res;
+ }
+
+ *d = tmp.dp[0];
+ mp_clear(&tmp);
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_reduce_2k_setup.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+static int
+mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+ mp_int q;
+ int p, res;
+
+ if ((res = mp_init(&q)) != MP_OKAY) {
+ return res;
+ }
+
+ p = mp_count_bits(n);
+top:
+ /* q = a/2**p, a = a mod 2**p */
+ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (d != 1) {
+ /* q = q * d */
+ if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) {
+ goto ERR;
+ }
+ }
+
+ /* a = a + q */
+ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+ goto ERR;
+ }
+
+ if (mp_cmp_mag(a, n) != MP_LT) {
+ s_mp_sub(a, n, a);
+ goto top;
+ }
+
+ERR:
+ mp_clear(&q);
+ return res;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_reduce_2k.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b. This saves alot of multiple precision shifting.
+ */
+static int
+mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+ int x, bits, res;
+
+ /* how many bits of last digit does b use */
+ bits = mp_count_bits (b) % DIGIT_BIT;
+
+ if (b->used > 1) {
+ if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+ return res;
+ }
+ } else {
+ mp_set(a, 1);
+ bits = 1;
+ }
+
+
+ /* now compute C = A * B mod b */
+ for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+ if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+ return res;
+ }
+ if (mp_cmp_mag (a, b) != MP_LT) {
+ if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+ return res;
+ }
+ }
+ }
+
+ return MP_OKAY;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_montgomery_calc_normalization.c,v $ */
+/* Revision: 1.1.1.1 $ */
+/* Date: 2011/03/12 22:58:18 $ */
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#define TAB_SIZE 256
+
+static int
+mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+ mp_int M[TAB_SIZE], res;
+ mp_digit buf, mp;
+ int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+ /* use a pointer to the reduction algorithm. This allows us to use
+ * one of many reduction algorithms without modding the guts of
+ * the code with if statements everywhere.
+ */
+ int (*redux)(mp_int*,mp_int*,mp_digit);
+
+ /* find window size */
+ x = mp_count_bits (X);
+ if (x <= 7) {
+ winsize = 2;
+ } else if (x <= 36) {
+ winsize = 3;
+ } else if (x <= 140) {
+ winsize = 4;
+ } else if (x <= 450) {
+ winsize = 5;
+ } else if (x <= 1303) {
+ winsize = 6;
+ } else if (x <= 3529) {
+ winsize = 7;
+ } else {
+ winsize = 8;
+ }
+
+ /* init M array */
+ /* init first cell */
+ if ((err = mp_init(&M[1])) != MP_OKAY) {
+ return err;
+ }
+
+ /* now init the second half of the array */
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ if ((err = mp_init(&M[x])) != MP_OKAY) {
+ for (y = 1<<(winsize-1); y < x; y++) {
+ mp_clear (&M[y]);
+ }
+ mp_clear(&M[1]);
+ return err;
+ }
+ }
+
+ /* determine and setup reduction code */
+ if (redmode == 0) {
+ /* now setup montgomery */
+ if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+ if (((unsigned)(P->used * 2 + 1) < MP_WARRAY) &&
+ P->used < (1 << (unsigned)((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+ redux = fast_mp_montgomery_reduce;
+ } else
+ {
+ /* use slower baseline Montgomery method */
+ redux = mp_montgomery_reduce;
+ }
+ } else if (redmode == 1) {
+ /* setup DR reduction for moduli of the form B**k - b */
+ mp_dr_setup(P, &mp);
+ redux = mp_dr_reduce;
+ } else {
+ /* setup DR reduction for moduli of the form 2**k - b */
+ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+ goto LBL_M;
+ }
+ redux = mp_reduce_2k;
+ }
+
+ /* setup result */
+ if ((err = mp_init (&res)) != MP_OKAY) {
+ goto LBL_M;
+ }
+
+ /* create M table
+ *
+
+ *
+ * The first half of the table is not computed though accept for M[0] and M[1]
+ */
+
+ if (redmode == 0) {
+ /* now we need R mod m */
+ if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* now set M[1] to G * R mod m */
+ if ((err = mp_mulmod (&M[1], G, &res, P)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ } else {
+ mp_set(&res, 1);
+ if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+ if ((err = mp_copy ( &M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ for (x = 0; x < (winsize - 1); x++) {
+ if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* create upper table */
+ for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+ if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* set initial mode and bit cnt */
+ mode = 0;
+ bitcnt = 1;
+ buf = 0;
+ digidx = X->used - 1;
+ bitcpy = 0;
+ bitbuf = 0;
+
+ for (;;) {
+ /* grab next digit as required */
+ if (--bitcnt == 0) {
+ /* if digidx == -1 we are out of digits so break */
+ if (digidx == -1) {
+ break;
+ }
+ /* read next digit and reset bitcnt */
+ buf = X->dp[digidx--];
+ bitcnt = (int)DIGIT_BIT;
+ }
+
+ /* grab the next msb from the exponent */
+ y = (int)(mp_digit)((mp_digit)buf >> (unsigned)(DIGIT_BIT - 1)) & 1;
+ buf <<= (mp_digit)1;
+
+ /* if the bit is zero and mode == 0 then we ignore it
+ * These represent the leading zero bits before the first 1 bit
+ * in the exponent. Technically this opt is not required but it
+ * does lower the # of trivial squaring/reductions used
+ */
+ if (mode == 0 && y == 0) {
+ continue;
+ }
+
+ /* if the bit is zero and mode == 1 then we square */
+ if (mode == 1 && y == 0) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ continue;
+ }
+
+ /* else we add it to the window */
+ bitbuf |= (y << (winsize - ++bitcpy));
+ mode = 2;
+
+ if (bitcpy == winsize) {
+ /* ok window is filled so square as required and multiply */
+ /* square first */
+ for (x = 0; x < winsize; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* empty window and reset */
+ bitcpy = 0;
+ bitbuf = 0;
+ mode = 1;
+ }
+ }
+
+ /* if bits remain then square/multiply */
+ if (mode == 2 && bitcpy > 0) {
+ /* square then multiply if the bit is set */
+ for (x = 0; x < bitcpy; x++) {
+ if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+
+ /* get next bit of the window */
+ bitbuf <<= 1;
+ if ((bitbuf & (1 << winsize)) != 0) {
+ /* then multiply */
+ if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ if ((err = redux (&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+ }
+ }
+
+ if (redmode == 0) {
+ /* fixup result if Montgomery reduction is used
+ * recall that any value in a Montgomery system is
+ * actually multiplied by R mod n. So we have
+ * to reduce one more time to cancel out the factor
+ * of R.
+ */
+ if ((err = redux(&res, P, mp)) != MP_OKAY) {
+ goto LBL_RES;
+ }
+ }
+
+ /* swap res with Y */
+ mp_exch (&res, Y);
+ err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+ mp_clear(&M[1]);
+ for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+ mp_clear (&M[x]);
+ }
+ return err;
+}
+
+/* Source: /usr/cvsroot/libtommath/dist/libtommath/bn_mp_exptmod_fast.c,v $ */
+/* Revision: 1.4 $ */
+/* Date: 2011/03/18 16:43:04 $ */
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions. Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+static int
+mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int *Y)
+{
+ int dr;
+
+ /* modulus P must be positive */
+ if (P->sign == MP_NEG) {
+ return MP_VAL;
+ }
+
+ /* if exponent X is negative we have to recurse */
+ if (X->sign == MP_NEG) {
+ mp_int tmpG, tmpX;
+ int err;
+
+ /* first compute 1/G mod P */
+ if ((err = mp_init(&tmpG)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_invmod(&tmpG, G, P)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+
+ /* now get |X| */
+ if ((err = mp_init(&tmpX)) != MP_OKAY) {
+ mp_clear(&tmpG);
+ return err;
+ }
+ if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+ }
+
+ /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+ err = mp_exptmod(&tmpG, &tmpX, P, Y);
+ mp_clear_multi(&tmpG, &tmpX, NULL);
+ return err;
+ }
+
+/* modified diminished radix reduction */
+ if (mp_reduce_is_2k_l(P) == MP_YES) {
+ return s_mp_exptmod(G, X, P, Y, 1);
+ }
+
+ /* is it a DR modulus? */
+ dr = mp_dr_is_modulus(P);
+
+ /* if not, is it a unrestricted DR modulus? */
+ if (dr == 0) {
+ dr = mp_reduce_is_2k(P) << 1;
+ }
+
+ /* if the modulus is odd or dr != 0 use the montgomery method */
+ if (BN_is_odd (P) == 1 || dr != 0) {
+ return mp_exptmod_fast (G, X, P, Y, dr);
+ } else {
+ /* otherwise use the generic Barrett reduction technique */
+ return s_mp_exptmod (G, X, P, Y, 0);
+ }
+}
+
+/* reverse an array, used for radix code */
+static void
+bn_reverse(unsigned char *s, int len)
+{
+ int ix, iy;
+ unsigned char t;
+
+ ix = 0;
+ iy = len - 1;
+ while (ix < iy) {
+ t = s[ix];
+ s[ix] = s[iy];
+ s[iy] = t;
+ ++ix;
+ --iy;
+ }
+}
+
+static int
+s_is_power_of_two(mp_digit b, int *p)
+{
+ int x;
+
+ /* fast return if no power of two */
+ if ((b==0) || (b & (b-1))) {
+ return 0;
+ }
+
+ for (x = 0; x < DIGIT_BIT; x++) {
+ if (b == (((mp_digit)1)<<x)) {
+ *p = x;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+static int
+mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d)
+{
+ mp_int q;
+ mp_word w;
+ mp_digit t;
+ int res, ix;
+
+ /* cannot divide by zero */
+ if (b == 0) {
+ return MP_VAL;
+ }
+
+ /* quick outs */
+ if (b == 1 || mp_iszero(a) == 1) {
+ if (d != NULL) {
+ *d = 0;
+ }
+ if (c != NULL) {
+ return mp_copy(a, c);
+ }
+ return MP_OKAY;
+ }
+
+ /* power of two ? */
+ if (s_is_power_of_two(b, &ix) == 1) {
+ if (d != NULL) {
+ *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+ }
+ if (c != NULL) {
+ return mp_div_2d(a, ix, c, NULL);
+ }
+ return MP_OKAY;
+ }
+
+#ifdef BN_MP_DIV_3_C
+ /* three? */
+ if (b == 3) {
+ return mp_div_3(a, c, d);
+ }
+#endif
+
+ /* no easy answer [c'est la vie]. Just division */
+ if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+ return res;
+ }
+
+ q.used = a->used;
+ q.sign = a->sign;
+ w = 0;
+ for (ix = a->used - 1; ix >= 0; ix--) {
+ w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+ if (w >= b) {
+ t = (mp_digit)(w / b);
+ w -= ((mp_word)t) * ((mp_word)b);
+ } else {
+ t = 0;
+ }
+ q.dp[ix] = (mp_digit)t;
+ }
+
+ if (d != NULL) {
+ *d = (mp_digit)w;
+ }
+
+ if (c != NULL) {
+ mp_clamp(&q);
+ mp_exch(&q, c);
+ }
+ mp_clear(&q);
+
+ return res;
+}
+
+static int
+mp_mod_d(mp_int *a, mp_digit b, mp_digit *c)
+{
+ return mp_div_d(a, b, NULL, c);
+}
+
+static const mp_digit ltm_prime_tab[] = {
+ 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+ 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+ 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+ 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+ 0x0083,
+ 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+ 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+ 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+ 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+ 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+ 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+ 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+ 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+ 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+ 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+ 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+ 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+ 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+ 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+ 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+ 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+ 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+ 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+ 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+ 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+ 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+ 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+ 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+ 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+ 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+ 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+ 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+
+#define PRIME_SIZE __arraycount(ltm_prime_tab)
+
+static int
+mp_prime_is_divisible(mp_int *a, int *result)
+{
+ int err, ix;
+ mp_digit res;
+
+ /* default to not */
+ *result = MP_NO;
+
+ for (ix = 0; ix < (int)PRIME_SIZE; ix++) {
+ /* what is a mod LBL_prime_tab[ix] */
+ if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* is the residue zero? */
+ if (res == 0) {
+ *result = MP_YES;
+ return MP_OKAY;
+ }
+ }
+
+ return MP_OKAY;
+}
+
+/* single digit addition */
+static int
+mp_add_d(mp_int *a, mp_digit b, mp_int *c)
+{
+ int res, ix, oldused;
+ mp_digit *tmpa, *tmpc, mu;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative and |a| >= b, call c = |a| - b */
+ if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+ /* temporarily fix sign of a */
+ a->sign = MP_ZPOS;
+
+ /* c = |a| - b */
+ res = mp_sub_d(a, b, c);
+
+ /* fix sign */
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* old number of used digits in c */
+ oldused = c->used;
+
+ /* sign always positive */
+ c->sign = MP_ZPOS;
+
+ /* source alias */
+ tmpa = a->dp;
+
+ /* destination alias */
+ tmpc = c->dp;
+
+ /* if a is positive */
+ if (a->sign == MP_ZPOS) {
+ /* add digit, after this we're propagating
+ * the carry.
+ */
+ *tmpc = *tmpa++ + b;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+
+ /* now handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ + mu;
+ mu = *tmpc >> DIGIT_BIT;
+ *tmpc++ &= MP_MASK;
+ }
+ /* set final carry */
+ ix++;
+ *tmpc++ = mu;
+
+ /* setup size */
+ c->used = a->used + 1;
+ } else {
+ /* a was negative and |a| < b */
+ c->used = 1;
+
+ /* the result is a single digit */
+ if (a->used == 1) {
+ *tmpc++ = b - a->dp[0];
+ } else {
+ *tmpc++ = b;
+ }
+
+ /* setup count so the clearing of oldused
+ * can fall through correctly
+ */
+ ix = 1;
+ }
+
+ /* now zero to oldused */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+
+ return MP_OKAY;
+}
+
+/* single digit subtraction */
+static int
+mp_sub_d(mp_int *a, mp_digit b, mp_int *c)
+{
+ mp_digit *tmpa, *tmpc, mu;
+ int res, ix, oldused;
+
+ /* grow c as required */
+ if (c->alloc < a->used + 1) {
+ if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+ return res;
+ }
+ }
+
+ /* if a is negative just do an unsigned
+ * addition [with fudged signs]
+ */
+ if (a->sign == MP_NEG) {
+ a->sign = MP_ZPOS;
+ res = mp_add_d(a, b, c);
+ a->sign = c->sign = MP_NEG;
+
+ /* clamp */
+ mp_clamp(c);
+
+ return res;
+ }
+
+ /* setup regs */
+ oldused = c->used;
+ tmpa = a->dp;
+ tmpc = c->dp;
+
+ /* if a <= b simply fix the single digit */
+ if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+ if (a->used == 1) {
+ *tmpc++ = b - *tmpa;
+ } else {
+ *tmpc++ = b;
+ }
+ ix = 1;
+
+ /* negative/1digit */
+ c->sign = MP_NEG;
+ c->used = 1;
+ } else {
+ /* positive/size */
+ c->sign = MP_ZPOS;
+ c->used = a->used;
+
+ /* subtract first digit */
+ *tmpc = *tmpa++ - b;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+
+ /* handle rest of the digits */
+ for (ix = 1; ix < a->used; ix++) {
+ *tmpc = *tmpa++ - mu;
+ mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+ *tmpc++ &= MP_MASK;
+ }
+ }
+
+ /* zero excess digits */
+ while (ix++ < oldused) {
+ *tmpc++ = 0;
+ }
+ mp_clamp(c);
+ return MP_OKAY;
+}
+
+static const int lnz[16] = {
+ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+static int
+mp_cnt_lsb(mp_int *a)
+{
+ int x;
+ mp_digit q, qq;
+
+ /* easy out */
+ if (mp_iszero(a) == 1) {
+ return 0;
+ }
+
+ /* scan lower digits until non-zero */
+ for (x = 0; x < a->used && a->dp[x] == 0; x++);
+ q = a->dp[x];
+ x *= DIGIT_BIT;
+
+ /* now scan this digit until a 1 is found */
+ if ((q & 1) == 0) {
+ do {
+ qq = q & 15;
+ /* LINTED previous op ensures range of qq */
+ x += lnz[qq];
+ q >>= 4;
+ } while (qq == 0);
+ }
+ return x;
+}
+
+/* c = a * a (mod b) */
+static int
+mp_sqrmod(mp_int *a, mp_int *b, mp_int *c)
+{
+ int res;
+ mp_int t;
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, b, c);
+ mp_clear (&t);
+ return res;
+}
+static int
+mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result)
+{
+ mp_int n1, y, r;
+ int s, j, err;
+
+ /* default */
+ *result = MP_NO;
+
+ /* ensure b > 1 */
+ if (mp_cmp_d(b, 1) != MP_GT) {
+ return MP_VAL;
+ }
+
+ /* get n1 = a - 1 */
+ if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* set 2**s * r = n1 */
+ if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+ goto LBL_N1;
+ }
+
+ /* count the number of least significant bits
+ * which are zero
+ */
+ s = mp_cnt_lsb(&r);
+
+ /* now divide n - 1 by 2**s */
+ if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+ goto LBL_R;
+ }
+
+ /* compute y = b**r mod a */
+ if ((err = mp_init (&y)) != MP_OKAY) {
+ goto LBL_R;
+ }
+ if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y != 1 and y != n1 do */
+ if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+ j = 1;
+ /* while j <= s-1 and y != n1 */
+ while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+ if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+ goto LBL_Y;
+ }
+
+ /* if y == 1 then composite */
+ if (mp_cmp_d (&y, 1) == MP_EQ) {
+ goto LBL_Y;
+ }
+
+ ++j;
+ }
+
+ /* if y != n1 then composite */
+ if (mp_cmp (&y, &n1) != MP_EQ) {
+ goto LBL_Y;
+ }
+ }
+
+ /* probably prime now */
+ *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+ return err;
+}
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+static int
+mp_prime_is_prime(mp_int *a, int t, int *result)
+{
+ mp_int b;
+ int ix, err, res;
+
+ /* default to no */
+ *result = MP_NO;
+
+ /* valid value of t? */
+ if (t <= 0 || t > (int)PRIME_SIZE) {
+ return MP_VAL;
+ }
+
+ /* is the input equal to one of the primes in the table? */
+ for (ix = 0; ix < (int)PRIME_SIZE; ix++) {
+ if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+ *result = 1;
+ return MP_OKAY;
+ }
+ }
+
+ /* first perform trial division */
+ if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+ return err;
+ }
+
+ /* return if it was trivially divisible */
+ if (res == MP_YES) {
+ return MP_OKAY;
+ }
+
+ /* now perform the miller-rabin rounds */
+ if ((err = mp_init (&b)) != MP_OKAY) {
+ return err;
+ }
+
+ for (ix = 0; ix < t; ix++) {
+ /* set the prime */
+ mp_set (&b, ltm_prime_tab[ix]);
+
+ if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+ goto LBL_B;
+ }
+
+ if (res == MP_NO) {
+ goto LBL_B;
+ }
+ }
+
+ /* passed the test */
+ *result = MP_YES;
+LBL_B:mp_clear (&b);
+ return err;
+}
+
+/* returns size of ASCII reprensentation */
+static int
+mp_radix_size (mp_int *a, int radix, int *size)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+
+ *size = 0;
+
+ /* special case for binary */
+ if (radix == 2) {
+ *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+ return MP_OKAY;
+ }
+
+ /* make sure the radix is in range */
+ if (radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ if (mp_iszero(a) == MP_YES) {
+ *size = 2;
+ return MP_OKAY;
+ }
+
+ /* digs is the digit count */
+ digs = 0;
+
+ /* if it's negative add one for the sign */
+ if (a->sign == MP_NEG) {
+ ++digs;
+ }
+
+ /* init a copy of the input */
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* force temp to positive */
+ t.sign = MP_ZPOS;
+
+ /* fetch out all of the digits */
+ while (mp_iszero (&t) == MP_NO) {
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ ++digs;
+ }
+ mp_clear (&t);
+
+ /* return digs + 1, the 1 is for the NULL byte that would be required. */
+ *size = digs + 1;
+ return MP_OKAY;
+}
+
+static const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+/* stores a bignum as a ASCII string in a given radix (2..64)
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte
+ */
+static int
+mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+ int res, digs;
+ mp_int t;
+ mp_digit d;
+ char *_s = str;
+
+ /* check range of the maxlen, radix */
+ if (maxlen < 2 || radix < 2 || radix > 64) {
+ return MP_VAL;
+ }
+
+ /* quick out if its zero */
+ if (mp_iszero(a) == MP_YES) {
+ *str++ = '0';
+ *str = '\0';
+ return MP_OKAY;
+ }
+
+ if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+ return res;
+ }
+
+ /* if it is negative output a - */
+ if (t.sign == MP_NEG) {
+ /* we have to reverse our digits later... but not the - sign!! */
+ ++_s;
+
+ /* store the flag and mark the number as positive */
+ *str++ = '-';
+ t.sign = MP_ZPOS;
+
+ /* subtract a char */
+ --maxlen;
+ }
+
+ digs = 0;
+ while (mp_iszero (&t) == 0) {
+ if (--maxlen < 1) {
+ /* no more room */
+ break;
+ }
+ if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ /* LINTED -- radix' range is checked above, limits d's range */
+ *str++ = mp_s_rmap[d];
+ ++digs;
+ }
+
+ /* reverse the digits of the string. In this case _s points
+ * to the first digit [exluding the sign] of the number
+ */
+ bn_reverse ((unsigned char *)_s, digs);
+
+ /* append a NULL so the string is properly terminated */
+ *str = '\0';
+
+ mp_clear (&t);
+ return MP_OKAY;
+}
+
+static char *
+formatbn(const BIGNUM *a, const int radix)
+{
+ char *s;
+ int len;
+
+ if (mp_radix_size(__UNCONST(a), radix, &len) != MP_OKAY) {
+ return NULL;
+ }
+ if ((s = netpgp_allocate(1, (size_t)len)) != NULL) {
+ if (mp_toradix_n(__UNCONST(a), s, radix, len) != MP_OKAY) {
+ netpgp_deallocate(s, (size_t)len);
+ return NULL;
+ }
+ }
+ return s;
+}
+
+static int
+mp_getradix_num(mp_int *a, int radix, char *s)
+{
+ int err, ch, neg, y;
+
+ /* clear a */
+ mp_zero(a);
+
+ /* if first digit is - then set negative */
+ if ((ch = *s++) == '-') {
+ neg = MP_NEG;
+ ch = *s++;
+ } else {
+ neg = MP_ZPOS;
+ }
+
+ for (;;) {
+ /* find y in the radix map */
+ for (y = 0; y < radix; y++) {
+ if (mp_s_rmap[y] == ch) {
+ break;
+ }
+ }
+ if (y == radix) {
+ break;
+ }
+
+ /* shift up and add */
+ if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+ return err;
+ }
+ if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+ return err;
+ }
+
+ ch = *s++;
+ }
+ if (mp_cmp_d(a, 0) != MP_EQ) {
+ a->sign = neg;
+ }
+
+ return MP_OKAY;
+}
+
+static int
+getbn(BIGNUM **a, const char *str, int radix)
+{
+ int len;
+
+ if (a == NULL || str == NULL || (*a = BN_new()) == NULL) {
+ return 0;
+ }
+ if (mp_getradix_num(*a, radix, __UNCONST(str)) != MP_OKAY) {
+ return 0;
+ }
+ mp_radix_size(__UNCONST(a), radix, &len);
+ return len - 1;
+}
+
+/* d = a - b (mod c) */
+static int
+mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
+{
+ int res;
+ mp_int t;
+
+
+ if ((res = mp_init (&t)) != MP_OKAY) {
+ return res;
+ }
+
+ if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+ mp_clear (&t);
+ return res;
+ }
+ res = mp_mod (&t, c, d);
+ mp_clear (&t);
+ return res;
+}
+
+/**************************************************************************/
+
+/* BIGNUM emulation layer */
+
+/* essentiually, these are just wrappers around the libtommath functions */
+/* usually the order of args changes */
+/* the BIGNUM API tends to have more const poisoning */
+/* these wrappers also check the arguments passed for sanity */
+
+BIGNUM *
+BN_bin2bn(const uint8_t *data, int len, BIGNUM *ret)
+{
+ if (data == NULL) {
+ return BN_new();
+ }
+ if (ret == NULL) {
+ ret = BN_new();
+ }
+ return (mp_read_unsigned_bin(ret, data, len) == MP_OKAY) ? ret : NULL;
+}
+
+/* store in unsigned [big endian] format */
+int
+BN_bn2bin(const BIGNUM *a, unsigned char *b)
+{
+ BIGNUM t;
+ int x;
+
+ if (a == NULL || b == NULL) {
+ return -1;
+ }
+ if (mp_init_copy (&t, __UNCONST(a)) != MP_OKAY) {
+ return -1;
+ }
+ for (x = 0; !BN_is_zero(&t) ; ) {
+ b[x++] = (unsigned char) (t.dp[0] & 0xff);
+ if (mp_div_2d (&t, 8, &t, NULL) != MP_OKAY) {
+ mp_clear(&t);
+ return -1;
+ }
+ }
+ bn_reverse(b, x);
+ mp_clear(&t);
+ return x;
+}
+
+void
+BN_init(BIGNUM *a)
+{
+ if (a != NULL) {
+ mp_init(a);
+ }
+}
+
+BIGNUM *
+BN_new(void)
+{
+ BIGNUM *a;
+
+ if ((a = netpgp_allocate(1, sizeof(*a))) != NULL) {
+ mp_init(a);
+ }
+ return a;
+}
+
+/* copy, b = a */
+int
+BN_copy(BIGNUM *b, const BIGNUM *a)
+{
+ if (a == NULL || b == NULL) {
+ return MP_VAL;
+ }
+ return mp_copy(__UNCONST(a), b);
+}
+
+BIGNUM *
+BN_dup(const BIGNUM *a)
+{
+ BIGNUM *ret;
+
+ if (a == NULL) {
+ return NULL;
+ }
+ if ((ret = BN_new()) != NULL) {
+ BN_copy(ret, a);
+ }
+ return ret;
+}
+
+void
+BN_swap(BIGNUM *a, BIGNUM *b)
+{
+ if (a && b) {
+ mp_exch(a, b);
+ }
+}
+
+int
+BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
+{
+ if (r == NULL || a == NULL || n < 0) {
+ return 0;
+ }
+ BN_copy(r, a);
+ return mp_lshd(r, n) == MP_OKAY;
+}
+
+int
+BN_lshift1(BIGNUM *r, BIGNUM *a)
+{
+ if (r == NULL || a == NULL) {
+ return 0;
+ }
+ BN_copy(r, a);
+ return mp_lshd(r, 1) == MP_OKAY;
+}
+
+int
+BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
+{
+ if (r == NULL || a == NULL || n < 0) {
+ return MP_VAL;
+ }
+ BN_copy(r, a);
+ return mp_rshd(r, n) == MP_OKAY;
+}
+
+int
+BN_rshift1(BIGNUM *r, BIGNUM *a)
+{
+ if (r == NULL || a == NULL) {
+ return 0;
+ }
+ BN_copy(r, a);
+ return mp_rshd(r, 1) == MP_OKAY;
+}
+
+int
+BN_set_word(BIGNUM *a, BN_ULONG w)
+{
+ if (a == NULL) {
+ return 0;
+ }
+ mp_set(a, w);
+ return 1;
+}
+
+int
+BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+ if (a == NULL || b == NULL || r == NULL) {
+ return 0;
+ }
+ return mp_add(__UNCONST(a), __UNCONST(b), r) == MP_OKAY;
+}
+
+int
+BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
+{
+ if (a == NULL || b == NULL || r == NULL) {
+ return 0;
+ }
+ return mp_sub(__UNCONST(a), __UNCONST(b), r) == MP_OKAY;
+}
+
+int
+BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
+{
+ if (a == NULL || b == NULL || r == NULL) {
+ return 0;
+ }
+ USE_ARG(ctx);
+ return mp_mul(__UNCONST(a), __UNCONST(b), r) == MP_OKAY;
+}
+
+int
+BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *a, const BIGNUM *d, BN_CTX *ctx)
+{
+ if ((dv == NULL && rem == NULL) || a == NULL || d == NULL) {
+ return 0;
+ }
+ USE_ARG(ctx);
+ return mp_div(dv, rem, __UNCONST(a), __UNCONST(d)) == MP_OKAY;
+}
+
+void
+BN_free(BIGNUM *a)
+{
+ if (a) {
+ mp_clear(a);
+ }
+}
+
+void
+BN_clear(BIGNUM *a)
+{
+ if (a) {
+ mp_clear(a);
+ }
+}
+
+void
+BN_clear_free(BIGNUM *a)
+{
+ if (a) {
+ mp_clear(a);
+ }
+}
+
+int
+BN_num_bytes(const BIGNUM *a)
+{
+ if (a == NULL) {
+ return MP_VAL;
+ }
+ return mp_unsigned_bin_size(__UNCONST(a));
+}
+
+int
+BN_num_bits(const BIGNUM *a)
+{
+ if (a == NULL) {
+ return 0;
+ }
+ return mp_count_bits(a);
+}
+
+void
+BN_set_negative(BIGNUM *a, int n)
+{
+ if (a) {
+ a->sign = (n) ? MP_NEG : 0;
+ }
+}
+
+int
+BN_cmp(BIGNUM *a, BIGNUM *b)
+{
+ if (a == NULL || b == NULL) {
+ return MP_VAL;
+ }
+ switch(mp_cmp(a, b)) {
+ case MP_LT:
+ return -1;
+ case MP_GT:
+ return 1;
+ case MP_EQ:
+ default:
+ return 0;
+ }
+}
+
+int
+BN_mod_exp(BIGNUM *Y, BIGNUM *G, BIGNUM *X, BIGNUM *P, BN_CTX *ctx)
+{
+ if (Y == NULL || G == NULL || X == NULL || P == NULL) {
+ return MP_VAL;
+ }
+ USE_ARG(ctx);
+ return mp_exptmod(G, X, P, Y) == MP_OKAY;
+}
+
+BIGNUM *
+BN_mod_inverse(BIGNUM *r, BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
+{
+ USE_ARG(ctx);
+ if (r == NULL || a == NULL || n == NULL) {
+ return NULL;
+ }
+ return (mp_invmod(r, a, __UNCONST(n)) == MP_OKAY) ? r : NULL;
+}
+
+int
+BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+{
+ USE_ARG(ctx);
+ if (ret == NULL || a == NULL || b == NULL || m == NULL) {
+ return 0;
+ }
+ return mp_mulmod(ret, a, b, __UNCONST(m)) == MP_OKAY;
+}
+
+BN_CTX *
+BN_CTX_new(void)
+{
+ return netpgp_allocate(1, sizeof(BN_CTX));
+}
+
+void
+BN_CTX_init(BN_CTX *c)
+{
+ if (c != NULL) {
+ c->arraysize = 15;
+ if ((c->v = netpgp_allocate(sizeof(*c->v), c->arraysize)) == NULL) {
+ c->arraysize = 0;
+ }
+ }
+}
+
+BIGNUM *
+BN_CTX_get(BN_CTX *ctx)
+{
+ if (ctx == NULL || ctx->v == NULL || ctx->arraysize == 0 || ctx->count == ctx->arraysize - 1) {
+ return NULL;
+ }
+ return ctx->v[ctx->count++] = BN_new();
+}
+
+void
+BN_CTX_start(BN_CTX *ctx)
+{
+ BN_CTX_init(ctx);
+}
+
+void
+BN_CTX_free(BN_CTX *c)
+{
+ unsigned i;
+
+ if (c != NULL && c->v != NULL) {
+ for (i = 0 ; i < c->count ; i++) {
+ BN_clear_free(c->v[i]);
+ }
+ netpgp_deallocate(c->v, sizeof(*c->v) * c->arraysize);
+ }
+}
+
+void
+BN_CTX_end(BN_CTX *ctx)
+{
+ BN_CTX_free(ctx);
+}
+
+char *
+BN_bn2hex(const BIGNUM *a)
+{
+ return (a == NULL) ? NULL : formatbn(a, 16);
+}
+
+char *
+BN_bn2dec(const BIGNUM *a)
+{
+ return (a == NULL) ? NULL : formatbn(a, 10);
+}
+
+#ifndef _KERNEL
+int
+BN_print_fp(FILE *fp, const BIGNUM *a)
+{
+ char *s;
+ int ret;
+
+ if (fp == NULL || a == NULL) {
+ return 0;
+ }
+ s = BN_bn2hex(a);
+ ret = fprintf(fp, "%s", s);
+ netpgp_deallocate(s, strlen(s) + 1);
+ return ret;
+}
+#endif
+
+int
+BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
+{
+ uint64_t r;
+ int digits;
+ int i;
+
+ if (rnd == NULL) {
+ return 0;
+ }
+ mp_init_size(rnd, digits = howmany(bits, DIGIT_BIT));
+ for (i = 0 ; i < digits ; i++) {
+ r = (uint64_t)arc4random();
+ r <<= 32;
+ r |= arc4random();
+ rnd->dp[i] = (r & MP_MASK);
+ }
+ if (top == 0) {
+ rnd->dp[rnd->used - 1] |= (((mp_digit)1)<<((mp_digit)DIGIT_BIT));
+ }
+ if (top == 1) {
+ rnd->dp[rnd->used - 1] |= (((mp_digit)1)<<((mp_digit)DIGIT_BIT));
+ rnd->dp[rnd->used - 1] |= (((mp_digit)1)<<((mp_digit)(DIGIT_BIT - 1)));
+ }
+ if (bottom) {
+ rnd->dp[0] |= 0x1;
+ }
+ return 1;
+}
+
+int
+BN_rand_range(BIGNUM *rnd, BIGNUM *range)
+{
+ if (rnd == NULL || range == NULL || BN_is_zero(range)) {
+ return 0;
+ }
+ BN_rand(rnd, BN_num_bits(range), 1, 0);
+ return mp_mod(rnd, range, rnd) == MP_OKAY;
+}
+
+int
+BN_is_prime(const BIGNUM *a, int checks, void (*callback)(int, int, void *), BN_CTX *ctx, void *cb_arg)
+{
+ int primality;
+
+ if (a == NULL) {
+ return 0;
+ }
+ USE_ARG(ctx);
+ USE_ARG(cb_arg);
+ USE_ARG(callback);
+ return (mp_prime_is_prime(__UNCONST(a), checks, &primality) == MP_OKAY) ? primality : 0;
+}
+
+const BIGNUM *
+BN_value_one(void)
+{
+ static mp_digit digit = 1UL;
+ static const BIGNUM one = { &digit, 1, 1, 0 };
+
+ return &one;
+}
+
+int
+BN_hex2bn(BIGNUM **a, const char *str)
+{
+ return getbn(a, str, 16);
+}
+
+int
+BN_dec2bn(BIGNUM **a, const char *str)
+{
+ return getbn(a, str, 10);
+}
+
+int
+BN_mod_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+{
+ USE_ARG(ctx);
+ if (r == NULL || a == NULL || b == NULL || m == NULL) {
+ return 0;
+ }
+ return mp_submod(a, b, __UNCONST(m), r) == MP_OKAY;
+}
+
+int
+BN_is_bit_set(const BIGNUM *a, int n)
+{
+ if (a == NULL || n < 0 || n >= a->used * DIGIT_BIT) {
+ return 0;
+ }
+ return (a->dp[n / DIGIT_BIT] & (1 << (n % DIGIT_BIT))) ? 1 : 0;
+}
diff --git a/security/libnetpgpverify/files/src/libbn/bn.h b/security/libnetpgpverify/files/src/libbn/bn.h
new file mode 100644
index 00000000000..fdc49d8760a
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/bn.h
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef FAUXBN_H_
+#define FAUXBN_H_ 20100108
+
+#include <sys/types.h>
+
+#ifndef _KERNEL
+# include <inttypes.h>
+# include <stdio.h>
+#endif
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+/* should be 32bit on ILP32, 64bit on LP64 */
+typedef unsigned long mp_digit;
+typedef uint64_t mp_word;
+
+/* multi-precision integer */
+typedef struct mp_int {
+ mp_digit *dp; /* array of digits */
+ int used; /* # of digits used */
+ int alloc; /* # of digits allocated */
+ int sign; /* non-zero if negative */
+} mp_int;
+
+#define BIGNUM mp_int
+#define BN_ULONG mp_digit
+
+/* a "context" of mp integers - never really used */
+typedef struct bn_ctx_t {
+ size_t count;
+ size_t arraysize;
+ BIGNUM **v;
+} BN_CTX;
+
+#define MP_LT -1
+#define MP_EQ 0
+#define MP_GT 1
+
+#define MP_ZPOS 0
+#define MP_NEG 1
+
+#define MP_OKAY 0
+#define MP_MEM -2
+#define MP_VAL -3
+#define MP_RANGE MP_VAL
+
+/*********************************/
+
+#define BN_is_negative(x) ((x)->sign == MP_NEG)
+#define BN_is_zero(a) (((a)->used == 0) ? 1 : 0)
+#define BN_is_odd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? 1 : 0)
+#define BN_is_even(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? 1 : 0)
+
+BIGNUM *BN_new(void);
+BIGNUM *BN_dup(const BIGNUM */*a*/);
+int BN_copy(BIGNUM */*b*/, const BIGNUM */*a*/);
+
+void BN_init(BIGNUM */*a*/);
+void BN_free(BIGNUM */*a*/);
+void BN_clear(BIGNUM */*a*/);
+void BN_clear_free(BIGNUM */*a*/);
+
+int BN_cmp(BIGNUM */*a*/, BIGNUM */*b*/);
+
+BIGNUM *BN_bin2bn(const uint8_t */*buf*/, int /*size*/, BIGNUM */*bn*/);
+int BN_bn2bin(const BIGNUM */*a*/, unsigned char */*b*/);
+char *BN_bn2hex(const BIGNUM */*a*/);
+char *BN_bn2dec(const BIGNUM */*a*/);
+int BN_hex2bn(BIGNUM **/*a*/, const char */*str*/);
+int BN_dec2bn(BIGNUM **/*a*/, const char */*str*/);
+#ifndef _KERNEL
+int BN_print_fp(FILE */*fp*/, const BIGNUM */*a*/);
+#endif
+
+int BN_add(BIGNUM */*r*/, const BIGNUM */*a*/, const BIGNUM */*b*/);
+int BN_sub(BIGNUM */*r*/, const BIGNUM */*a*/, const BIGNUM */*b*/);
+int BN_mul(BIGNUM */*r*/, const BIGNUM */*a*/, const BIGNUM */*b*/, BN_CTX */*ctx*/);
+int BN_div(BIGNUM */*q*/, BIGNUM */*r*/, const BIGNUM */*a*/, const BIGNUM */*b*/, BN_CTX */*ctx*/);
+void BN_swap(BIGNUM */*a*/, BIGNUM */*b*/);
+int BN_lshift(BIGNUM */*r*/, const BIGNUM */*a*/, int /*n*/);
+int BN_lshift1(BIGNUM */*r*/, BIGNUM */*a*/);
+int BN_rshift(BIGNUM */*r*/, const BIGNUM */*a*/, int /*n*/);
+int BN_rshift1(BIGNUM */*r*/, BIGNUM */*a*/);
+int BN_set_word(BIGNUM */*a*/, BN_ULONG /*w*/);
+void BN_set_negative(BIGNUM */*a*/, int /*n*/);
+
+int BN_num_bytes(const BIGNUM */*a*/);
+int BN_num_bits(const BIGNUM */*a*/);
+
+int BN_mod_exp(BIGNUM */*r*/, BIGNUM */*a*/, BIGNUM */*p*/, BIGNUM */*m*/, BN_CTX */*ctx*/);
+BIGNUM *BN_mod_inverse(BIGNUM */*ret*/, BIGNUM */*a*/, const BIGNUM */*n*/, BN_CTX */*ctx*/);
+int BN_mod_mul(BIGNUM */*ret*/, BIGNUM */*a*/, BIGNUM */*b*/, const BIGNUM */*m*/, BN_CTX */*ctx*/);
+int BN_mod_sub(BIGNUM */*r*/, BIGNUM */*a*/, BIGNUM */*b*/, const BIGNUM */*m*/, BN_CTX */*ctx*/);
+
+BN_CTX *BN_CTX_new(void);
+BIGNUM *BN_CTX_get(BN_CTX */*ctx*/);
+void BN_CTX_start(BN_CTX */*ctx*/);
+void BN_CTX_end(BN_CTX */*ctx*/);
+void BN_CTX_init(BN_CTX */*c*/);
+void BN_CTX_free(BN_CTX */*c*/);
+
+int BN_rand(BIGNUM */*rnd*/, int /*bits*/, int /*top*/, int /*bottom*/);
+int BN_rand_range(BIGNUM */*rnd*/, BIGNUM */*range*/);
+
+int BN_is_prime(const BIGNUM */*a*/, int /*checks*/, void (*callback)(int, int, void *), BN_CTX */*ctx*/, void */*cb_arg*/);
+
+const BIGNUM *BN_value_one(void);
+int BN_is_bit_set(const BIGNUM */*a*/, int /*n*/);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libbn/libnetpgpbn.3 b/security/libnetpgpverify/files/src/libbn/libnetpgpbn.3
new file mode 100644
index 00000000000..29134ca7b77
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/libnetpgpbn.3
@@ -0,0 +1,304 @@
+.\" $NetBSD: libnetpgpbn.3,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+.\"
+.\" Copyright (c) 2010 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.
+.\"
+.Dd April 13, 2012
+.Dt LIBNETPGPBN 3
+.Os
+.Sh NAME
+.Nm libnetpgpbn
+.Nd BIGNUM library of multi-precision integers
+.Sh LIBRARY
+.Lb libnetpgpbn
+.Sh SYNOPSIS
+.In netpgp/bn.h
+.Ft BIGNUM *
+.Fo BN_new
+.Fa "void"
+.Fc
+.Ft BIGNUM *
+.Fo BN_dup
+.Fa "const BIGNUM *orig"
+.Fc
+.Ft int
+.Fo BN_copy
+.Fa "BIGNUM *to" "const BIGNUM *from"
+.Fc
+.Ft void
+.Fo BN_swap
+.Fa "BIGNUM *a" "BIGNUM *b"
+.Fc
+.Pp
+.Ft void
+.Fo BN_init
+.Fa "BIGNUM *bn"
+.Fc
+.Ft void
+.Fo BN_free
+.Fa "BIGNUM *bn"
+.Fc
+.Ft void
+.Fo BN_clear
+.Fa "BIGNUM *bn"
+.Fc
+.Ft void
+.Fo BN_clear_free
+.Fa "BIGNUM *bn"
+.Fc
+.Pp
+.Ft void
+.Fo BN_clear_free
+.Fa "BIGNUM *bn"
+.Fc
+.Pp
+.Ft int
+.Fo BN_cmp
+.Fa "BIGNUM *lhs" "BIGNUM *rhs"
+.Fc
+.Ft int
+.Fo BN_is_negative
+.Fa "BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_is_zero
+.Fa "BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_is_odd
+.Fa "BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_is_even
+.Fa "BIGNUM *bn"
+.Fc
+.Pp
+.Ft BIGNUM *
+.Fo BN_bin2bn
+.Fa "const uint8_t *buf" "int size" "BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_bn2bin
+.Fa "BIGNUM *bn" "uint8_t *buf"
+.Fc
+.Ft int
+.Fo BN_bn2bin
+.Fa "BIGNUM *bn" "uint8_t *buf"
+.Fc
+.Ft char *
+.Fo BN_bn2hex
+.Fa "const BIGNUM *bn"
+.Fc
+.Ft char *
+.Fo BN_bn2dec
+.Fa "const BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_hex2bn
+.Fa "BIGNUM **bn" "const char *str"
+.Fc
+.Ft int
+.Fo BN_dec2bn
+.Fa "BIGNUM **bn" "const char *str"
+.Fc
+.Ft int
+.Fo BN_print_fp
+.Fa "FILE *fp" "const BIGNUM *bn"
+.Fc
+.Pp
+.Ft int
+.Fo BN_add
+.Fa "BIGNUM *sum" "const BIGNUM *a" "const BIGNUM *b"
+.Fc
+.Ft int
+.Fo BN_sub
+.Fa "BIGNUM *sum" "const BIGNUM *a" "const BIGNUM *b"
+.Fc
+.Ft int
+.Fo BN_mul
+.Fa "BIGNUM *product" "const BIGNUM *a" "const BIGNUM *b" "BN_CTX *context"
+.Fc
+.Ft int
+.Fo BN_div
+.Fa "BIGNUM *quotient" "BIGNUM *remainder" "const BIGNUM *a" "const BIGNUM *b" "BN_CTX *context"
+.Fc
+.Pp
+.Ft int
+.Fo BN_lshift
+.Fa "BIGNUM *result" "const BIGNUM *bn" "int n"
+.Fc
+.Ft int
+.Fo BN_lshift1
+.Fa "BIGNUM *result" "const BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_rshift
+.Fa "BIGNUM *result" "const BIGNUM *bn" "int n"
+.Fc
+.Ft int
+.Fo BN_rshift1
+.Fa "BIGNUM *result" "const BIGNUM *bn"
+.Fc
+.Pp
+.Ft int
+.Fo BN_set_word
+.Fa "BIGNUM *result" "unsigned long val"
+.Fc
+.Ft int
+.Fo BN_set_negative
+.Fa "BIGNUM *result" "int val"
+.Fc
+.Pp
+.Ft int
+.Fo BN_num_bytes
+.Fa "const BIGNUM *bn"
+.Fc
+.Ft int
+.Fo BN_num_bits
+.Fa "const BIGNUM *bn"
+.Fc
+.Pp
+.Ft int
+.Fo BN_mod_exp
+.Fa "BIGNUM *result" "BIGNUM *a" "BIGNUM *p" "BIGNUM *m" "BN_CTX *context"
+.Fc
+.Ft BIGNUM *
+.Fo BN_mod_inverse
+.Fa "BIGNUM *result" "BIGNUM *a" "BIGNUM *n" "BN_CTX *context"
+.Fc
+.Ft int
+.Fo BN_mod_mul
+.Fa "BIGNUM *result" "BIGNUM *a" "BIGNUM *b" "BIGNUM *m" "BN_CTX *context"
+.Fc
+.Ft int
+.Fo BN_mod_sub
+.Fa "BIGNUM *result" "BIGNUM *a" "BIGNUM *b" "BIGNUM *m" "BN_CTX *context"
+.Fc
+.Pp
+.Ft BN_CTX *
+.Fo BN_CTX_new
+.Fa "void"
+.Fc
+.Ft BIGNUM *
+.Fo BN_CTX_get
+.Fa "BN_CTX *context"
+.Fc
+.Ft void
+.Fo BN_CTX_start
+.Fa "BN_CTX *context"
+.Fc
+.Ft void
+.Fo BN_CTX_end
+.Fa "BN_CTX *context"
+.Fc
+.Ft void
+.Fo BN_CTX_init
+.Fa "BN_CTX *context"
+.Fc
+.Ft void
+.Fo BN_CTX_free
+.Fa "BN_CTX *context"
+.Fc
+.Ft int
+.Fo BN_rand
+.Fa "BIGNUM *result" "int bits" "int top" "int bottom"
+.Fc
+.Ft int
+.Fo BN_rand_range
+.Fa "BIGNUM *result" "BIGNUM *range"
+.Fc
+.Ft int
+.Fo BN_is_prime
+.Fa "const BIGNUM *bn" "int checks" "void (*callback)(int int void)"
+.Fa "BN_CTX *context" "void *callbackarg"
+.Fc
+.Pp
+.Ft const BIGNUM *
+.Fo BN_value_one
+.Fa "void"
+.Fc
+.Ft int
+.Fo BN_is_bit_set
+.Fa "const BIGNUM *bn" "int n"
+.Fc
+.Sh DESCRIPTION
+.Nm
+emulates the API of the openssl
+.Xr bn 3
+library.
+It is implemented using Tom St Denis
+.Dq libtommath
+library.
+.Sh EXAMPLES
+The follow code fragment will make a JSON object
+out of the string
+.Dq Hello <USERNAME>\en
+in the
+buffer called
+.Dq buf
+where
+.Dq USERNAME
+is the name of the user taken from the runtime environment.
+The encoded text will be in an allocated buffer called
+.Dq s
+.Bd -literal -offset indent
+mj_t atom;
+char buf[BUFSIZ];
+char *s;
+int cc;
+
+(void) memset(\*[Am]atom, 0x0, sizeof(atom));
+cc = snprintf(buf, sizeof(buf), "Hello %s\en", getenv("USER"));
+mj_create(\*[Am]atom, "string", buf, cc);
+cc = mj_asprint(\*[Am]s, \*[Am]atom, MJ_JSON_ENCODE);
+.Ed
+.Pp
+and the following example will take the (binary) text which has been encoded into
+JSON and is in the buffer
+.Dq buf ,
+such as in the previous example, and re-create the original text:
+.Bd -literal -offset indent
+int from, to, tok, cc;
+char *s;
+mj_t atom;
+
+(void) memset(\*[Am]atom, 0x0, sizeof(atom));
+from = to = tok = 0;
+mj_parse(\*[Am]atom, buf, \*[Am]from, \*[Am]to, \*[Am]tok);
+cc = mj_asprint(\*[Am]s, \*[Am]atom, MJ_HUMAN);
+printf("%.*s", cc, s);
+.Ed
+.Pp
+The
+.Dv s
+pointer points to allocated storage with the original NUL-terminated string
+in it.
+.Sh SEE ALSO
+.Xr bn 3
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Nx 7.0 .
+.Sh AUTHORS
+.An Alistair Crooks Aq agc@NetBSD.org
diff --git a/security/libnetpgpverify/files/src/libbn/misc.c b/security/libnetpgpverify/files/src/libbn/misc.c
new file mode 100644
index 00000000000..b3bb5ea68f8
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/misc.c
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/syslog.h>
+
+#ifdef _KERNEL
+# include <sys/kmem.h>
+#else
+# include <ctype.h>
+# include <inttypes.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <unistd.h>
+#endif
+
+#include "misc.h"
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+void *
+netpgp_allocate(size_t n, size_t nels)
+{
+#ifdef _KERNEL
+ return kmem_zalloc(n * nels, KM_SLEEP);
+#else
+ return calloc(n, nels);
+#endif
+}
+
+void
+netpgp_deallocate(void *ptr, size_t size)
+{
+#ifdef _KERNEL
+ kmem_free(ptr, size);
+#else
+ USE_ARG(size);
+ free(ptr);
+#endif
+}
+
+#ifndef _KERNEL
+void
+logmessage(const int level, const char *fmt, ...)
+{
+ va_list args;
+
+ USE_ARG(level);
+ if (fmt != NULL) {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ }
+}
+#endif
diff --git a/security/libnetpgpverify/files/src/libbn/misc.h b/security/libnetpgpverify/files/src/libbn/misc.h
new file mode 100644
index 00000000000..dbace86fdcf
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/misc.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef MISC_H_
+#define MISC_H_ 20110705
+
+#include <sys/types.h>
+
+#include <inttypes.h>
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+void *netpgp_allocate(size_t /*n*/, size_t /*nels*/);
+void netpgp_deallocate(void */*ptr*/, size_t /*size*/);
+
+#ifndef _KERNEL
+void logmessage(const int /*level*/, const char */*fmt*/, ...);
+#endif
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libbn/rand.c b/security/libnetpgpverify/files/src/libbn/rand.c
new file mode 100644
index 00000000000..d2bcc1196e6
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/rand.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef _KERNEL
+# include <sys/kmem.h>
+#else
+# include <arpa/inet.h>
+# include <ctype.h>
+# include <inttypes.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <unistd.h>
+#endif
+
+#include "rand.h"
+
+int
+RAND_bytes(unsigned char *buf, int num)
+{
+ uint32_t r;
+ size_t cc;
+ int i;
+
+ if (buf == NULL || num < 0) {
+ return 0;
+ }
+ for (i = 0 ; i < num ; i += sizeof(r)) {
+ r = arc4random();
+ cc = MIN(sizeof(r), (size_t)(num - i));
+ (void) memcpy(&buf[i], &r, cc);
+ }
+ return 1;
+}
diff --git a/security/libnetpgpverify/files/src/libbn/rand.h b/security/libnetpgpverify/files/src/libbn/rand.h
new file mode 100644
index 00000000000..c2bdc950149
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/rand.h
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef RAND_H_
+#define RAND_H_ 20120327
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+int RAND_bytes(unsigned char */*buf*/, int /*len*/);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libbn/stubs.c b/security/libnetpgpverify/files/src/libbn/stubs.c
new file mode 100644
index 00000000000..5e78fab880b
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/stubs.c
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef _KERNEL
+# include <sys/kmem.h>
+#else
+# include <arpa/inet.h>
+# include <ctype.h>
+# include <inttypes.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <unistd.h>
+#endif
+
+#include "misc.h"
+#include "bn.h"
+
+#include "stubs.h"
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+void
+OpenSSL_add_all_algorithms(void)
+{
+}
+
+void
+OPENSSL_add_all_algorithms_noconf(void)
+{
+}
+
+void
+CRYPTO_cleanup_all_ex_data(void)
+{
+}
+
+BIO *
+BIO_new_fd(int fd, int close_flag)
+{
+ USE_ARG(fd);
+ USE_ARG(close_flag);
+ return NULL;
+}
+
+unsigned long
+ERR_get_error(void)
+{
+ return 0;
+}
+
+char *
+ERR_error_string(unsigned long e, char *buf)
+{
+ static char staticbuf[120];
+
+ if (buf == NULL) {
+ buf = staticbuf;
+ }
+ snprintf(buf, 120, "error:%lu:netssl:[unknown function]:[unknown error]", e);
+ return buf;
+}
+
+void
+ERR_remove_state(unsigned long pid)
+{
+ USE_ARG(pid);
+}
+
+void
+ERR_print_errors(BIO *bp)
+{
+ USE_ARG(bp);
+}
+
+void
+idea_set_encrypt_key(uint8_t *key, IDEA_KEY_SCHEDULE *ks)
+{
+ printf("idea_set_encrypt_key stubbed\n");
+ USE_ARG(key);
+ USE_ARG(ks);
+}
+
+void
+idea_set_decrypt_key(IDEA_KEY_SCHEDULE *encrypt_ks, IDEA_KEY_SCHEDULE *decrypt_ks)
+{
+ printf("idea_set_decrypt_key stubbed\n");
+ USE_ARG(encrypt_ks);
+ USE_ARG(decrypt_ks);
+}
+
+void
+idea_cfb64_encrypt(uint8_t *in, uint8_t *out, long length, des_key_schedule *ks, des_cblock *ivec, int *num, int enc)
+{
+ printf("idea_cfb64_encrypt stubbed\n");
+ USE_ARG(in);
+ USE_ARG(out);
+ USE_ARG(length);
+ USE_ARG(ks);
+ USE_ARG(ivec);
+ USE_ARG(num);
+ USE_ARG(enc);
+}
+
+void
+idea_ecb_encrypt(uint8_t *in, uint8_t *out, IDEA_KEY_SCHEDULE *ks)
+{
+ printf("idea_cfb64_decrypt stubbed\n");
+ USE_ARG(in);
+ USE_ARG(out);
+ USE_ARG(ks);
+}
+
+int
+Camellia_set_key(const unsigned char *userKey, const int bits, CAMELLIA_KEY *key)
+{
+ printf("Camellia_set_key stubbed\n");
+ USE_ARG(userKey);
+ USE_ARG(bits);
+ USE_ARG(key);
+ return 0;
+}
+
+void
+Camellia_encrypt(const unsigned char *in, unsigned char *out, const CAMELLIA_KEY *key)
+{
+ printf("Camellia_encrypt stubbed\n");
+ USE_ARG(in);
+ USE_ARG(out);
+ USE_ARG(key);
+}
+
+void
+Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, const CAMELLIA_KEY *key, unsigned char *ivec, int *num, const int enc)
+{
+ printf("Camellia_cfb128_encrypt stubbed\n");
+ USE_ARG(in);
+ USE_ARG(out);
+ USE_ARG(length);
+ USE_ARG(key);
+ USE_ARG(ivec);
+ USE_ARG(num);
+ USE_ARG(enc);
+}
+
+void
+Camellia_decrypt(const unsigned char *in, unsigned char *out, const CAMELLIA_KEY *key)
+{
+ printf("Camellia_decrypt stubbed\n");
+ USE_ARG(in);
+ USE_ARG(out);
+ USE_ARG(key);
+}
+
+int
+DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule)
+{
+ printf("DES_set_key stubbed\n");
+ USE_ARG(key);
+ USE_ARG(schedule);
+ return 0;
+}
+
+void
+DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, DES_key_schedule *ks1,DES_key_schedule *ks2, DES_key_schedule *ks3, int enc)
+{
+ printf("DES_ecb3_encrypt stubbed\n");
+ USE_ARG(input);
+ USE_ARG(output);
+ USE_ARG(ks1);
+ USE_ARG(ks2);
+ USE_ARG(ks3);
+ USE_ARG(enc);
+}
+
+void
+DES_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out, long length,DES_key_schedule *ks1, DES_key_schedule *ks2,DES_key_schedule *ks3, DES_cblock *ivec,int *num,int enc)
+{
+ printf("DES_ede3_cfb64_encrypt stubbed\n");
+ USE_ARG(in);
+ USE_ARG(out);
+ USE_ARG(length);
+ USE_ARG(ks1);
+ USE_ARG(ks2);
+ USE_ARG(ks3);
+ USE_ARG(ivec);
+ USE_ARG(num);
+ USE_ARG(enc);
+}
diff --git a/security/libnetpgpverify/files/src/libbn/stubs.h b/security/libnetpgpverify/files/src/libbn/stubs.h
new file mode 100644
index 00000000000..6441b22606c
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libbn/stubs.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef STUBS_H_
+#define STUBS_H_ 20120327
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+/*********************************/
+/* stubs */
+/*********************************/
+
+void OpenSSL_add_all_algorithms(void);
+void OPENSSL_add_all_algorithms_noconf(void);
+void CRYPTO_cleanup_all_ex_data(void);
+
+#include <stdio.h>
+
+#define BIO FILE
+
+BIO *BIO_new_fd(int /*fd*/, int /*close_flag*/);
+
+unsigned long ERR_get_error(void);
+char *ERR_error_string(unsigned long /*e*/, char */*buf*/);
+void ERR_remove_state(unsigned long /*pid*/);
+void ERR_print_errors(BIO */*bp*/);
+
+#define IDEA_KEY_SCHEDULE void
+#define des_key_schedule void
+#define des_cblock void
+#define IDEA_DECRYPT 0
+#define IDEA_ENCRYPT 1
+#define IDEA_BLOCK 8
+#define IDEA_KEY_LENGTH 16
+
+void idea_set_encrypt_key(uint8_t *key, IDEA_KEY_SCHEDULE *ks);
+void idea_set_decrypt_key(IDEA_KEY_SCHEDULE *encrypt_ks, IDEA_KEY_SCHEDULE *decrypt_ks);
+void idea_cfb64_encrypt(uint8_t *in, uint8_t *out, long length, des_key_schedule *ks, des_cblock *ivec, int *num, int enc);
+void idea_ecb_encrypt(uint8_t *in, uint8_t *out, IDEA_KEY_SCHEDULE *ks);
+
+#define CAMELLIA_KEY void
+#define CAMELLIA_DECRYPT 0
+#define CAMELLIA_ENCRYPT 1
+#define CAMELLIA_BLOCK_SIZE 16
+
+int Camellia_set_key(const unsigned char *userKey, const int bits, CAMELLIA_KEY *key);
+void Camellia_encrypt(const unsigned char *in, unsigned char *out, const CAMELLIA_KEY *key);
+void Camellia_cfb128_encrypt(const unsigned char *in, unsigned char *out, size_t length, const CAMELLIA_KEY *key, unsigned char *ivec, int *num, const int enc);
+void Camellia_decrypt(const unsigned char *in, unsigned char *out, const CAMELLIA_KEY *key);
+
+#define const_DES_cblock void
+#define DES_cblock void
+#define DES_key_schedule void
+#define DES_DECRYPT 0
+#define DES_ENCRYPT 1
+
+int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule);
+void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output, DES_key_schedule *ks1,DES_key_schedule *ks2, DES_key_schedule *ks3, int enc);
+void DES_ede3_cfb64_encrypt(const unsigned char *in,unsigned char *out, long length,DES_key_schedule *ks1, DES_key_schedule *ks2,DES_key_schedule *ks3, DES_cblock *ivec,int *num,int enc);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libdigest/Makefile b/security/libnetpgpverify/files/src/libdigest/Makefile
new file mode 100644
index 00000000000..4226113735f
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libdigest/Makefile
@@ -0,0 +1,16 @@
+LIB=netdigest
+SRCS= tiger.c digest.c
+MKMAN=no
+WARNS=4
+CPPFLAGS+=-I${EXTDIST}
+
+INCS=digest.h tiger.h
+INCSDIR=/usr/include/netpgp
+EXTDIST=${.CURDIR}
+
+.include <bsd.lib.mk>
+
+.if ${HAVE_GCC} >= 45
+#COPTS.isns_pdu.c+= -fno-strict-aliasing
+CPPFLAGS+= -fno-strict-aliasing
+.endif
diff --git a/security/libnetpgpverify/files/src/libdigest/digest.c b/security/libnetpgpverify/files/src/libdigest/digest.c
new file mode 100644
index 00000000000..8b30da7ebd5
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libdigest/digest.c
@@ -0,0 +1,383 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/syslog.h>
+
+#ifdef _KERNEL
+# include <sys/md5.h>
+# include <sys/sha1.h>
+# include <sys/sha2.h>
+# include <sys/rmd160.h>
+# include <sys/kmem.h>
+#else
+# include <arpa/inet.h>
+# include <ctype.h>
+# include <inttypes.h>
+# include <md5.h>
+# include <rmd160.h>
+# include <sha1.h>
+# include <sha2.h>
+# include <stdarg.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <time.h>
+# include <unistd.h>
+#endif
+
+#include "digest.h"
+
+static uint8_t prefix_md5[] = {
+ 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
+};
+
+static uint8_t prefix_sha1[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
+ 0x1A, 0x05, 0x00, 0x04, 0x14
+};
+
+static uint8_t prefix_sha256[] = {
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+ 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+};
+
+static uint64_t prefix_tiger[] = {
+ 0x0123456789ABCDEFLL,
+ 0xFEDCBA9876543210LL,
+ 0xF096A5B4C3B2E187LL
+};
+
+static uint8_t prefix_rmd160[] = {
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24,
+ 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14
+};
+
+static uint8_t prefix_sha512[] = {
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+ 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
+};
+
+#define V4_SIGNATURE 4
+
+/*************************************************************************/
+
+void
+MD5_Init(MD5_CTX *context)
+{
+ if (context) {
+ MD5Init(context);
+ }
+}
+
+void
+MD5_Update(MD5_CTX *context, const unsigned char *data, unsigned int len)
+{
+ if (context && data) {
+ MD5Update(context, data, len);
+ }
+}
+
+void
+MD5_Final(unsigned char digest[16], MD5_CTX *context)
+{
+ if (digest && context) {
+ MD5Final(digest, context);
+ }
+}
+
+void
+SHA1_Init(SHA1_CTX *context)
+{
+ if (context) {
+ SHA1Init(context);
+ }
+}
+
+void
+SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len)
+{
+ if (context && data) {
+ SHA1Update(context, data, len);
+ }
+}
+
+void
+SHA1_Final(unsigned char digest[20], SHA1_CTX *context)
+{
+ if (digest && context) {
+ SHA1Final(digest, context);
+ }
+}
+
+void
+RMD160_Init(RMD160_CTX *context)
+{
+ if (context) {
+ RMD160Init(context);
+ }
+}
+
+void
+RMD160_Update(RMD160_CTX *context, const unsigned char *data, unsigned int len)
+{
+ if (context && data) {
+ RMD160Update(context, data, len);
+ }
+}
+
+void
+RMD160_Final(unsigned char digest[20], RMD160_CTX *context)
+{
+ if (context && digest) {
+ RMD160Final(digest, context);
+ }
+}
+
+
+/* algorithm size (raw) */
+int
+digest_alg_size(unsigned alg)
+{
+ switch(alg) {
+ case MD5_HASH_ALG:
+ return 16;
+ case SHA1_HASH_ALG:
+ return 20;
+ case RIPEMD_HASH_ALG:
+ return RMD160_DIGEST_LENGTH;
+ case SHA256_HASH_ALG:
+ return 32;
+ case SHA512_HASH_ALG:
+ return 64;
+ case TIGER_HASH_ALG:
+ case TIGER2_HASH_ALG:
+ return TIGER_DIGEST_LENGTH;
+ default:
+ printf("hash_any: bad algorithm\n");
+ return 0;
+ }
+}
+
+/* initialise the hash structure */
+int
+digest_init(digest_t *hash, const uint32_t hashalg)
+{
+ if (hash == NULL) {
+ return 0;
+ }
+ switch(hash->alg = hashalg) {
+ case MD5_HASH_ALG:
+ MD5Init(&hash->u.md5ctx);
+ hash->size = 16;
+ hash->prefix = prefix_md5;
+ hash->len = sizeof(prefix_md5);
+ hash->ctx = &hash->u.md5ctx;
+ return 1;
+ case SHA1_HASH_ALG:
+ SHA1Init(&hash->u.sha1ctx);
+ hash->size = 20;
+ hash->prefix = prefix_sha1;
+ hash->len = sizeof(prefix_sha1);
+ hash->ctx = &hash->u.sha1ctx;
+ return 1;
+ case RIPEMD_HASH_ALG:
+ RMD160Init(&hash->u.rmd160ctx);
+ hash->size = 20;
+ hash->prefix = prefix_rmd160;
+ hash->len = sizeof(prefix_rmd160);
+ hash->ctx = &hash->u.rmd160ctx;
+ return 1;
+ case SHA256_HASH_ALG:
+ SHA256_Init(&hash->u.sha256ctx);
+ hash->size = 32;
+ hash->prefix = prefix_sha256;
+ hash->len = sizeof(prefix_sha256);
+ hash->ctx = &hash->u.sha256ctx;
+ return 1;
+ case SHA512_HASH_ALG:
+ SHA512_Init(&hash->u.sha512ctx);
+ hash->size = 64;
+ hash->prefix = prefix_sha512;
+ hash->len = sizeof(prefix_sha512);
+ hash->ctx = &hash->u.sha512ctx;
+ return 1;
+ case TIGER_HASH_ALG:
+ TIGER_Init(&hash->u.tigerctx);
+ hash->size = TIGER_DIGEST_LENGTH;
+ hash->prefix = prefix_tiger;
+ hash->len = sizeof(prefix_tiger);
+ hash->ctx = &hash->u.tigerctx;
+ return 1;
+ case TIGER2_HASH_ALG:
+ TIGER2_Init(&hash->u.tigerctx);
+ hash->size = TIGER_DIGEST_LENGTH;
+ hash->prefix = prefix_tiger;
+ hash->len = sizeof(prefix_tiger);
+ hash->ctx = &hash->u.tigerctx;
+ return 1;
+ default:
+ printf("hash_any: bad algorithm\n");
+ return 0;
+ }
+}
+
+typedef struct rec_t {
+ const char *s;
+ const unsigned alg;
+} rec_t;
+
+static rec_t hashalgs[] = {
+ { "md5", MD5_HASH_ALG },
+ { "sha1", SHA1_HASH_ALG },
+ { "ripemd", RIPEMD_HASH_ALG },
+ { "sha256", SHA256_HASH_ALG },
+ { "sha512", SHA512_HASH_ALG },
+ { "tiger", TIGER_HASH_ALG },
+ { "tiger2", TIGER2_HASH_ALG },
+ { NULL, 0 }
+};
+
+/* initialise by string alg name */
+unsigned
+digest_get_alg(const char *hashalg)
+{
+ rec_t *r;
+
+ for (r = hashalgs ; hashalg && r->s ; r++) {
+ if (strcasecmp(r->s, hashalg) == 0) {
+ return r->alg;
+ }
+ }
+ return 0;
+}
+
+int
+digest_update(digest_t *hash, const uint8_t *data, size_t length)
+{
+ if (hash == NULL || data == NULL) {
+ return 0;
+ }
+ switch(hash->alg) {
+ case MD5_HASH_ALG:
+ MD5Update(hash->ctx, data, (unsigned)length);
+ return 1;
+ case SHA1_HASH_ALG:
+ SHA1Update(hash->ctx, data, (unsigned)length);
+ return 1;
+ case RIPEMD_HASH_ALG:
+ RMD160Update(hash->ctx, data, (unsigned)length);
+ return 1;
+ case SHA256_HASH_ALG:
+ SHA256_Update(hash->ctx, data, length);
+ return 1;
+ case SHA512_HASH_ALG:
+ SHA512_Update(hash->ctx, data, length);
+ return 1;
+ case TIGER_HASH_ALG:
+ case TIGER2_HASH_ALG:
+ TIGER_Update(hash->ctx, data, length);
+ return 1;
+ default:
+ printf("hash_any: bad algorithm\n");
+ return 0;
+ }
+}
+
+unsigned
+digest_final(uint8_t *out, digest_t *hash)
+{
+ if (hash == NULL || out == NULL) {
+ return 0;
+ }
+ switch(hash->alg) {
+ case MD5_HASH_ALG:
+ MD5Final(out, hash->ctx);
+ break;
+ case SHA1_HASH_ALG:
+ SHA1Final(out, hash->ctx);
+ break;
+ case RIPEMD_HASH_ALG:
+ RMD160Final(out, hash->ctx);
+ break;
+ case SHA256_HASH_ALG:
+ SHA256_Final(out, hash->ctx);
+ break;
+ case SHA512_HASH_ALG:
+ SHA512_Final(out, hash->ctx);
+ break;
+ case TIGER_HASH_ALG:
+ TIGER_Final(out, hash->ctx);
+ break;
+ default:
+ printf("hash_any: bad algorithm\n");
+ return 0;
+ }
+ (void) memset(hash->ctx, 0x0, hash->size);
+ return (unsigned)hash->size;
+}
+
+int
+digest_length(digest_t *hash, unsigned hashedlen)
+{
+ uint8_t trailer[6];
+
+ if (hash == NULL) {
+ return 0;
+ }
+ trailer[0] = V4_SIGNATURE;
+ trailer[1] = 0xFF;
+ trailer[2] = (uint8_t)((hashedlen >> 24) & 0xff);
+ trailer[3] = (uint8_t)((hashedlen >> 16) & 0xff);
+ trailer[4] = (uint8_t)((hashedlen >> 8) & 0xff);
+ trailer[5] = (uint8_t)(hashedlen & 0xff);
+ digest_update(hash, trailer, sizeof(trailer));
+ return 1;
+}
+
+unsigned
+digest_get_prefix(unsigned hashalg, uint8_t *prefix, size_t size)
+{
+ if (prefix == NULL) {
+ return 0;
+ }
+ switch (hashalg) {
+ case MD5_HASH_ALG:
+ memcpy(prefix, prefix_md5, sizeof(prefix_md5));
+ return sizeof(prefix_md5);
+ case SHA1_HASH_ALG:
+ memcpy(prefix, prefix_sha1, sizeof(prefix_sha1));
+ return sizeof(prefix_sha1);
+ case SHA256_HASH_ALG:
+ memcpy(prefix, prefix_sha256, sizeof(prefix_sha256));
+ return sizeof(prefix_sha256);
+ default:
+ printf("digest_get_prefix: unknown hash algorithm: %d\n", hashalg);
+ return 0;
+ }
+}
+
diff --git a/security/libnetpgpverify/files/src/libdigest/digest.h b/security/libnetpgpverify/files/src/libdigest/digest.h
new file mode 100644
index 00000000000..28d1ebd08be
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libdigest/digest.h
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef DIGEST_H_
+#define DIGEST_H_ 20100108
+
+#include <sys/types.h>
+
+#ifdef _KERNEL
+# include <sys/md5.h>
+# include <sys/sha1.h>
+# include <sys/sha2.h>
+# include <sys/rmd160.h>
+#else
+# include <md5.h>
+# include <sha1.h>
+# include <sha2.h>
+# include <rmd160.h>
+# include <inttypes.h>
+#endif
+
+#include "tiger.h"
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+#define MD5_HASH_ALG 1
+#define SHA1_HASH_ALG 2
+#define RIPEMD_HASH_ALG 3
+#define TIGER_HASH_ALG 6 /* from rfc2440 */
+#define SHA256_HASH_ALG 8
+#define SHA384_HASH_ALG 9
+#define SHA512_HASH_ALG 10
+#define SHA224_HASH_ALG 11
+#define TIGER2_HASH_ALG 100 /* private/experimental from rfc4880 */
+
+/* structure to describe digest methods */
+typedef struct digest_t {
+ uint32_t alg; /* algorithm */
+ size_t size; /* size */
+ union {
+ MD5_CTX md5ctx; /* MD5 */
+ SHA1_CTX sha1ctx; /* SHA1 */
+ RMD160_CTX rmd160ctx; /* RIPEMD */
+ SHA256_CTX sha256ctx; /* SHA256 */
+ SHA512_CTX sha512ctx; /* SHA512 */
+ TIGER_CTX tigerctx; /* TIGER/TIGER2 */
+ } u;
+ void *prefix; /* points to specific prefix */
+ uint32_t len; /* prefix length */
+ void *ctx; /* pointer to context array */
+} digest_t;
+
+unsigned digest_get_alg(const char */*hashalg*/);
+
+int digest_init(digest_t */*digest*/, const uint32_t /*hashalg*/);
+
+int digest_update(digest_t */*digest*/, const uint8_t */*data*/, size_t /*size*/);
+unsigned digest_final(uint8_t */*out*/, digest_t */*digest*/);
+int digest_alg_size(unsigned /*alg*/);
+int digest_length(digest_t */*hash*/, unsigned /*hashedlen*/);
+
+void MD5_Init(MD5_CTX */*context*/);
+void MD5_Update(MD5_CTX */*context*/, const unsigned char */*data*/, unsigned int /*len*/);
+void MD5_Final(unsigned char /*digest*/[16], MD5_CTX */*context*/);
+
+void SHA1_Init(SHA1_CTX */*context*/);
+void SHA1_Update(SHA1_CTX */*context*/, const unsigned char */*data*/, unsigned int /*len*/);
+void SHA1_Final(unsigned char /*digest*/[20], SHA1_CTX */*context*/);
+
+void RMD160_Init(RMD160_CTX */*ctx*/);
+void RMD160_Update(RMD160_CTX */*ctx*/, const unsigned char */*data*/, uint32_t /*len*/);
+void RMD160_Final(unsigned char /*digest*/[RMD160_DIGEST_LENGTH], RMD160_CTX */*ctx*/);
+
+unsigned digest_get_prefix(unsigned /*hashalg*/, uint8_t */*prefix*/, size_t /*size*/);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libdigest/tiger.3 b/security/libnetpgpverify/files/src/libdigest/tiger.3
new file mode 100644
index 00000000000..868a2bbf975
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libdigest/tiger.3
@@ -0,0 +1,219 @@
+.\" $NetBSD: tiger.3,v 1.1.1.1 2013/02/23 21:04:27 agc Exp $
+.\"
+.\" Copyright (c) 2011 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.
+.\"
+.Dd May 30, 2011
+.Dt TIGER 3
+.Os
+.Sh NAME
+.Nm TIGER_Init ,
+.Nm TIGER_Update ,
+.Nm TIGER_Final ,
+.Nm TIGER_End ,
+.Nm TIGER_File ,
+.Nm TIGER_Data
+.Nd calculate TIGER message digests
+.Sh SYNOPSIS
+.In tiger.h
+.Ft void
+.Fo TIGER_Init
+.Fa "TIGER_CTX *context"
+.Fc
+.Ft void
+.Fo TIGER_Update
+.Fa "TIGER_CTX *context" "const uint8_t *data" "u_int len"
+.Fc
+.Ft void
+.Fo TIGER_Final
+.Fa "uint8_t digest[20]" "TIGER_CTX *context"
+.Fc
+.Ft "char *"
+.Fo TIGER_End
+.Fa "TIGER_CTX *context" "char *buf"
+.Fc
+.Ft "char *"
+.Fo TIGER_File
+.Fa "char *filename" "char *buf"
+.Fc
+.Ft "char *"
+.Fo TIGER_Data
+.Fa "uint8_t *data" "size_t len" "char *buf"
+.Fc
+.Sh DESCRIPTION
+The TIGER functions calculate TIGER message digest functions,
+as defined by Ross Anderson and Eli Biham.
+The algorithm takes a
+message less than 2^64 bits as input and produces a 192-bit digest
+suitable for use as a digital signature.
+.Pp
+At the time of writing,
+May 2011,
+no attacks or pre-imaging have been discovered against the
+.Nm
+message digests, whilst the same cannot be said of
+.Xr md5 3
+or
+.Xr sha1 3 .
+.Pp
+The
+.Fn TIGER_Init
+function initializes a TIGER_CTX
+.Ar context
+for use with
+.Fn TIGER_Update ,
+and
+.Fn TIGER_Final .
+The
+.Fn TIGER_Update
+function adds
+.Ar data
+of length
+.Ar len
+to the TIGER_CTX specified by
+.Ar context .
+.Fn TIGER_Final
+is called when all data has been added via
+.Fn TIGER_Update
+and stores a message digest in the
+.Ar digest
+parameter.
+When a
+.Dv NULL
+pointer is passed to
+.Fn TIGER_Final
+as first argument only the final padding will be applied and the
+current context can still be used with
+.Fn TIGER_Update .
+.Pp
+The core of the TIGER message digest is performed by
+.Fn TIGER_Update .
+Most programs should use the interface provided by
+.Fn TIGER_Init ,
+.Fn TIGER_Update ,
+and
+.Fn TIGER_Final .
+.Pp
+The
+.Fn TIGER_End
+function is a front end for
+.Fn TIGER_Final
+which converts the digest into an
+.Tn ASCII
+representation of the 160 bit digest in hexadecimal.
+.Pp
+The
+.Fn TIGER_File
+function calculates the digest for a file and returns the result via
+.Fn TIGER_End .
+If
+.Fn TIGER_File
+is unable to open the file a
+.Dv NULL
+pointer is returned.
+.Pp
+The
+.Fn TIGER_Data
+function
+calculates the digest of an arbitrary string and returns the result via
+.Fn TIGER_End .
+.Pp
+For each of the
+.Fn TIGER_End ,
+.Fn TIGER_File ,
+and
+.Fn TIGER_Data
+functions the
+.Ar buf
+parameter should either be a string of at least 41 characters in
+size or a
+.Dv NULL
+pointer.
+In the latter case, space will be dynamically allocated via
+.Xr malloc 3
+and should be freed using
+.Xr free 3
+when it is no longer needed.
+.Sh EXAMPLES
+The follow code fragment will calculate the digest for the string
+"The quick brown fox jumps over the lazy dog"
+which is
+.Dq 6d12a41e72e644f017b6f0e2f7b44c6285f06dd5d2c5b075 .
+.Bd -literal -offset indent
+TIGER_CTX tiger;
+uint8_t results[24];
+char *buf;
+int n;
+
+buf = "The quick brown fox jumps over the lazy dog";
+n = strlen(buf);
+TIGER_Init(\*[Am]tiger);
+TIGER_Update(\*[Am]tiger, (uint8_t *)buf, n);
+TIGER_Final(results, \*[Am]tiger);
+
+/* Print the digest as one long hex value */
+printf("0x");
+for (n = 0; n \*[Lt] 24; n++)
+ printf("%02x", results[n]);
+putchar('\en');
+.Ed
+.Pp
+Alternately, the helper functions could be used in the following way:
+.Bd -literal -offset indent
+TIGER_CTX tiger;
+uint8_t output[49];
+char *buf = "The quick brown fox jumps over the lazy dog";
+
+printf("0x%s", TIGER_Data(buf, strlen(buf), output));
+.Ed
+.Sh SEE ALSO
+.Xr md5 3 ,
+.Xr sha1 3
+.Pp
+.Rs
+.%A Ross Anderson
+.%A Eli Biham
+.%T "Tiger - A Fast New Hash Function"
+.%B Proceedings of Fast Software Encryption 3, Cambridge
+.%D 1996
+.Re
+.Sh HISTORY
+The TIGER functions appeared in
+.Nx 6.0 .
+.Sh AUTHORS
+.An -nosplit
+This implementation of TIGER was adapted by
+.An Alistair Crooks Aq agc@NetBSD.org
+from the original reference code.
+.Pp
+The
+.Fn TIGER_End ,
+.Fn TIGER_File ,
+and
+.Fn TIGER_Data
+helper functions are derived from code written by Poul-Henning Kamp.
+.Sh BUGS
+All attempts have bene made to optimise for the underlying hardware,
+as well as to format the digest properly in an endian-neutral manner.
+The author has no VAX hardware on which to test, and so it is not known
+whether that platform is supported.
diff --git a/security/libnetpgpverify/files/src/libdigest/tiger.c b/security/libnetpgpverify/files/src/libdigest/tiger.c
new file mode 100644
index 00000000000..e0b44d912e7
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libdigest/tiger.c
@@ -0,0 +1,906 @@
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tiger.h"
+
+#ifndef IS_LITTLE_ENDIAN
+#define IS_LITTLE_ENDIAN(x) (*(char *)(void *)&x)
+#define IS_BIG_ENDIAN(x) !(*(char *)(void *)&x)
+#endif
+
+#define BSWAP64(x) ((((x) & 0xffULL) << 56) | \
+ (((x) & 0xff00ULL) << 40) | \
+ (((x) & 0xff0000ULL) << 24) | \
+ (((x) & 0xff000000ULL) << 8) | \
+ (((x) & 0xff00000000ULL) >> 8) | \
+ (((x) & 0xff0000000000ULL) >> 24) | \
+ (((x) & 0xff000000000000ULL) >> 40) | \
+ (((x) & 0xff00000000000000ULL) >> 56))
+
+/* sboxes.c: Tiger S boxes */
+static uint64_t table[4*256] = {
+ 0x02AAB17CF7E90C5ELL /* 0 */, 0xAC424B03E243A8ECLL /* 1 */,
+ 0x72CD5BE30DD5FCD3LL /* 2 */, 0x6D019B93F6F97F3ALL /* 3 */,
+ 0xCD9978FFD21F9193LL /* 4 */, 0x7573A1C9708029E2LL /* 5 */,
+ 0xB164326B922A83C3LL /* 6 */, 0x46883EEE04915870LL /* 7 */,
+ 0xEAACE3057103ECE6LL /* 8 */, 0xC54169B808A3535CLL /* 9 */,
+ 0x4CE754918DDEC47CLL /* 10 */, 0x0AA2F4DFDC0DF40CLL /* 11 */,
+ 0x10B76F18A74DBEFALL /* 12 */, 0xC6CCB6235AD1AB6ALL /* 13 */,
+ 0x13726121572FE2FFLL /* 14 */, 0x1A488C6F199D921ELL /* 15 */,
+ 0x4BC9F9F4DA0007CALL /* 16 */, 0x26F5E6F6E85241C7LL /* 17 */,
+ 0x859079DBEA5947B6LL /* 18 */, 0x4F1885C5C99E8C92LL /* 19 */,
+ 0xD78E761EA96F864BLL /* 20 */, 0x8E36428C52B5C17DLL /* 21 */,
+ 0x69CF6827373063C1LL /* 22 */, 0xB607C93D9BB4C56ELL /* 23 */,
+ 0x7D820E760E76B5EALL /* 24 */, 0x645C9CC6F07FDC42LL /* 25 */,
+ 0xBF38A078243342E0LL /* 26 */, 0x5F6B343C9D2E7D04LL /* 27 */,
+ 0xF2C28AEB600B0EC6LL /* 28 */, 0x6C0ED85F7254BCACLL /* 29 */,
+ 0x71592281A4DB4FE5LL /* 30 */, 0x1967FA69CE0FED9FLL /* 31 */,
+ 0xFD5293F8B96545DBLL /* 32 */, 0xC879E9D7F2A7600BLL /* 33 */,
+ 0x860248920193194ELL /* 34 */, 0xA4F9533B2D9CC0B3LL /* 35 */,
+ 0x9053836C15957613LL /* 36 */, 0xDB6DCF8AFC357BF1LL /* 37 */,
+ 0x18BEEA7A7A370F57LL /* 38 */, 0x037117CA50B99066LL /* 39 */,
+ 0x6AB30A9774424A35LL /* 40 */, 0xF4E92F02E325249BLL /* 41 */,
+ 0x7739DB07061CCAE1LL /* 42 */, 0xD8F3B49CECA42A05LL /* 43 */,
+ 0xBD56BE3F51382F73LL /* 44 */, 0x45FAED5843B0BB28LL /* 45 */,
+ 0x1C813D5C11BF1F83LL /* 46 */, 0x8AF0E4B6D75FA169LL /* 47 */,
+ 0x33EE18A487AD9999LL /* 48 */, 0x3C26E8EAB1C94410LL /* 49 */,
+ 0xB510102BC0A822F9LL /* 50 */, 0x141EEF310CE6123BLL /* 51 */,
+ 0xFC65B90059DDB154LL /* 52 */, 0xE0158640C5E0E607LL /* 53 */,
+ 0x884E079826C3A3CFLL /* 54 */, 0x930D0D9523C535FDLL /* 55 */,
+ 0x35638D754E9A2B00LL /* 56 */, 0x4085FCCF40469DD5LL /* 57 */,
+ 0xC4B17AD28BE23A4CLL /* 58 */, 0xCAB2F0FC6A3E6A2ELL /* 59 */,
+ 0x2860971A6B943FCDLL /* 60 */, 0x3DDE6EE212E30446LL /* 61 */,
+ 0x6222F32AE01765AELL /* 62 */, 0x5D550BB5478308FELL /* 63 */,
+ 0xA9EFA98DA0EDA22ALL /* 64 */, 0xC351A71686C40DA7LL /* 65 */,
+ 0x1105586D9C867C84LL /* 66 */, 0xDCFFEE85FDA22853LL /* 67 */,
+ 0xCCFBD0262C5EEF76LL /* 68 */, 0xBAF294CB8990D201LL /* 69 */,
+ 0xE69464F52AFAD975LL /* 70 */, 0x94B013AFDF133E14LL /* 71 */,
+ 0x06A7D1A32823C958LL /* 72 */, 0x6F95FE5130F61119LL /* 73 */,
+ 0xD92AB34E462C06C0LL /* 74 */, 0xED7BDE33887C71D2LL /* 75 */,
+ 0x79746D6E6518393ELL /* 76 */, 0x5BA419385D713329LL /* 77 */,
+ 0x7C1BA6B948A97564LL /* 78 */, 0x31987C197BFDAC67LL /* 79 */,
+ 0xDE6C23C44B053D02LL /* 80 */, 0x581C49FED002D64DLL /* 81 */,
+ 0xDD474D6338261571LL /* 82 */, 0xAA4546C3E473D062LL /* 83 */,
+ 0x928FCE349455F860LL /* 84 */, 0x48161BBACAAB94D9LL /* 85 */,
+ 0x63912430770E6F68LL /* 86 */, 0x6EC8A5E602C6641CLL /* 87 */,
+ 0x87282515337DDD2BLL /* 88 */, 0x2CDA6B42034B701BLL /* 89 */,
+ 0xB03D37C181CB096DLL /* 90 */, 0xE108438266C71C6FLL /* 91 */,
+ 0x2B3180C7EB51B255LL /* 92 */, 0xDF92B82F96C08BBCLL /* 93 */,
+ 0x5C68C8C0A632F3BALL /* 94 */, 0x5504CC861C3D0556LL /* 95 */,
+ 0xABBFA4E55FB26B8FLL /* 96 */, 0x41848B0AB3BACEB4LL /* 97 */,
+ 0xB334A273AA445D32LL /* 98 */, 0xBCA696F0A85AD881LL /* 99 */,
+ 0x24F6EC65B528D56CLL /* 100 */, 0x0CE1512E90F4524ALL /* 101 */,
+ 0x4E9DD79D5506D35ALL /* 102 */, 0x258905FAC6CE9779LL /* 103 */,
+ 0x2019295B3E109B33LL /* 104 */, 0xF8A9478B73A054CCLL /* 105 */,
+ 0x2924F2F934417EB0LL /* 106 */, 0x3993357D536D1BC4LL /* 107 */,
+ 0x38A81AC21DB6FF8BLL /* 108 */, 0x47C4FBF17D6016BFLL /* 109 */,
+ 0x1E0FAADD7667E3F5LL /* 110 */, 0x7ABCFF62938BEB96LL /* 111 */,
+ 0xA78DAD948FC179C9LL /* 112 */, 0x8F1F98B72911E50DLL /* 113 */,
+ 0x61E48EAE27121A91LL /* 114 */, 0x4D62F7AD31859808LL /* 115 */,
+ 0xECEBA345EF5CEAEBLL /* 116 */, 0xF5CEB25EBC9684CELL /* 117 */,
+ 0xF633E20CB7F76221LL /* 118 */, 0xA32CDF06AB8293E4LL /* 119 */,
+ 0x985A202CA5EE2CA4LL /* 120 */, 0xCF0B8447CC8A8FB1LL /* 121 */,
+ 0x9F765244979859A3LL /* 122 */, 0xA8D516B1A1240017LL /* 123 */,
+ 0x0BD7BA3EBB5DC726LL /* 124 */, 0xE54BCA55B86ADB39LL /* 125 */,
+ 0x1D7A3AFD6C478063LL /* 126 */, 0x519EC608E7669EDDLL /* 127 */,
+ 0x0E5715A2D149AA23LL /* 128 */, 0x177D4571848FF194LL /* 129 */,
+ 0xEEB55F3241014C22LL /* 130 */, 0x0F5E5CA13A6E2EC2LL /* 131 */,
+ 0x8029927B75F5C361LL /* 132 */, 0xAD139FABC3D6E436LL /* 133 */,
+ 0x0D5DF1A94CCF402FLL /* 134 */, 0x3E8BD948BEA5DFC8LL /* 135 */,
+ 0xA5A0D357BD3FF77ELL /* 136 */, 0xA2D12E251F74F645LL /* 137 */,
+ 0x66FD9E525E81A082LL /* 138 */, 0x2E0C90CE7F687A49LL /* 139 */,
+ 0xC2E8BCBEBA973BC5LL /* 140 */, 0x000001BCE509745FLL /* 141 */,
+ 0x423777BBE6DAB3D6LL /* 142 */, 0xD1661C7EAEF06EB5LL /* 143 */,
+ 0xA1781F354DAACFD8LL /* 144 */, 0x2D11284A2B16AFFCLL /* 145 */,
+ 0xF1FC4F67FA891D1FLL /* 146 */, 0x73ECC25DCB920ADALL /* 147 */,
+ 0xAE610C22C2A12651LL /* 148 */, 0x96E0A810D356B78ALL /* 149 */,
+ 0x5A9A381F2FE7870FLL /* 150 */, 0xD5AD62EDE94E5530LL /* 151 */,
+ 0xD225E5E8368D1427LL /* 152 */, 0x65977B70C7AF4631LL /* 153 */,
+ 0x99F889B2DE39D74FLL /* 154 */, 0x233F30BF54E1D143LL /* 155 */,
+ 0x9A9675D3D9A63C97LL /* 156 */, 0x5470554FF334F9A8LL /* 157 */,
+ 0x166ACB744A4F5688LL /* 158 */, 0x70C74CAAB2E4AEADLL /* 159 */,
+ 0xF0D091646F294D12LL /* 160 */, 0x57B82A89684031D1LL /* 161 */,
+ 0xEFD95A5A61BE0B6BLL /* 162 */, 0x2FBD12E969F2F29ALL /* 163 */,
+ 0x9BD37013FEFF9FE8LL /* 164 */, 0x3F9B0404D6085A06LL /* 165 */,
+ 0x4940C1F3166CFE15LL /* 166 */, 0x09542C4DCDF3DEFBLL /* 167 */,
+ 0xB4C5218385CD5CE3LL /* 168 */, 0xC935B7DC4462A641LL /* 169 */,
+ 0x3417F8A68ED3B63FLL /* 170 */, 0xB80959295B215B40LL /* 171 */,
+ 0xF99CDAEF3B8C8572LL /* 172 */, 0x018C0614F8FCB95DLL /* 173 */,
+ 0x1B14ACCD1A3ACDF3LL /* 174 */, 0x84D471F200BB732DLL /* 175 */,
+ 0xC1A3110E95E8DA16LL /* 176 */, 0x430A7220BF1A82B8LL /* 177 */,
+ 0xB77E090D39DF210ELL /* 178 */, 0x5EF4BD9F3CD05E9DLL /* 179 */,
+ 0x9D4FF6DA7E57A444LL /* 180 */, 0xDA1D60E183D4A5F8LL /* 181 */,
+ 0xB287C38417998E47LL /* 182 */, 0xFE3EDC121BB31886LL /* 183 */,
+ 0xC7FE3CCC980CCBEFLL /* 184 */, 0xE46FB590189BFD03LL /* 185 */,
+ 0x3732FD469A4C57DCLL /* 186 */, 0x7EF700A07CF1AD65LL /* 187 */,
+ 0x59C64468A31D8859LL /* 188 */, 0x762FB0B4D45B61F6LL /* 189 */,
+ 0x155BAED099047718LL /* 190 */, 0x68755E4C3D50BAA6LL /* 191 */,
+ 0xE9214E7F22D8B4DFLL /* 192 */, 0x2ADDBF532EAC95F4LL /* 193 */,
+ 0x32AE3909B4BD0109LL /* 194 */, 0x834DF537B08E3450LL /* 195 */,
+ 0xFA209DA84220728DLL /* 196 */, 0x9E691D9B9EFE23F7LL /* 197 */,
+ 0x0446D288C4AE8D7FLL /* 198 */, 0x7B4CC524E169785BLL /* 199 */,
+ 0x21D87F0135CA1385LL /* 200 */, 0xCEBB400F137B8AA5LL /* 201 */,
+ 0x272E2B66580796BELL /* 202 */, 0x3612264125C2B0DELL /* 203 */,
+ 0x057702BDAD1EFBB2LL /* 204 */, 0xD4BABB8EACF84BE9LL /* 205 */,
+ 0x91583139641BC67BLL /* 206 */, 0x8BDC2DE08036E024LL /* 207 */,
+ 0x603C8156F49F68EDLL /* 208 */, 0xF7D236F7DBEF5111LL /* 209 */,
+ 0x9727C4598AD21E80LL /* 210 */, 0xA08A0896670A5FD7LL /* 211 */,
+ 0xCB4A8F4309EBA9CBLL /* 212 */, 0x81AF564B0F7036A1LL /* 213 */,
+ 0xC0B99AA778199ABDLL /* 214 */, 0x959F1EC83FC8E952LL /* 215 */,
+ 0x8C505077794A81B9LL /* 216 */, 0x3ACAAF8F056338F0LL /* 217 */,
+ 0x07B43F50627A6778LL /* 218 */, 0x4A44AB49F5ECCC77LL /* 219 */,
+ 0x3BC3D6E4B679EE98LL /* 220 */, 0x9CC0D4D1CF14108CLL /* 221 */,
+ 0x4406C00B206BC8A0LL /* 222 */, 0x82A18854C8D72D89LL /* 223 */,
+ 0x67E366B35C3C432CLL /* 224 */, 0xB923DD61102B37F2LL /* 225 */,
+ 0x56AB2779D884271DLL /* 226 */, 0xBE83E1B0FF1525AFLL /* 227 */,
+ 0xFB7C65D4217E49A9LL /* 228 */, 0x6BDBE0E76D48E7D4LL /* 229 */,
+ 0x08DF828745D9179ELL /* 230 */, 0x22EA6A9ADD53BD34LL /* 231 */,
+ 0xE36E141C5622200ALL /* 232 */, 0x7F805D1B8CB750EELL /* 233 */,
+ 0xAFE5C7A59F58E837LL /* 234 */, 0xE27F996A4FB1C23CLL /* 235 */,
+ 0xD3867DFB0775F0D0LL /* 236 */, 0xD0E673DE6E88891ALL /* 237 */,
+ 0x123AEB9EAFB86C25LL /* 238 */, 0x30F1D5D5C145B895LL /* 239 */,
+ 0xBB434A2DEE7269E7LL /* 240 */, 0x78CB67ECF931FA38LL /* 241 */,
+ 0xF33B0372323BBF9CLL /* 242 */, 0x52D66336FB279C74LL /* 243 */,
+ 0x505F33AC0AFB4EAALL /* 244 */, 0xE8A5CD99A2CCE187LL /* 245 */,
+ 0x534974801E2D30BBLL /* 246 */, 0x8D2D5711D5876D90LL /* 247 */,
+ 0x1F1A412891BC038ELL /* 248 */, 0xD6E2E71D82E56648LL /* 249 */,
+ 0x74036C3A497732B7LL /* 250 */, 0x89B67ED96361F5ABLL /* 251 */,
+ 0xFFED95D8F1EA02A2LL /* 252 */, 0xE72B3BD61464D43DLL /* 253 */,
+ 0xA6300F170BDC4820LL /* 254 */, 0xEBC18760ED78A77ALL /* 255 */,
+ 0xE6A6BE5A05A12138LL /* 256 */, 0xB5A122A5B4F87C98LL /* 257 */,
+ 0x563C6089140B6990LL /* 258 */, 0x4C46CB2E391F5DD5LL /* 259 */,
+ 0xD932ADDBC9B79434LL /* 260 */, 0x08EA70E42015AFF5LL /* 261 */,
+ 0xD765A6673E478CF1LL /* 262 */, 0xC4FB757EAB278D99LL /* 263 */,
+ 0xDF11C6862D6E0692LL /* 264 */, 0xDDEB84F10D7F3B16LL /* 265 */,
+ 0x6F2EF604A665EA04LL /* 266 */, 0x4A8E0F0FF0E0DFB3LL /* 267 */,
+ 0xA5EDEEF83DBCBA51LL /* 268 */, 0xFC4F0A2A0EA4371ELL /* 269 */,
+ 0xE83E1DA85CB38429LL /* 270 */, 0xDC8FF882BA1B1CE2LL /* 271 */,
+ 0xCD45505E8353E80DLL /* 272 */, 0x18D19A00D4DB0717LL /* 273 */,
+ 0x34A0CFEDA5F38101LL /* 274 */, 0x0BE77E518887CAF2LL /* 275 */,
+ 0x1E341438B3C45136LL /* 276 */, 0xE05797F49089CCF9LL /* 277 */,
+ 0xFFD23F9DF2591D14LL /* 278 */, 0x543DDA228595C5CDLL /* 279 */,
+ 0x661F81FD99052A33LL /* 280 */, 0x8736E641DB0F7B76LL /* 281 */,
+ 0x15227725418E5307LL /* 282 */, 0xE25F7F46162EB2FALL /* 283 */,
+ 0x48A8B2126C13D9FELL /* 284 */, 0xAFDC541792E76EEALL /* 285 */,
+ 0x03D912BFC6D1898FLL /* 286 */, 0x31B1AAFA1B83F51BLL /* 287 */,
+ 0xF1AC2796E42AB7D9LL /* 288 */, 0x40A3A7D7FCD2EBACLL /* 289 */,
+ 0x1056136D0AFBBCC5LL /* 290 */, 0x7889E1DD9A6D0C85LL /* 291 */,
+ 0xD33525782A7974AALL /* 292 */, 0xA7E25D09078AC09BLL /* 293 */,
+ 0xBD4138B3EAC6EDD0LL /* 294 */, 0x920ABFBE71EB9E70LL /* 295 */,
+ 0xA2A5D0F54FC2625CLL /* 296 */, 0xC054E36B0B1290A3LL /* 297 */,
+ 0xF6DD59FF62FE932BLL /* 298 */, 0x3537354511A8AC7DLL /* 299 */,
+ 0xCA845E9172FADCD4LL /* 300 */, 0x84F82B60329D20DCLL /* 301 */,
+ 0x79C62CE1CD672F18LL /* 302 */, 0x8B09A2ADD124642CLL /* 303 */,
+ 0xD0C1E96A19D9E726LL /* 304 */, 0x5A786A9B4BA9500CLL /* 305 */,
+ 0x0E020336634C43F3LL /* 306 */, 0xC17B474AEB66D822LL /* 307 */,
+ 0x6A731AE3EC9BAAC2LL /* 308 */, 0x8226667AE0840258LL /* 309 */,
+ 0x67D4567691CAECA5LL /* 310 */, 0x1D94155C4875ADB5LL /* 311 */,
+ 0x6D00FD985B813FDFLL /* 312 */, 0x51286EFCB774CD06LL /* 313 */,
+ 0x5E8834471FA744AFLL /* 314 */, 0xF72CA0AEE761AE2ELL /* 315 */,
+ 0xBE40E4CDAEE8E09ALL /* 316 */, 0xE9970BBB5118F665LL /* 317 */,
+ 0x726E4BEB33DF1964LL /* 318 */, 0x703B000729199762LL /* 319 */,
+ 0x4631D816F5EF30A7LL /* 320 */, 0xB880B5B51504A6BELL /* 321 */,
+ 0x641793C37ED84B6CLL /* 322 */, 0x7B21ED77F6E97D96LL /* 323 */,
+ 0x776306312EF96B73LL /* 324 */, 0xAE528948E86FF3F4LL /* 325 */,
+ 0x53DBD7F286A3F8F8LL /* 326 */, 0x16CADCE74CFC1063LL /* 327 */,
+ 0x005C19BDFA52C6DDLL /* 328 */, 0x68868F5D64D46AD3LL /* 329 */,
+ 0x3A9D512CCF1E186ALL /* 330 */, 0x367E62C2385660AELL /* 331 */,
+ 0xE359E7EA77DCB1D7LL /* 332 */, 0x526C0773749ABE6ELL /* 333 */,
+ 0x735AE5F9D09F734BLL /* 334 */, 0x493FC7CC8A558BA8LL /* 335 */,
+ 0xB0B9C1533041AB45LL /* 336 */, 0x321958BA470A59BDLL /* 337 */,
+ 0x852DB00B5F46C393LL /* 338 */, 0x91209B2BD336B0E5LL /* 339 */,
+ 0x6E604F7D659EF19FLL /* 340 */, 0xB99A8AE2782CCB24LL /* 341 */,
+ 0xCCF52AB6C814C4C7LL /* 342 */, 0x4727D9AFBE11727BLL /* 343 */,
+ 0x7E950D0C0121B34DLL /* 344 */, 0x756F435670AD471FLL /* 345 */,
+ 0xF5ADD442615A6849LL /* 346 */, 0x4E87E09980B9957ALL /* 347 */,
+ 0x2ACFA1DF50AEE355LL /* 348 */, 0xD898263AFD2FD556LL /* 349 */,
+ 0xC8F4924DD80C8FD6LL /* 350 */, 0xCF99CA3D754A173ALL /* 351 */,
+ 0xFE477BACAF91BF3CLL /* 352 */, 0xED5371F6D690C12DLL /* 353 */,
+ 0x831A5C285E687094LL /* 354 */, 0xC5D3C90A3708A0A4LL /* 355 */,
+ 0x0F7F903717D06580LL /* 356 */, 0x19F9BB13B8FDF27FLL /* 357 */,
+ 0xB1BD6F1B4D502843LL /* 358 */, 0x1C761BA38FFF4012LL /* 359 */,
+ 0x0D1530C4E2E21F3BLL /* 360 */, 0x8943CE69A7372C8ALL /* 361 */,
+ 0xE5184E11FEB5CE66LL /* 362 */, 0x618BDB80BD736621LL /* 363 */,
+ 0x7D29BAD68B574D0BLL /* 364 */, 0x81BB613E25E6FE5BLL /* 365 */,
+ 0x071C9C10BC07913FLL /* 366 */, 0xC7BEEB7909AC2D97LL /* 367 */,
+ 0xC3E58D353BC5D757LL /* 368 */, 0xEB017892F38F61E8LL /* 369 */,
+ 0xD4EFFB9C9B1CC21ALL /* 370 */, 0x99727D26F494F7ABLL /* 371 */,
+ 0xA3E063A2956B3E03LL /* 372 */, 0x9D4A8B9A4AA09C30LL /* 373 */,
+ 0x3F6AB7D500090FB4LL /* 374 */, 0x9CC0F2A057268AC0LL /* 375 */,
+ 0x3DEE9D2DEDBF42D1LL /* 376 */, 0x330F49C87960A972LL /* 377 */,
+ 0xC6B2720287421B41LL /* 378 */, 0x0AC59EC07C00369CLL /* 379 */,
+ 0xEF4EAC49CB353425LL /* 380 */, 0xF450244EEF0129D8LL /* 381 */,
+ 0x8ACC46E5CAF4DEB6LL /* 382 */, 0x2FFEAB63989263F7LL /* 383 */,
+ 0x8F7CB9FE5D7A4578LL /* 384 */, 0x5BD8F7644E634635LL /* 385 */,
+ 0x427A7315BF2DC900LL /* 386 */, 0x17D0C4AA2125261CLL /* 387 */,
+ 0x3992486C93518E50LL /* 388 */, 0xB4CBFEE0A2D7D4C3LL /* 389 */,
+ 0x7C75D6202C5DDD8DLL /* 390 */, 0xDBC295D8E35B6C61LL /* 391 */,
+ 0x60B369D302032B19LL /* 392 */, 0xCE42685FDCE44132LL /* 393 */,
+ 0x06F3DDB9DDF65610LL /* 394 */, 0x8EA4D21DB5E148F0LL /* 395 */,
+ 0x20B0FCE62FCD496FLL /* 396 */, 0x2C1B912358B0EE31LL /* 397 */,
+ 0xB28317B818F5A308LL /* 398 */, 0xA89C1E189CA6D2CFLL /* 399 */,
+ 0x0C6B18576AAADBC8LL /* 400 */, 0xB65DEAA91299FAE3LL /* 401 */,
+ 0xFB2B794B7F1027E7LL /* 402 */, 0x04E4317F443B5BEBLL /* 403 */,
+ 0x4B852D325939D0A6LL /* 404 */, 0xD5AE6BEEFB207FFCLL /* 405 */,
+ 0x309682B281C7D374LL /* 406 */, 0xBAE309A194C3B475LL /* 407 */,
+ 0x8CC3F97B13B49F05LL /* 408 */, 0x98A9422FF8293967LL /* 409 */,
+ 0x244B16B01076FF7CLL /* 410 */, 0xF8BF571C663D67EELL /* 411 */,
+ 0x1F0D6758EEE30DA1LL /* 412 */, 0xC9B611D97ADEB9B7LL /* 413 */,
+ 0xB7AFD5887B6C57A2LL /* 414 */, 0x6290AE846B984FE1LL /* 415 */,
+ 0x94DF4CDEACC1A5FDLL /* 416 */, 0x058A5BD1C5483AFFLL /* 417 */,
+ 0x63166CC142BA3C37LL /* 418 */, 0x8DB8526EB2F76F40LL /* 419 */,
+ 0xE10880036F0D6D4ELL /* 420 */, 0x9E0523C9971D311DLL /* 421 */,
+ 0x45EC2824CC7CD691LL /* 422 */, 0x575B8359E62382C9LL /* 423 */,
+ 0xFA9E400DC4889995LL /* 424 */, 0xD1823ECB45721568LL /* 425 */,
+ 0xDAFD983B8206082FLL /* 426 */, 0xAA7D29082386A8CBLL /* 427 */,
+ 0x269FCD4403B87588LL /* 428 */, 0x1B91F5F728BDD1E0LL /* 429 */,
+ 0xE4669F39040201F6LL /* 430 */, 0x7A1D7C218CF04ADELL /* 431 */,
+ 0x65623C29D79CE5CELL /* 432 */, 0x2368449096C00BB1LL /* 433 */,
+ 0xAB9BF1879DA503BALL /* 434 */, 0xBC23ECB1A458058ELL /* 435 */,
+ 0x9A58DF01BB401ECCLL /* 436 */, 0xA070E868A85F143DLL /* 437 */,
+ 0x4FF188307DF2239ELL /* 438 */, 0x14D565B41A641183LL /* 439 */,
+ 0xEE13337452701602LL /* 440 */, 0x950E3DCF3F285E09LL /* 441 */,
+ 0x59930254B9C80953LL /* 442 */, 0x3BF299408930DA6DLL /* 443 */,
+ 0xA955943F53691387LL /* 444 */, 0xA15EDECAA9CB8784LL /* 445 */,
+ 0x29142127352BE9A0LL /* 446 */, 0x76F0371FFF4E7AFBLL /* 447 */,
+ 0x0239F450274F2228LL /* 448 */, 0xBB073AF01D5E868BLL /* 449 */,
+ 0xBFC80571C10E96C1LL /* 450 */, 0xD267088568222E23LL /* 451 */,
+ 0x9671A3D48E80B5B0LL /* 452 */, 0x55B5D38AE193BB81LL /* 453 */,
+ 0x693AE2D0A18B04B8LL /* 454 */, 0x5C48B4ECADD5335FLL /* 455 */,
+ 0xFD743B194916A1CALL /* 456 */, 0x2577018134BE98C4LL /* 457 */,
+ 0xE77987E83C54A4ADLL /* 458 */, 0x28E11014DA33E1B9LL /* 459 */,
+ 0x270CC59E226AA213LL /* 460 */, 0x71495F756D1A5F60LL /* 461 */,
+ 0x9BE853FB60AFEF77LL /* 462 */, 0xADC786A7F7443DBFLL /* 463 */,
+ 0x0904456173B29A82LL /* 464 */, 0x58BC7A66C232BD5ELL /* 465 */,
+ 0xF306558C673AC8B2LL /* 466 */, 0x41F639C6B6C9772ALL /* 467 */,
+ 0x216DEFE99FDA35DALL /* 468 */, 0x11640CC71C7BE615LL /* 469 */,
+ 0x93C43694565C5527LL /* 470 */, 0xEA038E6246777839LL /* 471 */,
+ 0xF9ABF3CE5A3E2469LL /* 472 */, 0x741E768D0FD312D2LL /* 473 */,
+ 0x0144B883CED652C6LL /* 474 */, 0xC20B5A5BA33F8552LL /* 475 */,
+ 0x1AE69633C3435A9DLL /* 476 */, 0x97A28CA4088CFDECLL /* 477 */,
+ 0x8824A43C1E96F420LL /* 478 */, 0x37612FA66EEEA746LL /* 479 */,
+ 0x6B4CB165F9CF0E5ALL /* 480 */, 0x43AA1C06A0ABFB4ALL /* 481 */,
+ 0x7F4DC26FF162796BLL /* 482 */, 0x6CBACC8E54ED9B0FLL /* 483 */,
+ 0xA6B7FFEFD2BB253ELL /* 484 */, 0x2E25BC95B0A29D4FLL /* 485 */,
+ 0x86D6A58BDEF1388CLL /* 486 */, 0xDED74AC576B6F054LL /* 487 */,
+ 0x8030BDBC2B45805DLL /* 488 */, 0x3C81AF70E94D9289LL /* 489 */,
+ 0x3EFF6DDA9E3100DBLL /* 490 */, 0xB38DC39FDFCC8847LL /* 491 */,
+ 0x123885528D17B87ELL /* 492 */, 0xF2DA0ED240B1B642LL /* 493 */,
+ 0x44CEFADCD54BF9A9LL /* 494 */, 0x1312200E433C7EE6LL /* 495 */,
+ 0x9FFCC84F3A78C748LL /* 496 */, 0xF0CD1F72248576BBLL /* 497 */,
+ 0xEC6974053638CFE4LL /* 498 */, 0x2BA7B67C0CEC4E4CLL /* 499 */,
+ 0xAC2F4DF3E5CE32EDLL /* 500 */, 0xCB33D14326EA4C11LL /* 501 */,
+ 0xA4E9044CC77E58BCLL /* 502 */, 0x5F513293D934FCEFLL /* 503 */,
+ 0x5DC9645506E55444LL /* 504 */, 0x50DE418F317DE40ALL /* 505 */,
+ 0x388CB31A69DDE259LL /* 506 */, 0x2DB4A83455820A86LL /* 507 */,
+ 0x9010A91E84711AE9LL /* 508 */, 0x4DF7F0B7B1498371LL /* 509 */,
+ 0xD62A2EABC0977179LL /* 510 */, 0x22FAC097AA8D5C0ELL /* 511 */,
+ 0xF49FCC2FF1DAF39BLL /* 512 */, 0x487FD5C66FF29281LL /* 513 */,
+ 0xE8A30667FCDCA83FLL /* 514 */, 0x2C9B4BE3D2FCCE63LL /* 515 */,
+ 0xDA3FF74B93FBBBC2LL /* 516 */, 0x2FA165D2FE70BA66LL /* 517 */,
+ 0xA103E279970E93D4LL /* 518 */, 0xBECDEC77B0E45E71LL /* 519 */,
+ 0xCFB41E723985E497LL /* 520 */, 0xB70AAA025EF75017LL /* 521 */,
+ 0xD42309F03840B8E0LL /* 522 */, 0x8EFC1AD035898579LL /* 523 */,
+ 0x96C6920BE2B2ABC5LL /* 524 */, 0x66AF4163375A9172LL /* 525 */,
+ 0x2174ABDCCA7127FBLL /* 526 */, 0xB33CCEA64A72FF41LL /* 527 */,
+ 0xF04A4933083066A5LL /* 528 */, 0x8D970ACDD7289AF5LL /* 529 */,
+ 0x8F96E8E031C8C25ELL /* 530 */, 0xF3FEC02276875D47LL /* 531 */,
+ 0xEC7BF310056190DDLL /* 532 */, 0xF5ADB0AEBB0F1491LL /* 533 */,
+ 0x9B50F8850FD58892LL /* 534 */, 0x4975488358B74DE8LL /* 535 */,
+ 0xA3354FF691531C61LL /* 536 */, 0x0702BBE481D2C6EELL /* 537 */,
+ 0x89FB24057DEDED98LL /* 538 */, 0xAC3075138596E902LL /* 539 */,
+ 0x1D2D3580172772EDLL /* 540 */, 0xEB738FC28E6BC30DLL /* 541 */,
+ 0x5854EF8F63044326LL /* 542 */, 0x9E5C52325ADD3BBELL /* 543 */,
+ 0x90AA53CF325C4623LL /* 544 */, 0xC1D24D51349DD067LL /* 545 */,
+ 0x2051CFEEA69EA624LL /* 546 */, 0x13220F0A862E7E4FLL /* 547 */,
+ 0xCE39399404E04864LL /* 548 */, 0xD9C42CA47086FCB7LL /* 549 */,
+ 0x685AD2238A03E7CCLL /* 550 */, 0x066484B2AB2FF1DBLL /* 551 */,
+ 0xFE9D5D70EFBF79ECLL /* 552 */, 0x5B13B9DD9C481854LL /* 553 */,
+ 0x15F0D475ED1509ADLL /* 554 */, 0x0BEBCD060EC79851LL /* 555 */,
+ 0xD58C6791183AB7F8LL /* 556 */, 0xD1187C5052F3EEE4LL /* 557 */,
+ 0xC95D1192E54E82FFLL /* 558 */, 0x86EEA14CB9AC6CA2LL /* 559 */,
+ 0x3485BEB153677D5DLL /* 560 */, 0xDD191D781F8C492ALL /* 561 */,
+ 0xF60866BAA784EBF9LL /* 562 */, 0x518F643BA2D08C74LL /* 563 */,
+ 0x8852E956E1087C22LL /* 564 */, 0xA768CB8DC410AE8DLL /* 565 */,
+ 0x38047726BFEC8E1ALL /* 566 */, 0xA67738B4CD3B45AALL /* 567 */,
+ 0xAD16691CEC0DDE19LL /* 568 */, 0xC6D4319380462E07LL /* 569 */,
+ 0xC5A5876D0BA61938LL /* 570 */, 0x16B9FA1FA58FD840LL /* 571 */,
+ 0x188AB1173CA74F18LL /* 572 */, 0xABDA2F98C99C021FLL /* 573 */,
+ 0x3E0580AB134AE816LL /* 574 */, 0x5F3B05B773645ABBLL /* 575 */,
+ 0x2501A2BE5575F2F6LL /* 576 */, 0x1B2F74004E7E8BA9LL /* 577 */,
+ 0x1CD7580371E8D953LL /* 578 */, 0x7F6ED89562764E30LL /* 579 */,
+ 0xB15926FF596F003DLL /* 580 */, 0x9F65293DA8C5D6B9LL /* 581 */,
+ 0x6ECEF04DD690F84CLL /* 582 */, 0x4782275FFF33AF88LL /* 583 */,
+ 0xE41433083F820801LL /* 584 */, 0xFD0DFE409A1AF9B5LL /* 585 */,
+ 0x4325A3342CDB396BLL /* 586 */, 0x8AE77E62B301B252LL /* 587 */,
+ 0xC36F9E9F6655615ALL /* 588 */, 0x85455A2D92D32C09LL /* 589 */,
+ 0xF2C7DEA949477485LL /* 590 */, 0x63CFB4C133A39EBALL /* 591 */,
+ 0x83B040CC6EBC5462LL /* 592 */, 0x3B9454C8FDB326B0LL /* 593 */,
+ 0x56F56A9E87FFD78CLL /* 594 */, 0x2DC2940D99F42BC6LL /* 595 */,
+ 0x98F7DF096B096E2DLL /* 596 */, 0x19A6E01E3AD852BFLL /* 597 */,
+ 0x42A99CCBDBD4B40BLL /* 598 */, 0xA59998AF45E9C559LL /* 599 */,
+ 0x366295E807D93186LL /* 600 */, 0x6B48181BFAA1F773LL /* 601 */,
+ 0x1FEC57E2157A0A1DLL /* 602 */, 0x4667446AF6201AD5LL /* 603 */,
+ 0xE615EBCACFB0F075LL /* 604 */, 0xB8F31F4F68290778LL /* 605 */,
+ 0x22713ED6CE22D11ELL /* 606 */, 0x3057C1A72EC3C93BLL /* 607 */,
+ 0xCB46ACC37C3F1F2FLL /* 608 */, 0xDBB893FD02AAF50ELL /* 609 */,
+ 0x331FD92E600B9FCFLL /* 610 */, 0xA498F96148EA3AD6LL /* 611 */,
+ 0xA8D8426E8B6A83EALL /* 612 */, 0xA089B274B7735CDCLL /* 613 */,
+ 0x87F6B3731E524A11LL /* 614 */, 0x118808E5CBC96749LL /* 615 */,
+ 0x9906E4C7B19BD394LL /* 616 */, 0xAFED7F7E9B24A20CLL /* 617 */,
+ 0x6509EADEEB3644A7LL /* 618 */, 0x6C1EF1D3E8EF0EDELL /* 619 */,
+ 0xB9C97D43E9798FB4LL /* 620 */, 0xA2F2D784740C28A3LL /* 621 */,
+ 0x7B8496476197566FLL /* 622 */, 0x7A5BE3E6B65F069DLL /* 623 */,
+ 0xF96330ED78BE6F10LL /* 624 */, 0xEEE60DE77A076A15LL /* 625 */,
+ 0x2B4BEE4AA08B9BD0LL /* 626 */, 0x6A56A63EC7B8894ELL /* 627 */,
+ 0x02121359BA34FEF4LL /* 628 */, 0x4CBF99F8283703FCLL /* 629 */,
+ 0x398071350CAF30C8LL /* 630 */, 0xD0A77A89F017687ALL /* 631 */,
+ 0xF1C1A9EB9E423569LL /* 632 */, 0x8C7976282DEE8199LL /* 633 */,
+ 0x5D1737A5DD1F7ABDLL /* 634 */, 0x4F53433C09A9FA80LL /* 635 */,
+ 0xFA8B0C53DF7CA1D9LL /* 636 */, 0x3FD9DCBC886CCB77LL /* 637 */,
+ 0xC040917CA91B4720LL /* 638 */, 0x7DD00142F9D1DCDFLL /* 639 */,
+ 0x8476FC1D4F387B58LL /* 640 */, 0x23F8E7C5F3316503LL /* 641 */,
+ 0x032A2244E7E37339LL /* 642 */, 0x5C87A5D750F5A74BLL /* 643 */,
+ 0x082B4CC43698992ELL /* 644 */, 0xDF917BECB858F63CLL /* 645 */,
+ 0x3270B8FC5BF86DDALL /* 646 */, 0x10AE72BB29B5DD76LL /* 647 */,
+ 0x576AC94E7700362BLL /* 648 */, 0x1AD112DAC61EFB8FLL /* 649 */,
+ 0x691BC30EC5FAA427LL /* 650 */, 0xFF246311CC327143LL /* 651 */,
+ 0x3142368E30E53206LL /* 652 */, 0x71380E31E02CA396LL /* 653 */,
+ 0x958D5C960AAD76F1LL /* 654 */, 0xF8D6F430C16DA536LL /* 655 */,
+ 0xC8FFD13F1BE7E1D2LL /* 656 */, 0x7578AE66004DDBE1LL /* 657 */,
+ 0x05833F01067BE646LL /* 658 */, 0xBB34B5AD3BFE586DLL /* 659 */,
+ 0x095F34C9A12B97F0LL /* 660 */, 0x247AB64525D60CA8LL /* 661 */,
+ 0xDCDBC6F3017477D1LL /* 662 */, 0x4A2E14D4DECAD24DLL /* 663 */,
+ 0xBDB5E6D9BE0A1EEBLL /* 664 */, 0x2A7E70F7794301ABLL /* 665 */,
+ 0xDEF42D8A270540FDLL /* 666 */, 0x01078EC0A34C22C1LL /* 667 */,
+ 0xE5DE511AF4C16387LL /* 668 */, 0x7EBB3A52BD9A330ALL /* 669 */,
+ 0x77697857AA7D6435LL /* 670 */, 0x004E831603AE4C32LL /* 671 */,
+ 0xE7A21020AD78E312LL /* 672 */, 0x9D41A70C6AB420F2LL /* 673 */,
+ 0x28E06C18EA1141E6LL /* 674 */, 0xD2B28CBD984F6B28LL /* 675 */,
+ 0x26B75F6C446E9D83LL /* 676 */, 0xBA47568C4D418D7FLL /* 677 */,
+ 0xD80BADBFE6183D8ELL /* 678 */, 0x0E206D7F5F166044LL /* 679 */,
+ 0xE258A43911CBCA3ELL /* 680 */, 0x723A1746B21DC0BCLL /* 681 */,
+ 0xC7CAA854F5D7CDD3LL /* 682 */, 0x7CAC32883D261D9CLL /* 683 */,
+ 0x7690C26423BA942CLL /* 684 */, 0x17E55524478042B8LL /* 685 */,
+ 0xE0BE477656A2389FLL /* 686 */, 0x4D289B5E67AB2DA0LL /* 687 */,
+ 0x44862B9C8FBBFD31LL /* 688 */, 0xB47CC8049D141365LL /* 689 */,
+ 0x822C1B362B91C793LL /* 690 */, 0x4EB14655FB13DFD8LL /* 691 */,
+ 0x1ECBBA0714E2A97BLL /* 692 */, 0x6143459D5CDE5F14LL /* 693 */,
+ 0x53A8FBF1D5F0AC89LL /* 694 */, 0x97EA04D81C5E5B00LL /* 695 */,
+ 0x622181A8D4FDB3F3LL /* 696 */, 0xE9BCD341572A1208LL /* 697 */,
+ 0x1411258643CCE58ALL /* 698 */, 0x9144C5FEA4C6E0A4LL /* 699 */,
+ 0x0D33D06565CF620FLL /* 700 */, 0x54A48D489F219CA1LL /* 701 */,
+ 0xC43E5EAC6D63C821LL /* 702 */, 0xA9728B3A72770DAFLL /* 703 */,
+ 0xD7934E7B20DF87EFLL /* 704 */, 0xE35503B61A3E86E5LL /* 705 */,
+ 0xCAE321FBC819D504LL /* 706 */, 0x129A50B3AC60BFA6LL /* 707 */,
+ 0xCD5E68EA7E9FB6C3LL /* 708 */, 0xB01C90199483B1C7LL /* 709 */,
+ 0x3DE93CD5C295376CLL /* 710 */, 0xAED52EDF2AB9AD13LL /* 711 */,
+ 0x2E60F512C0A07884LL /* 712 */, 0xBC3D86A3E36210C9LL /* 713 */,
+ 0x35269D9B163951CELL /* 714 */, 0x0C7D6E2AD0CDB5FALL /* 715 */,
+ 0x59E86297D87F5733LL /* 716 */, 0x298EF221898DB0E7LL /* 717 */,
+ 0x55000029D1A5AA7ELL /* 718 */, 0x8BC08AE1B5061B45LL /* 719 */,
+ 0xC2C31C2B6C92703ALL /* 720 */, 0x94CC596BAF25EF42LL /* 721 */,
+ 0x0A1D73DB22540456LL /* 722 */, 0x04B6A0F9D9C4179ALL /* 723 */,
+ 0xEFFDAFA2AE3D3C60LL /* 724 */, 0xF7C8075BB49496C4LL /* 725 */,
+ 0x9CC5C7141D1CD4E3LL /* 726 */, 0x78BD1638218E5534LL /* 727 */,
+ 0xB2F11568F850246ALL /* 728 */, 0xEDFABCFA9502BC29LL /* 729 */,
+ 0x796CE5F2DA23051BLL /* 730 */, 0xAAE128B0DC93537CLL /* 731 */,
+ 0x3A493DA0EE4B29AELL /* 732 */, 0xB5DF6B2C416895D7LL /* 733 */,
+ 0xFCABBD25122D7F37LL /* 734 */, 0x70810B58105DC4B1LL /* 735 */,
+ 0xE10FDD37F7882A90LL /* 736 */, 0x524DCAB5518A3F5CLL /* 737 */,
+ 0x3C9E85878451255BLL /* 738 */, 0x4029828119BD34E2LL /* 739 */,
+ 0x74A05B6F5D3CECCBLL /* 740 */, 0xB610021542E13ECALL /* 741 */,
+ 0x0FF979D12F59E2ACLL /* 742 */, 0x6037DA27E4F9CC50LL /* 743 */,
+ 0x5E92975A0DF1847DLL /* 744 */, 0xD66DE190D3E623FELL /* 745 */,
+ 0x5032D6B87B568048LL /* 746 */, 0x9A36B7CE8235216ELL /* 747 */,
+ 0x80272A7A24F64B4ALL /* 748 */, 0x93EFED8B8C6916F7LL /* 749 */,
+ 0x37DDBFF44CCE1555LL /* 750 */, 0x4B95DB5D4B99BD25LL /* 751 */,
+ 0x92D3FDA169812FC0LL /* 752 */, 0xFB1A4A9A90660BB6LL /* 753 */,
+ 0x730C196946A4B9B2LL /* 754 */, 0x81E289AA7F49DA68LL /* 755 */,
+ 0x64669A0F83B1A05FLL /* 756 */, 0x27B3FF7D9644F48BLL /* 757 */,
+ 0xCC6B615C8DB675B3LL /* 758 */, 0x674F20B9BCEBBE95LL /* 759 */,
+ 0x6F31238275655982LL /* 760 */, 0x5AE488713E45CF05LL /* 761 */,
+ 0xBF619F9954C21157LL /* 762 */, 0xEABAC46040A8EAE9LL /* 763 */,
+ 0x454C6FE9F2C0C1CDLL /* 764 */, 0x419CF6496412691CLL /* 765 */,
+ 0xD3DC3BEF265B0F70LL /* 766 */, 0x6D0E60F5C3578A9ELL /* 767 */,
+ 0x5B0E608526323C55LL /* 768 */, 0x1A46C1A9FA1B59F5LL /* 769 */,
+ 0xA9E245A17C4C8FFALL /* 770 */, 0x65CA5159DB2955D7LL /* 771 */,
+ 0x05DB0A76CE35AFC2LL /* 772 */, 0x81EAC77EA9113D45LL /* 773 */,
+ 0x528EF88AB6AC0A0DLL /* 774 */, 0xA09EA253597BE3FFLL /* 775 */,
+ 0x430DDFB3AC48CD56LL /* 776 */, 0xC4B3A67AF45CE46FLL /* 777 */,
+ 0x4ECECFD8FBE2D05ELL /* 778 */, 0x3EF56F10B39935F0LL /* 779 */,
+ 0x0B22D6829CD619C6LL /* 780 */, 0x17FD460A74DF2069LL /* 781 */,
+ 0x6CF8CC8E8510ED40LL /* 782 */, 0xD6C824BF3A6ECAA7LL /* 783 */,
+ 0x61243D581A817049LL /* 784 */, 0x048BACB6BBC163A2LL /* 785 */,
+ 0xD9A38AC27D44CC32LL /* 786 */, 0x7FDDFF5BAAF410ABLL /* 787 */,
+ 0xAD6D495AA804824BLL /* 788 */, 0xE1A6A74F2D8C9F94LL /* 789 */,
+ 0xD4F7851235DEE8E3LL /* 790 */, 0xFD4B7F886540D893LL /* 791 */,
+ 0x247C20042AA4BFDALL /* 792 */, 0x096EA1C517D1327CLL /* 793 */,
+ 0xD56966B4361A6685LL /* 794 */, 0x277DA5C31221057DLL /* 795 */,
+ 0x94D59893A43ACFF7LL /* 796 */, 0x64F0C51CCDC02281LL /* 797 */,
+ 0x3D33BCC4FF6189DBLL /* 798 */, 0xE005CB184CE66AF1LL /* 799 */,
+ 0xFF5CCD1D1DB99BEALL /* 800 */, 0xB0B854A7FE42980FLL /* 801 */,
+ 0x7BD46A6A718D4B9FLL /* 802 */, 0xD10FA8CC22A5FD8CLL /* 803 */,
+ 0xD31484952BE4BD31LL /* 804 */, 0xC7FA975FCB243847LL /* 805 */,
+ 0x4886ED1E5846C407LL /* 806 */, 0x28CDDB791EB70B04LL /* 807 */,
+ 0xC2B00BE2F573417FLL /* 808 */, 0x5C9590452180F877LL /* 809 */,
+ 0x7A6BDDFFF370EB00LL /* 810 */, 0xCE509E38D6D9D6A4LL /* 811 */,
+ 0xEBEB0F00647FA702LL /* 812 */, 0x1DCC06CF76606F06LL /* 813 */,
+ 0xE4D9F28BA286FF0ALL /* 814 */, 0xD85A305DC918C262LL /* 815 */,
+ 0x475B1D8732225F54LL /* 816 */, 0x2D4FB51668CCB5FELL /* 817 */,
+ 0xA679B9D9D72BBA20LL /* 818 */, 0x53841C0D912D43A5LL /* 819 */,
+ 0x3B7EAA48BF12A4E8LL /* 820 */, 0x781E0E47F22F1DDFLL /* 821 */,
+ 0xEFF20CE60AB50973LL /* 822 */, 0x20D261D19DFFB742LL /* 823 */,
+ 0x16A12B03062A2E39LL /* 824 */, 0x1960EB2239650495LL /* 825 */,
+ 0x251C16FED50EB8B8LL /* 826 */, 0x9AC0C330F826016ELL /* 827 */,
+ 0xED152665953E7671LL /* 828 */, 0x02D63194A6369570LL /* 829 */,
+ 0x5074F08394B1C987LL /* 830 */, 0x70BA598C90B25CE1LL /* 831 */,
+ 0x794A15810B9742F6LL /* 832 */, 0x0D5925E9FCAF8C6CLL /* 833 */,
+ 0x3067716CD868744ELL /* 834 */, 0x910AB077E8D7731BLL /* 835 */,
+ 0x6A61BBDB5AC42F61LL /* 836 */, 0x93513EFBF0851567LL /* 837 */,
+ 0xF494724B9E83E9D5LL /* 838 */, 0xE887E1985C09648DLL /* 839 */,
+ 0x34B1D3C675370CFDLL /* 840 */, 0xDC35E433BC0D255DLL /* 841 */,
+ 0xD0AAB84234131BE0LL /* 842 */, 0x08042A50B48B7EAFLL /* 843 */,
+ 0x9997C4EE44A3AB35LL /* 844 */, 0x829A7B49201799D0LL /* 845 */,
+ 0x263B8307B7C54441LL /* 846 */, 0x752F95F4FD6A6CA6LL /* 847 */,
+ 0x927217402C08C6E5LL /* 848 */, 0x2A8AB754A795D9EELL /* 849 */,
+ 0xA442F7552F72943DLL /* 850 */, 0x2C31334E19781208LL /* 851 */,
+ 0x4FA98D7CEAEE6291LL /* 852 */, 0x55C3862F665DB309LL /* 853 */,
+ 0xBD0610175D53B1F3LL /* 854 */, 0x46FE6CB840413F27LL /* 855 */,
+ 0x3FE03792DF0CFA59LL /* 856 */, 0xCFE700372EB85E8FLL /* 857 */,
+ 0xA7BE29E7ADBCE118LL /* 858 */, 0xE544EE5CDE8431DDLL /* 859 */,
+ 0x8A781B1B41F1873ELL /* 860 */, 0xA5C94C78A0D2F0E7LL /* 861 */,
+ 0x39412E2877B60728LL /* 862 */, 0xA1265EF3AFC9A62CLL /* 863 */,
+ 0xBCC2770C6A2506C5LL /* 864 */, 0x3AB66DD5DCE1CE12LL /* 865 */,
+ 0xE65499D04A675B37LL /* 866 */, 0x7D8F523481BFD216LL /* 867 */,
+ 0x0F6F64FCEC15F389LL /* 868 */, 0x74EFBE618B5B13C8LL /* 869 */,
+ 0xACDC82B714273E1DLL /* 870 */, 0xDD40BFE003199D17LL /* 871 */,
+ 0x37E99257E7E061F8LL /* 872 */, 0xFA52626904775AAALL /* 873 */,
+ 0x8BBBF63A463D56F9LL /* 874 */, 0xF0013F1543A26E64LL /* 875 */,
+ 0xA8307E9F879EC898LL /* 876 */, 0xCC4C27A4150177CCLL /* 877 */,
+ 0x1B432F2CCA1D3348LL /* 878 */, 0xDE1D1F8F9F6FA013LL /* 879 */,
+ 0x606602A047A7DDD6LL /* 880 */, 0xD237AB64CC1CB2C7LL /* 881 */,
+ 0x9B938E7225FCD1D3LL /* 882 */, 0xEC4E03708E0FF476LL /* 883 */,
+ 0xFEB2FBDA3D03C12DLL /* 884 */, 0xAE0BCED2EE43889ALL /* 885 */,
+ 0x22CB8923EBFB4F43LL /* 886 */, 0x69360D013CF7396DLL /* 887 */,
+ 0x855E3602D2D4E022LL /* 888 */, 0x073805BAD01F784CLL /* 889 */,
+ 0x33E17A133852F546LL /* 890 */, 0xDF4874058AC7B638LL /* 891 */,
+ 0xBA92B29C678AA14ALL /* 892 */, 0x0CE89FC76CFAADCDLL /* 893 */,
+ 0x5F9D4E0908339E34LL /* 894 */, 0xF1AFE9291F5923B9LL /* 895 */,
+ 0x6E3480F60F4A265FLL /* 896 */, 0xEEBF3A2AB29B841CLL /* 897 */,
+ 0xE21938A88F91B4ADLL /* 898 */, 0x57DFEFF845C6D3C3LL /* 899 */,
+ 0x2F006B0BF62CAAF2LL /* 900 */, 0x62F479EF6F75EE78LL /* 901 */,
+ 0x11A55AD41C8916A9LL /* 902 */, 0xF229D29084FED453LL /* 903 */,
+ 0x42F1C27B16B000E6LL /* 904 */, 0x2B1F76749823C074LL /* 905 */,
+ 0x4B76ECA3C2745360LL /* 906 */, 0x8C98F463B91691BDLL /* 907 */,
+ 0x14BCC93CF1ADE66ALL /* 908 */, 0x8885213E6D458397LL /* 909 */,
+ 0x8E177DF0274D4711LL /* 910 */, 0xB49B73B5503F2951LL /* 911 */,
+ 0x10168168C3F96B6BLL /* 912 */, 0x0E3D963B63CAB0AELL /* 913 */,
+ 0x8DFC4B5655A1DB14LL /* 914 */, 0xF789F1356E14DE5CLL /* 915 */,
+ 0x683E68AF4E51DAC1LL /* 916 */, 0xC9A84F9D8D4B0FD9LL /* 917 */,
+ 0x3691E03F52A0F9D1LL /* 918 */, 0x5ED86E46E1878E80LL /* 919 */,
+ 0x3C711A0E99D07150LL /* 920 */, 0x5A0865B20C4E9310LL /* 921 */,
+ 0x56FBFC1FE4F0682ELL /* 922 */, 0xEA8D5DE3105EDF9BLL /* 923 */,
+ 0x71ABFDB12379187ALL /* 924 */, 0x2EB99DE1BEE77B9CLL /* 925 */,
+ 0x21ECC0EA33CF4523LL /* 926 */, 0x59A4D7521805C7A1LL /* 927 */,
+ 0x3896F5EB56AE7C72LL /* 928 */, 0xAA638F3DB18F75DCLL /* 929 */,
+ 0x9F39358DABE9808ELL /* 930 */, 0xB7DEFA91C00B72ACLL /* 931 */,
+ 0x6B5541FD62492D92LL /* 932 */, 0x6DC6DEE8F92E4D5BLL /* 933 */,
+ 0x353F57ABC4BEEA7ELL /* 934 */, 0x735769D6DA5690CELL /* 935 */,
+ 0x0A234AA642391484LL /* 936 */, 0xF6F9508028F80D9DLL /* 937 */,
+ 0xB8E319A27AB3F215LL /* 938 */, 0x31AD9C1151341A4DLL /* 939 */,
+ 0x773C22A57BEF5805LL /* 940 */, 0x45C7561A07968633LL /* 941 */,
+ 0xF913DA9E249DBE36LL /* 942 */, 0xDA652D9B78A64C68LL /* 943 */,
+ 0x4C27A97F3BC334EFLL /* 944 */, 0x76621220E66B17F4LL /* 945 */,
+ 0x967743899ACD7D0BLL /* 946 */, 0xF3EE5BCAE0ED6782LL /* 947 */,
+ 0x409F753600C879FCLL /* 948 */, 0x06D09A39B5926DB6LL /* 949 */,
+ 0x6F83AEB0317AC588LL /* 950 */, 0x01E6CA4A86381F21LL /* 951 */,
+ 0x66FF3462D19F3025LL /* 952 */, 0x72207C24DDFD3BFBLL /* 953 */,
+ 0x4AF6B6D3E2ECE2EBLL /* 954 */, 0x9C994DBEC7EA08DELL /* 955 */,
+ 0x49ACE597B09A8BC4LL /* 956 */, 0xB38C4766CF0797BALL /* 957 */,
+ 0x131B9373C57C2A75LL /* 958 */, 0xB1822CCE61931E58LL /* 959 */,
+ 0x9D7555B909BA1C0CLL /* 960 */, 0x127FAFDD937D11D2LL /* 961 */,
+ 0x29DA3BADC66D92E4LL /* 962 */, 0xA2C1D57154C2ECBCLL /* 963 */,
+ 0x58C5134D82F6FE24LL /* 964 */, 0x1C3AE3515B62274FLL /* 965 */,
+ 0xE907C82E01CB8126LL /* 966 */, 0xF8ED091913E37FCBLL /* 967 */,
+ 0x3249D8F9C80046C9LL /* 968 */, 0x80CF9BEDE388FB63LL /* 969 */,
+ 0x1881539A116CF19ELL /* 970 */, 0x5103F3F76BD52457LL /* 971 */,
+ 0x15B7E6F5AE47F7A8LL /* 972 */, 0xDBD7C6DED47E9CCFLL /* 973 */,
+ 0x44E55C410228BB1ALL /* 974 */, 0xB647D4255EDB4E99LL /* 975 */,
+ 0x5D11882BB8AAFC30LL /* 976 */, 0xF5098BBB29D3212ALL /* 977 */,
+ 0x8FB5EA14E90296B3LL /* 978 */, 0x677B942157DD025ALL /* 979 */,
+ 0xFB58E7C0A390ACB5LL /* 980 */, 0x89D3674C83BD4A01LL /* 981 */,
+ 0x9E2DA4DF4BF3B93BLL /* 982 */, 0xFCC41E328CAB4829LL /* 983 */,
+ 0x03F38C96BA582C52LL /* 984 */, 0xCAD1BDBD7FD85DB2LL /* 985 */,
+ 0xBBB442C16082AE83LL /* 986 */, 0xB95FE86BA5DA9AB0LL /* 987 */,
+ 0xB22E04673771A93FLL /* 988 */, 0x845358C9493152D8LL /* 989 */,
+ 0xBE2A488697B4541ELL /* 990 */, 0x95A2DC2DD38E6966LL /* 991 */,
+ 0xC02C11AC923C852BLL /* 992 */, 0x2388B1990DF2A87BLL /* 993 */,
+ 0x7C8008FA1B4F37BELL /* 994 */, 0x1F70D0C84D54E503LL /* 995 */,
+ 0x5490ADEC7ECE57D4LL /* 996 */, 0x002B3C27D9063A3ALL /* 997 */,
+ 0x7EAEA3848030A2BFLL /* 998 */, 0xC602326DED2003C0LL /* 999 */,
+ 0x83A7287D69A94086LL /* 1000 */, 0xC57A5FCB30F57A8ALL /* 1001 */,
+ 0xB56844E479EBE779LL /* 1002 */, 0xA373B40F05DCBCE9LL /* 1003 */,
+ 0xD71A786E88570EE2LL /* 1004 */, 0x879CBACDBDE8F6A0LL /* 1005 */,
+ 0x976AD1BCC164A32FLL /* 1006 */, 0xAB21E25E9666D78BLL /* 1007 */,
+ 0x901063AAE5E5C33CLL /* 1008 */, 0x9818B34448698D90LL /* 1009 */,
+ 0xE36487AE3E1E8ABBLL /* 1010 */, 0xAFBDF931893BDCB4LL /* 1011 */,
+ 0x6345A0DC5FBBD519LL /* 1012 */, 0x8628FE269B9465CALL /* 1013 */,
+ 0x1E5D01603F9C51ECLL /* 1014 */, 0x4DE44006A15049B7LL /* 1015 */,
+ 0xBF6C70E5F776CBB1LL /* 1016 */, 0x411218F2EF552BEDLL /* 1017 */,
+ 0xCB0C0708705A36A3LL /* 1018 */, 0xE74D14754F986044LL /* 1019 */,
+ 0xCD56D9430EA8280ELL /* 1020 */, 0xC12591D7535F5065LL /* 1021 */,
+ 0xC83223F1720AEF96LL /* 1022 */, 0xC3A0396F7363A51FLL /* 1023 */
+};
+
+/* The following macro denotes that an optimization */
+/* for Alpha is required. It is used only for */
+/* optimization of time. Otherwise it does nothing. */
+#ifdef _LP64
+#define OPTIMIZE_FOR_LP64
+#endif
+
+/* NOTE that this code is NOT FULLY OPTIMIZED for any */
+/* machine. Assembly code might be much faster on some */
+/* machines, especially if the code is compiled with */
+/* gcc. */
+
+/* The number of passes of the hash function. */
+/* Three passes are recommended. */
+/* Use four passes when you need extra security. */
+/* Must be at least three. */
+#define PASSES 3
+
+#define T1 (table)
+#define T2 (table+256)
+#define T3 (table+(256*2))
+#define T4 (table+(256*3))
+
+#define SAVE_ABC do { \
+ aa = a; \
+ bb = b; \
+ cc = c; \
+} while (/*CONSTCOND*/0)
+
+#ifdef OPTIMIZE_FOR_LP64
+/* This is the official definition of round */
+#define ROUND(a,b,c,x,mul) do { \
+ c ^= x; \
+ a -= T1[((c)>>(0*8))&0xFF] ^ T2[((c)>>(2*8))&0xFF] ^ \
+ T3[((c)>>(4*8))&0xFF] ^ T4[((c)>>(6*8))&0xFF] ; \
+ b += T4[((c)>>(1*8))&0xFF] ^ T3[((c)>>(3*8))&0xFF] ^ \
+ T2[((c)>>(5*8))&0xFF] ^ T1[((c)>>(7*8))&0xFF] ; \
+ b *= mul; \
+} while (/*CONSTCOND*/ 0)
+#else
+/* This code works faster when compiled on 32-bit machines */
+/* (but works slower on Alpha) */
+#define ROUND(a,b,c,x,mul) do { \
+ c ^= x; \
+ a -= T1[(uint8_t)(c)] ^ \
+ T2[(const uint8_t)(((uint32_t)(c))>>(2*8))] ^ \
+ T3[(const uint8_t)((c)>>(4*8))] ^ \
+ T4[(const uint8_t)(((uint32_t)((c)>>(4*8)))>>(2*8))] ; \
+ b += T4[(uint8_t)(((uint32_t)(c))>>(1*8))] ^ \
+ T3[(const uint8_t)(((uint32_t)(c))>>(3*8))] ^ \
+ T2[(const uint8_t)(((uint32_t)((c)>>(4*8)))>>(1*8))] ^ \
+ T1[(const uint8_t)(((uint32_t)((c)>>(4*8)))>>(3*8))]; \
+ b *= mul; \
+} while (/*CONSTCOND*/0)
+#endif
+
+#define PASS(a,b,c,mul) do { \
+ ROUND(a,b,c,x0,mul); \
+ ROUND(b,c,a,x1,mul); \
+ ROUND(c,a,b,x2,mul); \
+ ROUND(a,b,c,x3,mul); \
+ ROUND(b,c,a,x4,mul); \
+ ROUND(c,a,b,x5,mul); \
+ ROUND(a,b,c,x6,mul); \
+ ROUND(b,c,a,x7,mul); \
+} while (/*CONSTCOND*/ 0)
+
+#define KEY_SCHEDULE do { \
+ x0 -= x7 ^ (uint64_t)0xA5A5A5A5A5A5A5A5LL; \
+ x1 ^= x0; \
+ x2 += x1; \
+ x3 -= x2 ^ ((~x1)<<19); \
+ x4 ^= x3; \
+ x5 += x4; \
+ x6 -= x5 ^ ((~x4)>>23); \
+ x7 ^= x6; \
+ x0 += x7; \
+ x1 -= x0 ^ ((~x7)<<19); \
+ x2 ^= x1; \
+ x3 += x2; \
+ x4 -= x3 ^ ((~x2)>>23); \
+ x5 ^= x4; \
+ x6 += x5; \
+ x7 -= x6 ^ (uint64_t)0x0123456789ABCDEFLL; \
+} while (/*CONSTCOND*/ 0)
+
+#define FEEDFORWARD do { \
+ a ^= aa; \
+ b -= bb; \
+ c += cc; \
+} while (/*CONSTCOND*/ 0)
+
+#ifdef OPTIMIZE_FOR_LP64
+/* The loop is unrolled: works better on Alpha */
+#define COMPRESS do { \
+ SAVE_ABC; \
+ PASS(a,b,c,5); \
+ KEY_SCHEDULE; \
+ PASS(c,a,b,7); \
+ KEY_SCHEDULE; \
+ PASS(b,c,a,9); \
+ for (pass_no = 3; pass_no < PASSES; pass_no++) { \
+ KEY_SCHEDULE; \
+ PASS(a,b,c,9); \
+ tmpa = a; a = c; c = b; b = tmpa; \
+ } \
+ FEEDFORWARD; \
+} while (/*CONSTCOND*/ 0)
+#else
+/* loop: works better on PC and Sun (smaller cache?) */
+#define COMPRESS do { \
+ SAVE_ABC; \
+ for (pass_no = 0; pass_no < PASSES; pass_no++) { \
+ if (pass_no != 0) { \
+ KEY_SCHEDULE; \
+ } \
+ PASS(a,b,c,(pass_no==0?5:pass_no==1?7:9)); \
+ tmpa = a; a = c; c = b; b = tmpa; \
+ } \
+ FEEDFORWARD; \
+} while (/*CONSTCOND*/0)
+#endif
+
+#define TIGER_COMPRESS_MACRO(str, state) do { \
+ uint64_t a, b, c, tmpa; \
+ uint64_t aa, bb, cc; \
+ uint64_t x0, x1, x2, x3, x4, x5, x6, x7; \
+ int pass_no; \
+ \
+ a = state[0]; \
+ b = state[1]; \
+ c = state[2]; \
+ \
+ x0 = str[0]; x1 = str[1]; x2 = str[2]; x3 = str[3]; \
+ x4 = str[4]; x5 = str[5]; x6 = str[6]; x7 = str[7]; \
+ \
+ COMPRESS; \
+ \
+ state[0] = a; \
+ state[1] = b; \
+ state[2] = c; \
+} while (/*CONSTCOND*/ 0)
+
+#ifdef OPTIMIZE_FOR_LP64
+/* The compress function is inlined: works better on Alpha. */
+/* Still leaves the function above in the code, in case some other */
+/* module calls it directly. */
+#define tiger_compress(str, state) \
+ TIGER_COMPRESS_MACRO(((const uint64_t*)(const void *)str), ((uint64_t*)(void *)state))
+#else
+/* The compress function is a function. Requires smaller cache? */
+static void
+tiger_compress(const uint64_t *str, uint64_t state[3])
+{
+ TIGER_COMPRESS_MACRO(((const uint64_t*)str), ((uint64_t*)state));
+}
+#endif
+
+/* weird function to format 8 raw bytes to 16 formatted hex chars */
+static void
+sprint_uint64(char *buf, uint64_t val)
+{
+ static const char hexdigits[] = "0123456789abcdef";
+ int indian = 1;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ if (IS_LITTLE_ENDIAN(indian)) {
+ buf[2 * (7 - i)] = hexdigits[(val >> (56 - 8 * i + 4)) & 15];
+ buf[(2 * (7 - i)) + 1] = hexdigits[(val >> (56 - 8 * i)) & 15];
+ } else {
+ buf[2 * i] = hexdigits[(val >> (56 - 8 * i + 4)) & 15];
+ buf[(2 * i) + 1] = hexdigits[(val >> (56 - 8 * i)) & 15];
+ }
+ }
+}
+
+/* common function to initialise context */
+static void
+initcontext(TIGER_CTX *ctx, uint8_t pad)
+{
+ (void) memset(ctx, 0x0, sizeof(*ctx));
+ ctx->ctx[0] = 0x0123456789ABCDEFLL;
+ ctx->ctx[1] = 0xFEDCBA9876543210LL;
+ ctx->ctx[2] = 0xF096A5B4C3B2E187LL;
+ ctx->init = 1;
+ ctx->pad = pad;
+}
+
+/* set the version number (0 is same as 1 for Tiger) */
+static int
+setversion(TIGER_CTX *ctx, int version)
+{
+ switch(version) {
+ case 0:
+ case 1:
+ initcontext(ctx, 0x01);
+ break;
+ case 2:
+ initcontext(ctx, 0x80);
+ break;
+ default:
+ (void) fprintf(stderr, "unknown version %d\n", version);
+ return 0;
+ }
+ return 1;
+}
+
+/*****************************************************************************/
+
+void
+TIGER_Init(TIGER_CTX *ctx)
+{
+ if (ctx) {
+ initcontext(ctx, 0x01);
+ }
+}
+
+void
+TIGER2_Init(TIGER_CTX *ctx)
+{
+ if (ctx) {
+ initcontext(ctx, 0x80);
+ }
+}
+
+void
+TIGER_Update(TIGER_CTX *ctx, const void *data, size_t length)
+{
+ const uint64_t *str = (const uint64_t *)data;
+ uint64_t i;
+ uint64_t j;
+ union {
+ uint8_t temp8[64];
+ uint64_t temp64[8];
+ } u;
+ int indian = 1;
+
+ if (ctx == NULL || data == NULL) {
+ return;
+ }
+ for(i = length; i >= 64; i -= 64) {
+ if (IS_BIG_ENDIAN(indian)) {
+ for (j = 0; j < 64; j++) {
+ u.temp8[j ^ 7] = ((const uint8_t *)(const void *)str)[j];
+ }
+ tiger_compress(u.temp64, ctx->ctx);
+ } else {
+ tiger_compress(str, ctx->ctx);
+ }
+ str += 8;
+ }
+ if (IS_BIG_ENDIAN(indian)) {
+ for (j = 0; j < i; j++) {
+ u.temp8[j ^ 7] = ((const uint8_t*)(const void *)str)[j];
+ }
+ u.temp8[j ^ 7] = ctx->pad;
+ for (j++; j&7; j++) {
+ u.temp8[j ^ 7] = 0;
+ }
+ } else {
+ for (j = 0; j < i; j++) {
+ u.temp8[j] = ((const uint8_t*)(const void *)str)[j];
+ }
+ u.temp8[j++] = ctx->pad;
+ for (; j&7; j++) {
+ u.temp8[j] = 0;
+ }
+ }
+ if (j > 56) {
+ for (; j < 64; j++) {
+ u.temp8[j] = 0;
+ }
+ tiger_compress(u.temp64, ctx->ctx);
+ j = 0;
+ }
+ for (; j < 56; j++) {
+ u.temp8[j] = 0;
+ }
+ ((uint64_t *)(void *)(&(u.temp8[56])))[0] = ((uint64_t)length) << 3;
+ tiger_compress(u.temp64, ctx->ctx);
+}
+
+void
+TIGER_Final(uint8_t *digest, TIGER_CTX *ctx)
+{
+ uint64_t le[3];
+ int indian = 1;
+ int i;
+
+ if (digest == NULL || ctx == NULL) {
+ return;
+ }
+ if (!ctx->init) {
+ TIGER_Init(ctx);
+ TIGER_Update(ctx, NULL, 0);
+ }
+ if (IS_LITTLE_ENDIAN(indian)) {
+ for (i = 0; i < 3; ++i) {
+ le[i] = (uint64_t)BSWAP64(ctx->ctx[i]);
+ }
+ (void) memcpy(digest, le, 3 * sizeof(le[0]));
+ } else {
+ (void) memcpy(digest, ctx->ctx, 3 * sizeof(ctx->ctx[0]));
+ }
+}
+
+char *
+TIGER_End(TIGER_CTX *ctx, char *buf)
+{
+ int i;
+
+ if (ctx == NULL) {
+ return NULL;
+ }
+ if (buf == NULL && (buf = calloc(1, 49)) == NULL) {
+ return NULL;
+ }
+ if (!ctx->init) {
+ TIGER_Init(ctx);
+ TIGER_Update(ctx, NULL, 0);
+ }
+ for (i = 0; i < 3; ++i) {
+ sprint_uint64(buf + i * 16, ctx->ctx[i]);
+ }
+ buf[16 * i] = 0x0;
+ return buf;
+}
+
+char *
+TIGER_File(char *filename, char *buf, int version)
+{
+ TIGER_CTX ctx;
+ uint8_t buffer[BUFSIZ];
+ ssize_t num;
+ int fd;
+ int oerrno;
+
+ if (filename == NULL || buf == NULL || !setversion(&ctx, version)) {
+ return NULL;
+ }
+ if ((fd = open(filename, O_RDONLY)) < 0) {
+ return NULL;
+ }
+ while ((num = read(fd, buffer, sizeof(buffer))) > 0) {
+ TIGER_Update(&ctx, buffer, (size_t)num);
+ }
+ oerrno = errno;
+ close(fd);
+ errno = oerrno;
+ return (num < 0) ? NULL : TIGER_End(&ctx, buf);
+}
+
+char *
+TIGER_Data(const uint8_t *data, size_t len, char *buf, int version)
+{
+ TIGER_CTX ctx;
+
+ if (data == NULL || buf == NULL || !setversion(&ctx, version)) {
+ return NULL;
+ }
+ TIGER_Update(&ctx, data, len);
+ return TIGER_End(&ctx, buf);
+}
diff --git a/security/libnetpgpverify/files/src/libdigest/tiger.h b/security/libnetpgpverify/files/src/libdigest/tiger.h
new file mode 100644
index 00000000000..ff25cf949d3
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libdigest/tiger.h
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2005-2011 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.
+ */
+#ifndef TIGER_H_
+#define TIGER_H_
+
+#include <sys/types.h>
+
+#include <inttypes.h>
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+#define TIGER_DIGEST_LENGTH 24
+#define TIGER_DIGEST_STRING_LENGTH ((TIGER_DIGEST_LENGTH * 2) + 1)
+
+typedef struct TIGER_CTX {
+ uint64_t ctx[3];
+ int init;
+ uint8_t pad;
+} TIGER_CTX;
+
+void TIGER_Init(TIGER_CTX *);
+void TIGER2_Init(TIGER_CTX *);
+void TIGER_Update(TIGER_CTX *, const void *, size_t);
+void TIGER_Final(uint8_t *, TIGER_CTX *);
+
+char *TIGER_End(TIGER_CTX *, char *);
+
+char *TIGER_File(char *, char *, int);
+char *TIGER_Data(const uint8_t *, size_t, char *, int);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/librsa/Makefile b/security/libnetpgpverify/files/src/librsa/Makefile
new file mode 100644
index 00000000000..a60ebfd462f
--- /dev/null
+++ b/security/libnetpgpverify/files/src/librsa/Makefile
@@ -0,0 +1,10 @@
+LIB=netrsa
+SRCS=rsa.c stubs.c
+MKMAN=no
+WARNS=4
+CPPFLAGS+=-I${.CURDIR}/../bn
+
+INCS=rsa.h
+INCSDIR=/usr/include/netpgp
+
+.include <bsd.lib.mk>
diff --git a/security/libnetpgpverify/files/src/librsa/libnetpgprsa.3 b/security/libnetpgpverify/files/src/librsa/libnetpgprsa.3
new file mode 100644
index 00000000000..4d5ef2444cc
--- /dev/null
+++ b/security/libnetpgpverify/files/src/librsa/libnetpgprsa.3
@@ -0,0 +1,113 @@
+.\" $NetBSD: libnetpgprsa.3,v 1.1.1.1 2013/02/23 21:04:26 agc Exp $
+.\"
+.\" Copyright (c) 2012 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.
+.\"
+.Dd April 13, 2012
+.Dt LIBNETPGPRSA 3
+.Os
+.Sh NAME
+.Nm libnetpgprsa
+.Nd BIGNUM library of multi-precision integers
+.Sh LIBRARY
+.Lb libnetpgprsa
+.Sh SYNOPSIS
+.In netpgp/rsa.h
+.Ft RSA *
+.Fo RSA_new
+.Fa "void"
+.Fc
+.Ft int
+.Fo RSA_size
+.Fa "const RSA *rsa"
+.Fc
+.Ft void
+.Fo RSA_free
+.Fa "RSA *rsa"
+.Fc
+.Ft int
+.Fo RSA_check_key
+.Fa "RSA *rsa"
+.Fc
+.Ft RSA *
+.Fo RSA_generate_key
+.Fa "int num" "unsigned long e" "void (*callback)(int, int, void *)" "void *callbackarg"
+.Fc
+.Ft int
+.Fo RSA_public_encrypt
+.Fa "int siglen" "const uint8_t *signature" "uint8_t *to" "RSA *rsa" "int padding"
+.Fc
+.Ft int
+.Fo RSA_private_encrypt
+.Fa "int siglen" "const uint8_t *signature" "uint8_t *to" "RSA *rsa" "int padding"
+.Fc
+.Ft int
+.Fo RSA_private_decrypt
+.Fa "int siglen" "const uint8_t *signature" "uint8_t *to" "RSA *rsa" "int padding"
+.Fc
+.Pp
+.Ft DSA *
+.Fo DSA_new
+.Fa "void"
+.Fc
+.Ft int
+.Fo DSA_size
+.Fa "const DSA *dsa"
+.Fc
+.Ft void
+.Fo DSA_free
+.Fa "DSA *dsa"
+.Fc
+.Ft DSA_SIG *
+.Fo DSA_SIG_new
+.Fa "void"
+.Fc
+.Ft void
+.Fo DSA_SIG_free
+.Fa "DSA_SIG *sig"
+.Fc
+.Ft int
+.Fo DSA_do_verify
+.Fa "const unsigned char *digest" "int digestlen" "DSA_SIG *sig" "DSA *dsa"
+.Fc
+.Ft int
+.Fo DSA_do_sign
+.Fa "const unsigned char *digest" "int digestlen" "DSA *dsa"
+.Fc
+.Sh DESCRIPTION
+.Nm
+is a small library which provides RSA signing,
+encryption and decryption, and DSA signing.
+RSA and DSA verification are provided by the
+.Xr libnetpgpverify 3
+library.
+.Sh SEE ALSO
+.Xr libnetpgpbn 3 ,
+.Xr libnetpgpverify 3
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Nx 7.0 .
+.Sh AUTHORS
+.An Alistair Crooks Aq agc@NetBSD.org
diff --git a/security/libnetpgpverify/files/src/librsa/rsa.c b/security/libnetpgpverify/files/src/librsa/rsa.c
new file mode 100644
index 00000000000..d25ebb2a2b9
--- /dev/null
+++ b/security/libnetpgpverify/files/src/librsa/rsa.c
@@ -0,0 +1,696 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/syslog.h>
+
+#ifdef _KERNEL
+# include <sys/kmem.h>
+# define logmessage log
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <unistd.h>
+#endif
+
+#include "misc.h"
+#include "digest.h"
+#include "rsa.h"
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+#define RSA_MAX_MODULUS_BITS 16384
+#define RSA_SMALL_MODULUS_BITS 3072
+#define RSA_MAX_PUBEXP_BITS 64 /* exponent limit enforced for "large" modulus only */
+
+static int
+rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num)
+{
+ USE_ARG(num);
+ if (flen > tlen) {
+ printf("r too large\n");
+ return -1;
+ }
+ (void) memset(to, 0x0, tlen - flen);
+ (void) memcpy(to + tlen - flen, from, flen);
+ return tlen;
+}
+
+static int
+lowlevel_rsa_private_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, RSA *rsa)
+{
+ BIGNUM *decbn;
+ BIGNUM *signedbn;
+ uint8_t *decbuf;
+ int nbytes;
+ int signc;
+ int signedbytes;
+ int r;
+
+ decbuf = NULL;
+ r = -1;
+ decbn = BN_new();
+ signedbn = BN_new();
+ nbytes = BN_num_bytes(rsa->n);
+ decbuf = netpgp_allocate(1, nbytes);
+ /* add no padding */
+ memcpy(decbuf, plain, plainc);
+ BN_bin2bn(decbuf, nbytes, decbn);
+ if (BN_cmp(decbn, rsa->n) >= 0) {
+ printf("decbn too big\n");
+ goto err;
+ }
+ if (!BN_mod_exp(signedbn, decbn, rsa->d, rsa->n, NULL)) {
+ printf("bad mod_exp\n");
+ goto err;
+ }
+ signedbytes = BN_num_bytes(signedbn);
+ signc = BN_bn2bin(signedbn, &encbuf[nbytes - signedbytes]);
+ memset(encbuf, 0x0, nbytes - signc);
+ r = nbytes;
+err:
+ netpgp_deallocate(decbuf, nbytes);
+ BN_clear_free(decbn);
+ BN_clear_free(signedbn);
+ return r;
+}
+
+static int
+lowlevel_rsa_public_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, RSA *rsa)
+{
+ BIGNUM *decbn;
+ BIGNUM *encbn;
+ uint8_t *decbuf;
+ int nbytes;
+ int encc;
+ int r;
+ int i;
+
+ r = -1;
+ decbn = BN_new();
+ encbn = BN_new();
+ nbytes = BN_num_bytes(rsa->n);
+ decbuf = netpgp_allocate(1, nbytes);
+ (void) memcpy(decbuf, plain, plainc);
+ if (BN_bin2bn(decbuf, nbytes, decbn) == NULL) {
+ printf("bin2bn failed\n");
+ goto err;
+ }
+ if (BN_cmp(decbn, rsa->n) >= 0) {
+ printf("BN_cmp failed\n");
+ goto err;
+ }
+ if (!BN_mod_exp(encbn, decbn, rsa->e, rsa->n, NULL)) {
+ printf("BN_mod_exp failed\n");
+ goto err;
+ }
+ encc = BN_num_bytes(encbn);
+ i = BN_bn2bin(encbn, &encbuf[nbytes - encc]);
+ (void) memset(encbuf, 0x0, nbytes - i);
+ r = nbytes;
+err:
+ if (decbuf) {
+ memset(decbuf, 0x0, nbytes);
+ netpgp_deallocate(decbuf, nbytes);
+ }
+ BN_clear_free(decbn);
+ BN_clear_free(encbn);
+ return r;
+}
+
+static int
+lowlevel_rsa_private_decrypt(int enclen, const unsigned char *encbuf, unsigned char *to, RSA *rsa)
+{
+ BIGNUM *encbn;
+ BIGNUM *decbn;
+ uint8_t *buf;
+ int nbytes;
+ int j;
+ int r;
+
+ r = -1;
+ decbn = encbn = NULL;
+ buf = NULL;
+ if (BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
+ return -1;
+ }
+ if (BN_cmp(rsa->n, rsa->e) <= 0) {
+ return -1;
+ }
+ encbn = BN_new();
+ decbn = BN_new();
+ nbytes = BN_num_bytes(rsa->n);
+ buf = netpgp_allocate(1, nbytes);
+ if (enclen > nbytes) {
+ printf("bad enclen\n");
+ goto err;
+ }
+ BN_bin2bn(encbuf, enclen, encbn);
+ if (BN_cmp(encbn, rsa->n) >= 0) {
+ printf("bad encbn\n");
+ goto err;
+ }
+ BN_mod_exp(decbn, encbn, rsa->d, rsa->n, NULL);
+ j = BN_bn2bin(decbn, buf);
+ r = rsa_padding_check_none(to, nbytes, buf, j, nbytes);
+err:
+ BN_clear_free(encbn);
+ BN_clear_free(decbn);
+ netpgp_deallocate(buf, nbytes);
+ return r;
+}
+
+static int
+lowlevel_rsa_public_decrypt(const uint8_t *encbuf, int enclen, uint8_t *dec, const rsa_pubkey_t *rsa)
+{
+ uint8_t *decbuf;
+ BIGNUM *decbn;
+ BIGNUM *encbn;
+ int decbytes;
+ int nbytes;
+ int r;
+
+ nbytes = 0;
+ r = -1;
+ decbuf = NULL;
+ decbn = encbn = NULL;
+ if (BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
+ printf("rsa r modulus too large\n");
+ goto err;
+ }
+ if (BN_cmp(rsa->n, rsa->e) <= 0) {
+ printf("rsa r bad n value\n");
+ goto err;
+ }
+ if (BN_num_bits(rsa->n) > RSA_SMALL_MODULUS_BITS &&
+ BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) {
+ printf("rsa r bad exponent limit\n");
+ goto err;
+ }
+ if ((encbn = BN_new()) == NULL ||
+ (decbn = BN_new()) == NULL ||
+ (decbuf = netpgp_allocate(1, nbytes = BN_num_bytes(rsa->n))) == NULL) {
+ printf("allocation failure\n");
+ goto err;
+ }
+ if (enclen > nbytes) {
+ printf("rsa r > mod len\n");
+ goto err;
+ }
+ if (BN_bin2bn(encbuf, enclen, encbn) == NULL) {
+ printf("null encrypted BN\n");
+ goto err;
+ }
+ if (BN_cmp(encbn, rsa->n) >= 0) {
+ printf("rsa r data too large for modulus\n");
+ goto err;
+ }
+ if (BN_mod_exp(decbn, encbn, rsa->e, rsa->n, NULL) < 0) {
+ printf("BN_mod_exp < 0\n");
+ goto err;
+ }
+ decbytes = BN_num_bytes(decbn);
+ (void) BN_bn2bin(decbn, decbuf);
+ if ((r = rsa_padding_check_none(dec, nbytes, decbuf, decbytes, 0)) < 0) {
+ printf("rsa r padding check failed\n");
+ }
+err:
+ BN_free(encbn);
+ BN_free(decbn);
+ if (decbuf != NULL) {
+ (void) memset(decbuf, 0x0, nbytes);
+ netpgp_deallocate(decbuf, nbytes);
+ }
+ return r;
+}
+
+#if 0
+/**
+ @file rsa_make_key.c
+ RSA key generation, Tom St Denis
+*/
+
+/**
+ Create an RSA key
+ @param prng An active PRNG state
+ @param wprng The index of the PRNG desired
+ @param size The size of the modulus (key size) desired (octets)
+ @param e The "e" value (public key). e==65537 is a good choice
+ @param key [out] Destination of a newly created private key pair
+ @return CRYPT_OK if successful, upon error all allocated ram is freed
+*/
+static int
+rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
+{
+ void *p, *q, *tmp1, *tmp2, *tmp3;
+ int err;
+
+ LTC_ARGCHK(ltc_mp.name != NULL);
+ LTC_ARGCHK(key != NULL);
+
+ if ((size < (MIN_RSA_SIZE/8)) || (size > (MAX_RSA_SIZE/8))) {
+ return CRYPT_INVALID_KEYSIZE;
+ }
+
+ if ((e < 3) || ((e & 1) == 0)) {
+ return CRYPT_INVALID_ARG;
+ }
+
+ if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
+ return err;
+ }
+
+ if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != CRYPT_OK) {
+ return err;
+ }
+
+ /* make primes p and q (optimization provided by Wayne Scott) */
+ /* tmp3 = e */
+ if ((err = mp_set_int(tmp3, e)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ /* make prime "p" */
+ do {
+ if ((err = rand_prime( p, size/2, prng, wprng)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* tmp1 = p-1 */
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* tmp2 = gcd(p-1, e) */
+ if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) {
+ goto errkey;
+ }
+ } while (mp_cmp_d( tmp2, 1) != 0);
+ /* while e divides p-1 */
+
+ /* make prime "q" */
+ do {
+ if ((err = rand_prime( q, size/2, prng, wprng)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* tmp1 = q-1 */
+ if ((err = mp_sub_d( q, 1, tmp1)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* tmp2 = gcd(q-1, e) */
+ if ((err = mp_gcd( tmp1, tmp3, tmp2)) != CRYPT_OK) {
+ goto errkey;
+ }
+ } while (mp_cmp_d( tmp2, 1) != 0);
+ /* while e divides q-1 */
+
+ /* tmp1 = lcm(p-1, q-1) */
+ /* tmp2 = p-1 */
+ if ((err = mp_sub_d( p, 1, tmp2)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* tmp1 = q-1 (previous do/while loop) */
+ /* tmp1 = lcm(p-1, q-1) */
+ if ((err = mp_lcm( tmp1, tmp2, tmp1)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ /* make key */
+ if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ /* key->e = e */
+ if ((err = mp_set_int( key->e, e)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* key->d = 1/e mod lcm(p-1,q-1) */
+ if ((err = mp_invmod( key->e, tmp1, key->d)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* key->N = pq */
+ if ((err = mp_mul( p, q, key->N)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ /* optimize for CRT now */
+ /* find d mod q-1 and d mod p-1 */
+ /* tmp1 = q-1 */
+ if ((err = mp_sub_d( p, 1, tmp1)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* tmp2 = p-1 */
+ if ((err = mp_sub_d( q, 1, tmp2)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* dP = d mod p-1 */
+ if ((err = mp_mod( key->d, tmp1, key->dP)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* dQ = d mod q-1 */
+ if ((err = mp_mod( key->d, tmp2, key->dQ)) != CRYPT_OK) {
+ goto errkey;
+ }
+ /* qP = 1/q mod p */
+ if ((err = mp_invmod( q, p, key->qP)) != CRYPT_OK) {
+ got oerrkey;
+ }
+
+ if ((err = mp_copy( p, key->p)) != CRYPT_OK) {
+ goto errkey;
+ }
+ if ((err = mp_copy( q, key->q)) != CRYPT_OK) {
+ goto errkey;
+ }
+
+ /* set key type (in this case it's CRT optimized) */
+ key->type = PK_PRIVATE;
+
+ /* return ok and free temps */
+ err = CRYPT_OK;
+ goto cleanup;
+errkey:
+ mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
+cleanup:
+ mp_clear_multi(tmp3, tmp2, tmp1, p, q, NULL);
+ return err;
+}
+#endif
+
+#define HASHBUF_LEN 512
+
+#define DSA_MAX_MODULUS_BITS 10000
+
+static int
+dsa_do_verify(const unsigned char *calculated, int dgst_len, const dsasig_t *sig, mpi_dsa_t *dsa)
+{
+ BIGNUM *M;
+ BIGNUM *W;
+ BIGNUM *t1;
+ int ret = -1;
+ int qbits;
+
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
+ return 0;
+ }
+ M = W = t1 = NULL;
+ qbits = BN_num_bits(dsa->q);
+ switch(qbits) {
+ case 160:
+ case 224:
+ case 256:
+ /* openssl sources say these are the valid values */
+ /* according to FIPS 186-3 */
+ break;
+ default:
+ printf("dsa: bad # of Q bits\n");
+ return 0;
+ }
+ if (BN_num_bits(dsa->p) > DSA_MAX_MODULUS_BITS) {
+ printf("dsa: p too large\n");
+ return 0;
+ }
+ /* no love for SHA512? */
+ if (dgst_len > SHA256_DIGEST_LENGTH) {
+ printf("dsa: digest too long\n");
+ return 0;
+ }
+ ret = 0;
+ if ((M = BN_new()) == NULL ||
+ (W = BN_new()) == NULL ||
+ (t1 = BN_new()) == NULL) {
+ goto err;
+ }
+ if (BN_is_zero(sig->r) ||
+ BN_is_negative(sig->r) ||
+ BN_cmp(sig->r, dsa->q) >= 0) {
+ goto err;
+ }
+ if (BN_is_zero(sig->s) ||
+ BN_is_negative(sig->s) ||
+ BN_cmp(sig->s, dsa->q) >= 0) {
+ goto err;
+ }
+ if (BN_mod_inverse(W, sig->s, dsa->q, NULL) != MP_OKAY) {
+ goto err;
+ }
+ if (dgst_len > qbits / 8) {
+ dgst_len = qbits / 8;
+ }
+ if (BN_bin2bn(calculated, dgst_len, M) == NULL) {
+ goto err;
+ }
+ if (!BN_mod_mul(M, M, W, dsa->q, NULL)) {
+ goto err;
+ }
+ if (!BN_mod_mul(W, sig->r, W, dsa->q, NULL)) {
+ goto err;
+ }
+ if (!BN_mod_exp(dsa->p, t1, dsa->g, M, NULL)) {
+ goto err;
+ }
+ if (!BN_div(NULL, M, t1, dsa->q, NULL)) {
+ goto err;
+ }
+ ret = (BN_cmp(M, sig->r) == 0);
+err:
+ if (M) {
+ BN_free(M);
+ }
+ if (W) {
+ BN_free(W);
+ }
+ if (t1) {
+ BN_free(t1);
+ }
+ return ret;
+}
+
+/*************************************************************************/
+
+int
+RSA_size(const RSA *rsa)
+{
+ return (rsa == NULL) ? 0 : BN_num_bits(rsa->n);
+}
+
+int
+DSA_size(const DSA *dsa)
+{
+ return (dsa == NULL) ? 0 : BN_num_bits(dsa->p);
+}
+
+unsigned
+dsa_verify(const signature_t *signature, const dsa_pubkey_t *pubdsa, const uint8_t *calculated, size_t hash_length)
+{
+ mpi_dsa_t odsa;
+ dsasig_t osig;
+ unsigned qlen;
+ int ret;
+
+ if (signature == NULL || pubdsa == NULL || calculated == NULL) {
+ return -1;
+ }
+ (void) memset(&osig, 0x0, sizeof(osig));
+ (void) memset(&odsa, 0x0, sizeof(odsa));
+ BN_copy(osig.r, signature->dsa.r);
+ BN_copy(osig.s, signature->dsa.s);
+ odsa.p = pubdsa->p;
+ odsa.q = pubdsa->q;
+ odsa.g = pubdsa->g;
+ odsa.pub_key = pubdsa->y;
+ if ((qlen = BN_num_bytes(odsa.q)) < hash_length) {
+ hash_length = qlen;
+ }
+ ret = dsa_do_verify(calculated, (int)hash_length, &signature->dsa, &odsa);
+ if (ret < 0) {
+ return 0;
+ }
+ BN_free(odsa.p);
+ BN_free(odsa.q);
+ BN_free(odsa.g);
+ BN_free(odsa.pub_key);
+ odsa.p = odsa.q = odsa.g = odsa.pub_key = NULL;
+ BN_free(osig.r);
+ BN_free(osig.s);
+ osig.r = osig.s = NULL;
+ return (unsigned)ret;
+}
+
+RSA *
+RSA_new(void)
+{
+ return netpgp_allocate(1, sizeof(RSA));
+}
+
+void
+RSA_free(RSA *rsa)
+{
+ if (rsa) {
+ netpgp_deallocate(rsa, sizeof(*rsa));
+ }
+}
+
+int
+RSA_check_key(RSA *rsa)
+{
+ BIGNUM *calcn;
+ int ret;
+
+ ret = 0;
+ if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->n == NULL) {
+ return -1;
+ }
+ /* check that p and q are coprime, and that n = p*q. */
+ if (!BN_is_prime(rsa->p, 1, NULL, NULL, NULL) ||
+ !BN_is_prime(rsa->q, 1, NULL, NULL, NULL)) {
+ return 0;
+ }
+ calcn = BN_new();
+ BN_mul(calcn, rsa->p, rsa->q, NULL);
+ if (BN_cmp(calcn, rsa->n) != 0) {
+ goto errout;
+ }
+ /* XXX - check that d*e = 1 mod (p-1*q-1) */
+ ret = 1;
+errout:
+ BN_clear_free(calcn);
+ return ret;
+}
+
+RSA *
+RSA_generate_key(int num, unsigned long e, void (*callback)(int,int,void *), void *cb_arg)
+{
+ /* STUBBED */
+ USE_ARG(num);
+ USE_ARG(e);
+ USE_ARG(callback);
+ USE_ARG(cb_arg);
+ printf("RSA_generate_key stubbed\n");
+ return RSA_new();
+}
+
+/* encrypt */
+int
+RSA_public_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, RSA *rsa, int padding)
+{
+ USE_ARG(padding);
+ if (plain == NULL || encbuf == NULL || rsa == NULL) {
+ return -1;
+ }
+ return lowlevel_rsa_public_encrypt(plainc, plain, encbuf, rsa);
+}
+
+/* decrypt */
+int
+RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
+{
+ USE_ARG(padding);
+ if (from == NULL || to == NULL || rsa == NULL) {
+ return -1;
+ }
+ return lowlevel_rsa_private_decrypt(flen, from, to, rsa);
+}
+
+/* sign */
+int
+RSA_private_encrypt(int plainc, const unsigned char *plain, unsigned char *encbuf, RSA *rsa, int padding)
+{
+ USE_ARG(padding);
+ if (plain == NULL || encbuf == NULL || rsa == NULL) {
+ return -1;
+ }
+ return lowlevel_rsa_private_encrypt(plainc, plain, encbuf, rsa);
+}
+
+/* verify */
+int
+RSA_public_decrypt(int enclen, const unsigned char *enc, unsigned char *dec, RSA *rsa, int padding)
+{
+ rsa_pubkey_t pub;
+ int ret;
+
+ if (enc == NULL || dec == NULL || rsa == NULL) {
+ return 0;
+ }
+ USE_ARG(padding);
+ (void) memset(&pub, 0x0, sizeof(pub));
+ pub.n = BN_dup(rsa->n);
+ pub.e = BN_dup(rsa->e);
+ ret = lowlevel_rsa_public_decrypt(enc, enclen, dec, &pub);
+ BN_free(pub.n);
+ BN_free(pub.e);
+ return ret;
+}
+
+/***********************************************************************/
+
+DSA *
+DSA_new(void)
+{
+ return netpgp_allocate(1, sizeof(DSA));
+}
+
+void
+DSA_free(DSA *dsa)
+{
+ if (dsa) {
+ netpgp_deallocate(dsa, sizeof(*dsa));
+ }
+}
+
+DSA_SIG *
+DSA_SIG_new(void)
+{
+ return netpgp_allocate(1, sizeof(DSA_SIG));
+}
+
+void
+DSA_SIG_free(DSA_SIG *sig)
+{
+ if (sig) {
+ netpgp_deallocate(sig, sizeof(*sig));
+ }
+}
+
+DSA_SIG *
+DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+{
+ /* STUBBED */
+ USE_ARG(dgst);
+ USE_ARG(dlen);
+ USE_ARG(dsa);
+ printf("DSA_do_sign stubbed\n");
+ return DSA_SIG_new();
+}
+
+int
+DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa)
+{
+ if (dgst == NULL || dgst_len == 0 || sig == NULL || dsa == NULL) {
+ return -1;
+ }
+ return dsa_do_verify(dgst, dgst_len, sig, dsa);
+}
diff --git a/security/libnetpgpverify/files/src/librsa/rsa.h b/security/libnetpgpverify/files/src/librsa/rsa.h
new file mode 100644
index 00000000000..739c9756df4
--- /dev/null
+++ b/security/libnetpgpverify/files/src/librsa/rsa.h
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef RSA_H_
+#define RSA_H_ 20120325
+
+#include "bn.h"
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+typedef struct rsa_pubkey_t {
+ BIGNUM *n; /* RSA public modulus n */
+ BIGNUM *e; /* RSA public encryption exponent e */
+} rsa_pubkey_t;
+
+typedef struct mpi_rsa_t {
+ int f1; /* openssl pad */
+ long f2; /* openssl version */
+ const void *f3; /* openssl method */
+ void *f4; /* openssl engine */
+ BIGNUM *n;
+ BIGNUM *e;
+ BIGNUM *d;
+ BIGNUM *p;
+ BIGNUM *q;
+ BIGNUM *dmp1;
+ BIGNUM *dmq1;
+ BIGNUM *iqmp;
+} mpi_rsa_t;
+
+#define RSA mpi_rsa_t
+
+typedef struct dsa_pubkey_t {
+ BIGNUM *p; /* DSA public modulus n */
+ BIGNUM *q; /* DSA public encryption exponent e */
+ BIGNUM *g;
+ BIGNUM *y;
+} dsa_pubkey_t;
+
+typedef struct mpi_dsa_t {
+ BIGNUM *p;
+ BIGNUM *q;
+ BIGNUM *g;
+ BIGNUM *y;
+ BIGNUM *x;
+ BIGNUM *pub_key;
+ BIGNUM *priv_key;
+} mpi_dsa_t;
+
+#define DSA mpi_dsa_t
+
+typedef struct rsasig_t {
+ BIGNUM *sig; /* mpi which is actual signature */
+} rsasig_t;
+
+typedef struct dsasig_t {
+ BIGNUM *r; /* mpi which is actual signature */
+ BIGNUM *s; /* mpi which is actual signature */
+} dsasig_t;
+
+#define DSA_SIG dsasig_t
+
+/* misc defs */
+#define RSA_NO_PADDING 3
+
+#define SIGNETBSD_ID_SIZE 8
+#define SIGNETBSD_NAME_SIZE 128
+
+#define RSA_PUBKEY_ALG 1
+#define DSA_PUBKEY_ALG 17
+
+/* the public part of the key */
+typedef struct pubkey_t {
+ uint32_t version; /* key version - usually 4 */
+ uint8_t id[SIGNETBSD_ID_SIZE]; /* binary id */
+ char name[SIGNETBSD_NAME_SIZE]; /* name of identity - not necessary, but looks better */
+ int64_t birthtime; /* time of creation of key */
+ int64_t expiry; /* expiration time of the key */
+ uint32_t validity; /* validity in days */
+ uint32_t alg; /* pubkey algorithm - rsa/dss etc */
+ rsa_pubkey_t rsa; /* specific RSA keys */
+ dsa_pubkey_t dsa; /* specific DSA keys */
+} pubkey_t;
+
+/* signature details (for a specific file) */
+typedef struct signature_t {
+ uint32_t version; /* signature version number */
+ uint32_t type; /* signature type value */
+ int64_t birthtime; /* creation time of the signature */
+ int64_t expiry; /* expiration time of the signature */
+ uint8_t id[SIGNETBSD_ID_SIZE]; /* binary id */
+ uint32_t key_alg; /* public key algorithm number */
+ uint32_t hash_alg; /* hashing algorithm number */
+ rsasig_t rsa; /* RSA signature */
+ dsasig_t dsa; /* DSA signature */
+ size_t v4_hashlen; /* length of hashed info */
+ uint8_t *v4_hashed; /* hashed info */
+ uint8_t hash2[2]; /* high 2 bytes of hashed value - for quick test */
+ pubkey_t *signer; /* pubkey of signer */
+} signature_t;
+
+unsigned dsa_verify(const signature_t */*sig*/, const dsa_pubkey_t */*pubdsa*/, const uint8_t */*calc*/, size_t /*hashlen*/);
+
+RSA *RSA_new(void);
+int RSA_size(const RSA */*rsa*/);
+void RSA_free(RSA */*rsa*/);
+int RSA_check_key(RSA */*rsa*/);
+RSA *RSA_generate_key(int /*num*/, unsigned long /*e*/, void (*callback)(int,int,void *), void */*cb_arg*/);
+int RSA_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
+int RSA_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
+int RSA_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding);
+int RSA_public_decrypt(int flen, const uint8_t *from, uint8_t *to, RSA *rsa, int padding);
+
+DSA *DSA_new(void);
+int DSA_size(const DSA */*rsa*/);
+void DSA_free(DSA */*dsa*/);
+DSA_SIG *DSA_SIG_new(void);
+void DSA_SIG_free(DSA_SIG */*sig*/);
+int DSA_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa);
+DSA_SIG *DSA_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/librsa/rsastubs.c b/security/libnetpgpverify/files/src/librsa/rsastubs.c
new file mode 100644
index 00000000000..2c36c7dd528
--- /dev/null
+++ b/security/libnetpgpverify/files/src/librsa/rsastubs.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <pwd.h>
+
+#include "rsa.h"
+#include "rsastubs.h"
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+static int
+pass_cb(char *buf, int size, int rwflag, void *u)
+{
+ char *passphrase;
+ char prompt[128];
+
+ USE_ARG(rwflag);
+ snprintf(prompt, sizeof(prompt), "\"%s\" passphrase: ", (char *)u);
+ if ((passphrase = getpass(prompt)) == NULL) {
+ return -1;
+ }
+ (void) memcpy(buf, passphrase, (size_t)size);
+ return (int)strlen(passphrase);
+}
+
+RSA *
+PEM_read_RSAPrivateKey(FILE *fp, RSA **x, pem_password_cb *cb, void *u)
+{
+ char phrase[128 + 1];
+ RSA *rsa;
+ int cc;
+
+fprintf(stderr, "Stubbed PEM_read_RSAPrivateKey\n");
+ USE_ARG(u);
+ if (cb == NULL) {
+ cb = pass_cb;
+ }
+ cc = (*cb)(phrase, sizeof(phrase), 0, u);
+ rsa = *x = RSA_new();
+ USE_ARG(fp);
+ return rsa;
+}
+
+DSA *
+PEM_read_DSAPrivateKey(FILE *fp, DSA **x, pem_password_cb *cb, void *u)
+{
+ DSA *dsa;
+
+ USE_ARG(u);
+ if (cb == NULL) {
+ cb = pass_cb;
+ }
+ dsa = *x = DSA_new();
+ USE_ARG(fp);
+ return dsa;
+}
diff --git a/security/libnetpgpverify/files/src/librsa/rsastubs.h b/security/libnetpgpverify/files/src/librsa/rsastubs.h
new file mode 100644
index 00000000000..e6f999c903e
--- /dev/null
+++ b/security/libnetpgpverify/files/src/librsa/rsastubs.h
@@ -0,0 +1,25 @@
+#ifndef RSASTUBS_H_
+#define RSASTUBS_H_ 20120412
+
+#include "rsa.h"
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+typedef int pem_password_cb(char */*buf*/, int /*size*/, int /*rwflag*/, void */*userdata*/);
+
+RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **x, pem_password_cb *cb, void *u);
+DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **x, pem_password_cb *cb, void *u);
+
+__END_DECLS
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libverify/Makefile b/security/libnetpgpverify/files/src/libverify/Makefile
new file mode 100644
index 00000000000..7b39520e233
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/Makefile
@@ -0,0 +1,71 @@
+# $NetBSD: Makefile,v 1.1.1.1 2013/02/23 21:04:27 agc Exp $
+
+PROG=netpgpv
+SRCS=libverify.c b64.c pgpsum.c
+SRCS+=digest.c tiger.c
+SRCS+=bignum.c misc.c
+SRCS+=rsaglue.c rsa.c
+SRCS+=main.c
+WARNS=5
+MKMAN=no
+CPPFLAGS+=-I${.CURDIR}/../libbn
+CPPFLAGS+=-I${.CURDIR}/../librsa
+LDADD+=-lz
+LDADD+=-lbz2
+
+# XXX - debugging
+#CPPFLAGS+=-g -O0
+#LDFLAGS+=-g -O0
+#CPPFLAGS+=-O3
+#LDFLAGS+=-O3
+
+.PATH: ${.CURDIR} ${.CURDIR}/../libdigest ${.CURDIR}/../libverify ${.CURDIR}/../libbn ${.CURDIR}/../librsa
+
+.include <bsd.prog.mk>
+
+t: ${PROG}
+ ./${PROG} -c verify b.gpg > output16
+ diff expected16 output16
+ rm -f output16
+ ./${PROG} -c verify a.gpg > output17
+ diff expected17 output17
+ rm -f output17
+ ./${PROG} -c verify gpgsigned-a.gpg > output18
+ diff expected18 output18
+ rm -f output18
+ ./${PROG} -c verify NetBSD-6.0_RC2_hashes.asc > output19
+ diff expected19 output19
+ rm -f output19
+ ./${PROG} -c cat jj.asc > output20
+ diff expected20 output20
+ rm -f output20
+ ./${PROG} < a.gpg > output21
+ diff expected21 output21
+ rm -f output21
+ ./${PROG} < jj.asc > output22
+ diff expected22 output22
+ rm -f output22
+ ./${PROG} < NetBSD-6.0_RC2_hashes.asc > output23
+ diff expected23 output23
+ rm -f output23
+ ./${PROG} < b.gpg > output24
+ diff expected24 output24
+ rm -f output24
+ ./${PROG} NetBSD-6.0_RC1_hashes.gpg > output25
+ diff expected25 output25
+ rm -f output25
+ ./${PROG} < NetBSD-6.0_RC1_hashes.gpg > output26
+ diff expected26 output26
+ rm -f output26
+ ./${PROG} < NetBSD-6.0_hashes.asc > output27
+ diff expected27 output27
+ rm -f output27
+ ./${PROG} NetBSD-6.0_hashes.asc > output28
+ diff expected28 output28
+ rm -f output28
+ ./${PROG} NetBSD-6.0_RC1_hashes_ascii.gpg > output29
+ diff expected29 output29
+ rm -f output29
+ ./${PROG} < NetBSD-6.0_RC1_hashes_ascii.gpg > output30
+ diff expected30 output30
+ rm -f output30
diff --git a/security/libnetpgpverify/files/src/libverify/array.h b/security/libnetpgpverify/files/src/libverify/array.h
new file mode 100644
index 00000000000..d5c19a98d67
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/array.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef ARRAY_H_
+#define ARRAY_H_ 20120921
+
+#ifndef PGPV_ARRAY
+/* creates 2 unsigned vars called "name"c and "name"size in current scope */
+/* also creates an array called "name"s in current scope */
+#define PGPV_ARRAY(type, name) \
+ unsigned name##c; unsigned name##vsize; type *name##s
+#endif
+
+/* if this isn't part of a struct, need to specifically initialise things */
+#define ARRAY_INIT(name) do { \
+ name##c = name##vsize = 0; \
+ name##s = NULL; \
+} while(/*CONSTCOND*/0)
+
+/* check the array is big enough - if not, expand it by explicit amount */
+/* this is clunky, but there are bugs a-lurking */
+#define ARRAY_EXPAND_SIZED(name, mult, add) do { \
+ if (name##c == name##vsize) { \
+ void *_v; \
+ char *_cv = NULL; \
+ unsigned _ents; \
+ _ents = (name##vsize * (mult)) + (add); \
+ _cv = _v = realloc(name##s, _ents * sizeof(*name##s)); \
+ if (_v == NULL) { \
+ fprintf(stderr, "ARRAY_EXPAND - bad realloc\n"); \
+ } else { \
+ memset(&_cv[name##vsize * sizeof(*name##s)], \
+ 0x0, (_ents - name##vsize) * sizeof(*name##s)); \
+ name##s = _v; \
+ name##vsize = _ents; \
+ } \
+ } \
+} while(/*CONSTCOND*/0)
+
+/* check the array is big enough - if not, expand it (size * 2) + 10 */
+#define ARRAY_EXPAND(name) ARRAY_EXPAND_SIZED(name, 2, 10)
+
+#define ARRAY_ELEMENT(name, num) name##s[num]
+#define ARRAY_LAST(name) name##s[name##c - 1]
+#define ARRAY_COUNT(name) name##c
+#define ARRAY_SIZE(name) name##vsize
+#define ARRAY_ARRAY(name) name##s
+
+#define ARRAY_APPEND(name, newel) do { \
+ ARRAY_EXPAND(name); \
+ ARRAY_COUNT(name) += 1; \
+ ARRAY_LAST(name) = newel; \
+} while(/*CONSTCOND*/0)
+
+#define ARRAY_DELETE(name, num) do { \
+ ARRAY_COUNT(name) -= 1; \
+ memmove(&ARRAY_ELEMENT(name, num), &ARRAY_ELEMENT(name, num + 1), \
+ (ARRAY_COUNT(name) - (num)) * sizeof(ARRAY_ELEMENT(name, 0))); \
+} while(/*CONSTCOND*/0)
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libverify/b64.c b/security/libnetpgpverify/files/src/libverify/b64.c
new file mode 100644
index 00000000000..50412dece7d
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/b64.c
@@ -0,0 +1,355 @@
+/*********************************************************************\
+
+MODULE NAME: b64.c
+
+AUTHOR: Bob Trower 08/04/01
+
+PROJECT: Crypt Data Packaging
+
+COPYRIGHT: Copyright (c) Trantor Standard Systems Inc., 2001
+
+NOTE: This source code may be used as you wish, subject to
+ the MIT license. See the LICENCE section below.
+
+DESCRIPTION:
+ This little utility implements the Base64
+ Content-Transfer-Encoding standard described in
+ RFC1113 (http://www.faqs.org/rfcs/rfc1113.html).
+
+ This is the coding scheme used by MIME to allow
+ binary data to be transferred by SMTP mail.
+
+ Groups of 3 bytes from a binary stream are coded as
+ groups of 4 bytes in a text stream.
+
+ The input stream is 'padded' with zeros to create
+ an input that is an even multiple of 3.
+
+ A special character ('=') is used to denote padding so
+ that the stream can be decoded back to its exact size.
+
+ Encoded output is formatted in lines which should
+ be a maximum of 72 characters to conform to the
+ specification. This program defaults to 72 characters,
+ but will allow more or less through the use of a
+ switch. The program enforces a minimum line size
+ of 4 characters.
+
+ Example encoding:
+
+ The stream 'ABCD' is 32 bits long. It is mapped as
+ follows:
+
+ ABCD
+
+ A (65) B (66) C (67) D (68) (None) (None)
+ 01000001 01000010 01000011 01000100
+
+ 16 (Q) 20 (U) 9 (J) 3 (D) 17 (R) 0 (A) NA (=) NA (=)
+ 010000 010100 001001 000011 010001 000000 000000 000000
+
+
+ QUJDRA==
+
+ Decoding is the process in reverse. A 'decode' lookup
+ table has been created to avoid string scans.
+
+DESIGN GOALS: Specifically:
+ Code is a stand-alone utility to perform base64
+ encoding/decoding. It should be genuinely useful
+ when the need arises and it meets a need that is
+ likely to occur for some users.
+ Code acts as sample code to show the author's
+ design and coding style.
+
+ Generally:
+ This program is designed to survive:
+ Everything you need is in a single source file.
+ It compiles cleanly using a vanilla ANSI C compiler.
+ It does its job correctly with a minimum of fuss.
+ The code is not overly clever, not overly simplistic
+ and not overly verbose.
+ Access is 'cut and paste' from a web page.
+ Terms of use are reasonable.
+
+VALIDATION: Non-trivial code is never without errors. This
+ file likely has some problems, since it has only
+ been tested by the author. It is expected with most
+ source code that there is a period of 'burn-in' when
+ problems are identified and corrected. That being
+ said, it is possible to have 'reasonably correct'
+ code by following a regime of unit test that covers
+ the most likely cases and regression testing prior
+ to release. This has been done with this code and
+ it has a good probability of performing as expected.
+
+ Unit Test Cases:
+
+ case 0:empty file:
+ CASE0.DAT -> ->
+ (Zero length target file created
+ on both encode and decode.)
+
+ case 1:One input character:
+ CASE1.DAT A -> QQ== -> A
+
+ case 2:Two input characters:
+ CASE2.DAT AB -> QUJD -> AB
+
+ case 3:Three input characters:
+ CASE3.DAT ABC -> QUJD -> ABC
+
+ case 4:Four input characters:
+ case4.dat ABCD -> QUJDRA== -> ABCD
+
+ case 5:All chars from 0 to ff, linesize set to 50:
+
+ AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj
+ JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH
+ SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr
+ bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P
+ kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz
+ tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX
+ 2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7
+ /P3+/w==
+
+ case 6:Mime Block from e-mail:
+ (Data same as test case 5)
+
+ case 7: Large files:
+ Tested 28 MB file in/out.
+
+ case 8: Random Binary Integrity:
+ This binary program (b64.exe) was encoded to base64,
+ back to binary and then executed.
+
+ case 9 Stress:
+ All files in a working directory encoded/decoded
+ and compared with file comparison utility to
+ ensure that multiple runs do not cause problems
+ such as exhausting file handles, tmp storage, etc.
+
+ -------------
+
+ Syntax, operation and failure:
+ All options/switches tested. Performs as
+ expected.
+
+ case 10:
+ No Args -- Shows Usage Screen
+ Return Code 1 (Invalid Syntax)
+ case 11:
+ One Arg (invalid) -- Shows Usage Screen
+ Return Code 1 (Invalid Syntax)
+ case 12:
+ One Arg Help (-?) -- Shows detailed Usage Screen.
+ Return Code 0 (Success -- help request is valid).
+ case 13:
+ One Arg Help (-h) -- Shows detailed Usage Screen.
+ Return Code 0 (Success -- help request is valid).
+ case 14:
+ One Arg (valid) -- Uses stdin/stdout (filter)
+ Return Code 0 (Sucess)
+ case 15:
+ Two Args (invalid file) -- shows system error.
+ Return Code 2 (File Error)
+ case 16:
+ Encode non-existent file -- shows system error.
+ Return Code 2 (File Error)
+ case 17:
+ Out of disk space -- shows system error.
+ Return Code 3 (File I/O Error)
+
+ -------------
+
+ Compile/Regression test:
+ gcc compiled binary under Cygwin
+ Microsoft Visual Studio under Windows 2000
+ Microsoft Version 6.0 C under Windows 2000
+
+DEPENDENCIES: None
+
+LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc.
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated
+ documentation files (the "Software"), to deal in the
+ Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute,
+ sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall
+ be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+VERSION HISTORY:
+ Bob Trower 08/04/01 -- Create Version 0.00.00B
+
+\******************************************************************* */
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "b64.h"
+
+/*
+** Translation Table as described in RFC1113
+*/
+static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/*
+** Translation Table to decode (created by author)
+*/
+static const char cd64[] = "|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
+
+/*
+** encodeblock
+**
+** encode 3 8-bit binary bytes as 4 '6-bit' characters
+*/
+static void
+encodeblock(uint8_t *wordin, uint8_t *wordout, int wordlen)
+{
+ wordout[0] = cb64[(unsigned)wordin[0] >> 2];
+ wordout[1] = cb64[((unsigned)(wordin[0] & 0x03) << 4) | ((unsigned)(wordin[1] & 0xf0) >> 4)];
+ wordout[2] = (uint8_t)(wordlen > 1) ?
+ cb64[((unsigned)(wordin[1] & 0x0f) << 2) | ((unsigned)(wordin[2] & 0xc0) >> 6)] : '=';
+ wordout[3] = (uint8_t)(wordlen > 2) ? cb64[wordin[2] & 0x3f] : '=';
+}
+
+/*
+** encode
+**
+** base64 encode a stream adding padding and line breaks as per spec.
+*/
+int
+b64encode(const char *in, const size_t insize, void *vp, size_t outsize, int linesize)
+{
+ const char *inp;
+ unsigned i;
+ uint8_t wordout[4];
+ uint8_t wordin[3];
+ char *out = vp;
+ char *outp;
+ int blocksout;
+ int wordlen;
+
+ if (in == NULL || vp == NULL) {
+ return 0;
+ }
+ wordlen = 0;
+ for (blocksout = 0, inp = in, outp = out; (size_t)(inp - in) < insize && (size_t)(outp - out) < outsize;) {
+ for (wordlen = 0, i = 0; i < sizeof(wordin); i++) {
+ wordin[i] = (uint8_t) *inp++;
+ if ((size_t)(inp - in) <= insize) {
+ wordlen++;
+ } else {
+ wordin[i] = 0x0;
+ }
+ }
+ if (wordlen > 0) {
+ encodeblock(wordin, wordout, wordlen);
+ for (i = 0; i < sizeof(wordout) ; i++) {
+ *outp++ = wordout[i];
+ }
+ blocksout++;
+ }
+ if (linesize > 0) {
+ if (blocksout >= (int)(linesize / sizeof(wordout)) ||
+ (size_t)(inp - in) >= insize) {
+ if (blocksout) {
+ *outp++ = '\r';
+ *outp++ = '\n';
+ }
+ blocksout = 0;
+ }
+ }
+ }
+ return (int)(outp - out);
+}
+
+/*
+** decodeblock
+**
+** decode 4 '6-bit' characters into 3 8-bit binary bytes
+*/
+static void
+decodeblock(uint8_t wordin[4], uint8_t wordout[3])
+{
+ wordout[0] = (uint8_t) ((unsigned)wordin[0] << 2 | (unsigned)wordin[1] >> 4);
+ wordout[1] = (uint8_t) ((unsigned)wordin[1] << 4 | (unsigned)wordin[2] >> 2);
+ wordout[2] = (uint8_t) (((wordin[2] << 6) & 0xc0) | wordin[3]);
+}
+
+/*
+** decode
+**
+** decode a base64 encoded stream discarding padding, line breaks and noise
+*/
+int
+b64decode(const char *in, const size_t insize, void *vp, size_t outsize)
+{
+ const char *inp;
+ unsigned wordlen;
+ unsigned i;
+ uint8_t wordout[3];
+ uint8_t wordin[4];
+ uint8_t v;
+ char *out = vp;
+ char *outp;
+
+ if (in == NULL || vp == NULL) {
+ return 0;
+ }
+ for (inp = in, outp = out ; (size_t)(inp - in) < insize && (size_t)(outp - out) < outsize ; ) {
+ for (wordlen = 0, i = 0 ; i < sizeof(wordin) && (size_t)(inp - in) < insize ; i++) {
+ /* get a single character */
+ for (v = 0; (size_t)(inp - in) <= insize && v == 0 ; ) {
+ if (*inp == '\r' && *(inp + 1) == '\n') {
+ inp += 2;
+ } else {
+ v = (uint8_t) *inp++;
+ v = (uint8_t) ((v < 43 || v > 122) ? 0 : cd64[v - 43]);
+ if (v) {
+ v = (uint8_t) ((v == '$') ? 0 : v - 61);
+ }
+ }
+ }
+ /* perhaps 0x0 pad */
+ if ((size_t)(inp - in) <= insize) {
+ wordlen += 1;
+ if (v) {
+ wordin[i] = (uint8_t) (v - 1);
+ }
+ } else {
+ wordin[i] = 0x0;
+ }
+ }
+ if (wordlen > 0) {
+ decodeblock(wordin, wordout);
+ for (i = 0; i < wordlen - 1 ; i++) {
+ *outp++ = wordout[i];
+ }
+ }
+ }
+ return (int)(outp - out);
+}
+
+/* return the encoded size for n bytes input */
+int
+b64_encsize(unsigned n)
+{
+ return ((4 * n) / 3) + 4;
+}
diff --git a/security/libnetpgpverify/files/src/libverify/b64.h b/security/libnetpgpverify/files/src/libverify/b64.h
new file mode 100644
index 00000000000..e939857cbdb
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/b64.h
@@ -0,0 +1,32 @@
+/*-
+ * Copyright (c) 2010 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.
+ */
+#ifndef B64_H_
+#define B64_H_ 20091223
+
+int b64encode(const char */*in*/, const size_t /*insize*/, void */*vp*/, size_t /*outsize*/, int /*linesize*/);
+int b64decode(const char */*in*/, const size_t /*insize*/, void */*vp*/, size_t /*outsize*/);
+int b64_encsize(unsigned /*n*/);
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libverify/dump.c b/security/libnetpgpverify/files/src/libverify/dump.c
new file mode 100644
index 00000000000..0c31b4b6b0d
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/dump.c
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef isprint
+#define isprint(x) ((x) >= ' ' && (x) <= '~')
+#endif
+
+#define HEXDUMP_LINELEN 16
+
+#ifndef PRIsize
+#define PRIsize "z"
+#endif
+
+/* show hexadecimal/ascii dump */
+static ssize_t
+hexdump(const char *in, const size_t len, void *outvp, size_t size)
+{
+ size_t i;
+ char line[HEXDUMP_LINELEN + 1];
+ char *out = (char *)outvp;
+ int o;
+
+ for (i = 0, o = 0 ; i < len ; i++) {
+ if (i % HEXDUMP_LINELEN == 0) {
+ o += snprintf(&out[o], size - o,
+ "%.5" PRIsize "u | ", i);
+ }
+ o += snprintf(&out[o], size - o, "%.02x ", (uint8_t)in[i]);
+ line[i % HEXDUMP_LINELEN] =
+ (isprint((uint8_t)in[i])) ? in[i] : '.';
+ if (i % HEXDUMP_LINELEN == HEXDUMP_LINELEN - 1) {
+ line[HEXDUMP_LINELEN] = 0x0;
+ o += snprintf(&out[o], size - o, " | %s\n", line);
+ }
+ }
+ if (i % HEXDUMP_LINELEN != 0) {
+ for ( ; i % HEXDUMP_LINELEN != 0 ; i++) {
+ o += snprintf(&out[o], size - o, " ");
+ line[i % HEXDUMP_LINELEN] = ' ';
+ }
+ line[HEXDUMP_LINELEN] = 0x0;
+ o += snprintf(&out[o], size - o, " | %s\n", line);
+ }
+ return (ssize_t)o;
+}
+
+void dumpmem(void */*p*/, size_t /*size*/);
+
+/* just dump an area of memory to stdout */
+void
+dumpmem(void *vp, size_t size)
+{
+ ssize_t cc;
+ uint8_t *p = (uint8_t *)vp;
+ char *buf;
+
+ buf = calloc(1, size * 5);
+ cc = hexdump((const char *)p, size, buf, size * 5);
+ fprintf(stdout, "%.*s\n", (int)cc, buf);
+ free(buf);
+}
diff --git a/security/libnetpgpverify/files/src/libverify/libnetpgpverify.3 b/security/libnetpgpverify/files/src/libverify/libnetpgpverify.3
new file mode 100644
index 00000000000..b57d34cc4c1
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/libnetpgpverify.3
@@ -0,0 +1,139 @@
+.\" $NetBSD: libnetpgpverify.3,v 1.1.1.1 2013/02/23 21:04:27 agc Exp $
+.\"
+.\" Copyright (c) 2012 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.
+.\"
+.Dd October 21, 2012
+.Dt LIBNETPGPVERIFY 3
+.Os
+.Sh NAME
+.Nm libnetpgpverify
+.Nd library to verify digital signatures
+.Sh LIBRARY
+.Lb libnetpgpverify
+.Sh SYNOPSIS
+.In netpgp/verify.h
+.Ft int
+.Fo pgpv_read_pubring
+.Fa "pgpv_t *pgp" "const void *keyring" "ssize_t size"
+.Fc
+.Ft size_t
+.Fo pgpv_verify
+.Fa "pgpv_cursor_t *cursor" "pgpv_t *pgp" "const void *ptr" "ssize_t size"
+.Fc
+.Ft size_t
+.Fo pgpv_get_verified
+.Fa "pgpv_cursor_t *cursor" "size_t cookie " "char **ret"
+.Fc
+.Ft size_t
+.Fo pgpv_get_entry
+.Fa "pgpv_t *pgp" "unsigned ent" "char **ret"
+.Fc
+.Ft int
+.Fo pgpv_close
+.Fa "pgpv_t *pgp"
+.Fc
+.Sh DESCRIPTION
+.Nm
+is a small library which will verify a digital signature on a text or
+binary document.
+It has been kept deliberately small and only uses compression libraries
+to function.
+.Pp
+PGP messages, including key rings, are made up of PGP packets, defined
+in RFC 4880.
+To match a digital signature, the public key of the signer must be
+located in a public key ring.
+This library has enough functionality to parse a pubkey keyring,
+using
+.Fn pgpv_read_pubring
+to read the public keys of trusted identities,
+and to read files or memory which has already been signed.
+The
+.Fn pgpv_verify
+function is used to verify the signature, either on data, or on memory.
+To signal to
+.Fn pgpv_verify
+to read a file and verify it, the
+.Dv size
+argument should be set to
+.Dv -1
+whilst a positive size signals that the pointer value should be that
+of signed memory.
+.Fn pgpv_verify
+returns a cookie if the ignature was verified, or 0 if it did not.
+This cookie can subsequently be used to retrieve the data which
+was verified.
+.Pp
+If the signature does match, then the file or memory can be considered as being
+verified as being unmodified and unchanged, integrally sound.
+.Pp
+Signatures have validity dates on them, and it is possible for a signature to
+have expired when it is being checked.
+If for any reason the signature does not match, then the reason for not
+verifying the signature will be stored in the
+.Dv why
+buffer in the
+.Dv pgpv_cursor_t
+structure.
+.Pp
+Occasionally, the memory or contents of the file which matched the signature
+will be needed, rather than a boolean value of whether it was verified.
+To do this, the
+.Fn pgpv_get_verified
+function is used.
+Arguments to
+.Fn pgpv_get_verified
+are the cookie returned from the verification, and a buffer
+allocated for the returned data and its size.
+If an error occurs, or the signature is not verified, a zero value is returned
+for the size.
+.Nm
+stores the starts of the data of all verified matches, and so the entry
+number argument is the index of the occurrence of verification.
+The first match will have an entry number of 0, the second 1, and so on.
+.Pp
+The
+.Fn pgpv_close
+function is used to clean up after all matching and verification has taken place.
+It frees and de-allocates all resources used in the verification of the signature.
+.Pp
+The program used for signing may encode into base64 encoding, and it may also
+use embedded compression to make the output smaller than it would otherwise be.
+This is handled automatically by
+.Nm
+.Sh SEE ALSO
+.Xr bn 3 ,
+.\" .Xr bzlib2 3 ,
+.Xr zlib 3
+.Sh STANDARDS
+The
+.Nm
+utility is designed to conform to IETF RFC 4880.
+.Sh HISTORY
+The
+.Nm
+library first appeared in
+.Nx 7.0 .
+.Sh AUTHORS
+.An Alistair Crooks Aq agc@NetBSD.org
diff --git a/security/libnetpgpverify/files/src/libverify/libverify.c b/security/libnetpgpverify/files/src/libverify/libverify.c
new file mode 100644
index 00000000000..754a8cc1f3d
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/libverify.c
@@ -0,0 +1,2366 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <bzlib.h>
+#include <err.h>
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include "array.h"
+#include "bn.h"
+#include "b64.h"
+#include "digest.h"
+#include "pgpsum.h"
+#include "rsa.h"
+#include "verify.h"
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+#define BITS_TO_BYTES(b) (((b) + (CHAR_BIT - 1)) / CHAR_BIT)
+
+/* packet types */
+#define SIGNATURE_PKT 2
+#define ONEPASS_SIGNATURE_PKT 4
+#define PUBKEY_PKT 6
+#define COMPRESSED_DATA_PKT 8
+#define MARKER_PKT 10
+#define LITDATA_PKT 11
+#define TRUST_PKT 12
+#define USERID_PKT 13
+#define PUB_SUBKEY_PKT 14
+#define USER_ATTRIBUTE_PKT 17
+
+/* only allow certain packets at certain times */
+#define PUBRING_ALLOWED "\002\006\014\015\016\021"
+#define SIGNATURE_ALLOWED "\002\004\010\013"
+
+/* actions to do on close */
+#define FREE_MEM 0x01
+#define UNMAP_MEM 0x02
+
+/* types of pubkey we encounter */
+#define PUBKEY_RSA_ENCRYPT_OR_SIGN 1
+#define PUBKEY_RSA_ENCRYPT 2
+#define PUBKEY_RSA_SIGN 3
+#define PUBKEY_ELGAMAL_ENCRYPT 16
+#define PUBKEY_DSA 17
+#define PUBKEY_ELLIPTIC_CURVE 18
+#define PUBKEY_ECDSA 19
+#define PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN 20
+
+/* hash algorithm definitions */
+#define PGPV_HASH_MD5 1
+#define PGPV_HASH_SHA1 2
+#define PGPV_HASH_RIPEMD 3
+#define PGPV_HASH_SHA256 8
+#define PGPV_HASH_SHA384 9
+#define PGPV_HASH_SHA512 10
+
+/* pubkey defs for bignums */
+#define RSA_N 0
+#define RSA_E 1
+#define DSA_P 0
+#define DSA_Q 1
+#define DSA_G 2
+#define DSA_Y 3
+#define ELGAMAL_P 0
+#define ELGAMAL_G 1
+#define ELGAMAL_Y 2
+
+/* sesskey indices */
+#define RSA_SESSKEY_ENCRYPTED_M 0
+#define RSA_SESSKEY_M 1
+#define ELGAMAL_SESSKEY_G_TO_K 0
+#define ELGAMAL_SESSKEY_ENCRYPTED_M 1
+
+/* seckey indices */
+#define RSA_SECKEY_D 0
+#define RSA_SECKEY_P 1
+#define RSA_SECKEY_Q 2
+#define RSA_SECKEY_U 3
+#define DSA_SECKEY_X 0
+#define ELGAMAL_SECKEY_X 0
+
+/* signature mpi indices in bignumber array */
+#define RSA_SIG 0
+#define DSA_R 0
+#define DSA_S 1
+#define ELGAMAL_SIG_R 0
+#define ELGAMAL_SIG_S 1
+
+/* signature types */
+#define SIGTYPE_BINARY_DOC 0x00 /* Signature of a binary document */
+#define SIGTYPE_TEXT 0x01 /* Signature of a canonical text document */
+#define SIGTYPE_STANDALONE 0x02 /* Standalone signature */
+
+#define SIGTYPE_GENERIC_USERID 0x10 /* Generic certification of a User ID and Public Key packet */
+#define SIGTYPE_PERSONA_USERID 0x11 /* Persona certification of a User ID and Public Key packet */
+#define SIGTYPE_CASUAL_USERID 0x12 /* Casual certification of a User ID and Public Key packet */
+#define SIGTYPE_POSITIVE_USERID 0x13 /* Positive certification of a User ID and Public Key packet */
+
+#define SIGTYPE_SUBKEY_BINDING 0x18 /* Subkey Binding Signature */
+#define SIGTYPE_PRIMARY_KEY_BINDING 0x19 /* Primary Key Binding Signature */
+#define SIGTYPE_DIRECT_KEY 0x1f /* Signature directly on a key */
+
+#define SIGTYPE_KEY_REVOCATION 0x20 /* Key revocation signature */
+#define SIGTYPE_SUBKEY_REVOCATION 0x28 /* Subkey revocation signature */
+#define SIGTYPE_CERT_REVOCATION 0x30 /* Certification revocation signature */
+
+#define SIGTYPE_TIMESTAMP_SIG 0x40 /* Timestamp signature */
+#define SIGTYPE_3RDPARTY 0x50 /* Third-Party Confirmation signature */
+
+/* Forward declarations */
+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
+read_file(pgpv_t *pgp, const char *f)
+{
+ struct stat st;
+ pgpv_mem_t *mem;
+
+ ARRAY_EXPAND(pgp->areas);
+ ARRAY_COUNT(pgp->areas) += 1;
+ mem = &ARRAY_LAST(pgp->areas);
+ memset(mem, 0x0, sizeof(*mem));
+ if ((mem->fp = fopen(f, "r")) == NULL) {
+ warn("can't read '%s'", f);
+ return 0;
+ }
+ fstat(fileno(mem->fp), &st);
+ mem->size = (size_t)st.st_size;
+ mem->mem = mmap(NULL, mem->size, PROT_READ, MAP_SHARED, fileno(mem->fp), 0);
+ mem->dealloc = UNMAP_MEM;
+ return 1;
+}
+
+/* DTRT and free resources */
+static int
+closemem(pgpv_mem_t *mem)
+{
+ switch(mem->dealloc) {
+ case FREE_MEM:
+ free(mem->mem);
+ mem->size = 0;
+ break;
+ case UNMAP_MEM:
+ munmap(mem->mem, mem->size);
+ fclose(mem->fp);
+ break;
+ }
+ return 1;
+}
+
+/* make a reference to a memory area, and its offset */
+static void
+make_ref(pgpv_t *pgp, uint8_t mement, pgpv_ref_t *ref)
+{
+ ref->mem = mement;
+ ref->offset = ARRAY_ELEMENT(pgp->areas, ref->mem).cc;
+ ref->vp = pgp;
+}
+
+/* return the pointer we wanted originally */
+static uint8_t *
+get_ref(pgpv_ref_t *ref)
+{
+ pgpv_mem_t *mem;
+ pgpv_t *pgp = (pgpv_t *)ref->vp;;
+
+ mem = &ARRAY_ELEMENT(pgp->areas, ref->mem);
+ return &mem->mem[ref->offset];
+}
+
+#define IS_PARTIAL(x) ((x) >= 224 && (x) < 255)
+#define DECODE_PARTIAL(x) (1 << ((x) & 0x1f))
+
+#define PKT_LENGTH(m, off) \
+ ((m[off] < 192) ? (m[off]) : \
+ (m[off] < 224) ? ((m[off] - 192) << 8) + (m[off + 1]) + 192 : \
+ (m[off + 1] << 24) | ((m[off + 2]) << 16) | ((m[off + 3]) << 8) | (m[off + 4]))
+
+#define PKT_LENGTH_LENGTH(m, off) \
+ ((m[off] < 192) ? 1 : (m[off] < 224) ? 2 : 5)
+
+/* fix up partial body lengths, return new size */
+static size_t
+fixup_partials(pgpv_t *pgp, uint8_t *p, size_t totlen, size_t filesize, size_t *cc)
+{
+ pgpv_mem_t *mem;
+ size_t partial;
+ size_t newcc;
+
+ if (totlen > filesize) {
+ printf("fixup_partial: filesize %zu is less than encoded size %zu\n", filesize, totlen);
+ return 0;
+ }
+ ARRAY_EXPAND(pgp->areas);
+ ARRAY_COUNT(pgp->areas) += 1;
+ mem = &ARRAY_LAST(pgp->areas);
+ mem->size = totlen;
+ if ((mem->mem = calloc(1, mem->size + 5)) == NULL) {
+ printf("fixup_partial: can't allocate %zu length\n", totlen);
+ return 0;
+ }
+ newcc = 0;
+ mem->dealloc = FREE_MEM;
+ for (*cc = 0 ; *cc < totlen ; newcc += partial, *cc += partial + 1) {
+ if (IS_PARTIAL(p[*cc])) {
+ partial = DECODE_PARTIAL(p[*cc]);
+ memcpy(&mem->mem[newcc], &p[*cc + 1], partial);
+ } else {
+ partial = PKT_LENGTH(p, *cc);
+ *cc += PKT_LENGTH_LENGTH(p, *cc);
+ memcpy(&mem->mem[newcc], &p[*cc], partial);
+ newcc += partial;
+ *cc += partial;
+ break;
+ }
+ }
+ return newcc;
+}
+
+/* get the weirdo packet length */
+static size_t
+get_pkt_len(uint8_t newfmt, uint8_t *p, size_t filesize, int isprimary)
+{
+ size_t lenbytes;
+ size_t len;
+
+ if (newfmt) {
+ if (IS_PARTIAL(*p)) {
+ if (!isprimary) {
+ /* for sub-packets, only 1, 2 or 4 byte sizes allowed */
+ return ((*p - 192) << 8) + *(p + 1) + 192;
+ }
+ lenbytes = 1;
+ for (len = DECODE_PARTIAL(*p) ; IS_PARTIAL(p[len + lenbytes]) ; lenbytes++) {
+ len += DECODE_PARTIAL(p[len + lenbytes]);
+ }
+ len += get_pkt_len(newfmt, &p[len + lenbytes], filesize, 1);
+ return len;
+ }
+ return PKT_LENGTH(p, 0);
+ } else {
+ switch(*--p & 0x3) {
+ case 0:
+ return *(p + 1);
+ case 1:
+ return (*(p + 1) << 8) | *(p + 2);
+ case 2:
+ return (*(p + 1) << 24) | (*(p + 2) << 16) | (*(p + 3) << 8) | *(p + 4);
+ default:
+ return filesize;
+ }
+ }
+}
+
+/* get the length of the packet length field */
+static unsigned
+get_pkt_len_len(uint8_t newfmt, uint8_t *p, int isprimary)
+{
+ if (newfmt) {
+ if (IS_PARTIAL(*p)) {
+ return (isprimary) ? 1 : 2;
+ }
+ return PKT_LENGTH_LENGTH(p, 0);
+ } else {
+ switch(*--p & 0x3) {
+ case 0:
+ return 1;
+ case 1:
+ return 2;
+ case 2:
+ return 4;
+ default:
+ return 0;
+ }
+ }
+}
+
+/* copy the 32bit integer in memory in network order */
+static unsigned
+fmt_32(uint8_t *p, uint32_t a)
+{
+ a = htonl(a);
+ memcpy(p, &a, sizeof(a));
+ return sizeof(a);
+}
+
+/* copy the 16bit integer in memory in network order */
+static unsigned
+fmt_16(uint8_t *p, uint16_t a)
+{
+ a = htons(a);
+ memcpy(p, &a, sizeof(a));
+ return sizeof(a);
+}
+
+/* format a binary string in memory */
+static size_t
+fmt_binary(char *s, size_t size, const uint8_t *bin, unsigned len)
+{
+ unsigned i;
+ size_t cc;
+
+ for (cc = 0, i = 0 ; i < len && cc < size ; i++) {
+ cc += snprintf(&s[cc], size - cc, "%02x", bin[i]);
+ }
+ return cc;
+}
+
+/* format an mpi into memory */
+static unsigned
+fmt_binary_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t size)
+{
+ unsigned bytes;
+ BIGNUM *bn;
+
+ bytes = BITS_TO_BYTES(mpi->bits);
+ if ((size_t)bytes + 2 + 1 > size) {
+ warn("truncated mpi");
+ return 0;
+ }
+ bn = (BIGNUM *)mpi->bn;
+ if (bn == NULL || BN_is_zero(bn)) {
+ fmt_32(p, 0);
+ return 2 + 1;
+ }
+ fmt_16(p, mpi->bits);
+ BN_bn2bin(bn, &p[2]);
+ return bytes + 2;
+}
+
+/* dump an mpi value onto stdout */
+static size_t
+fmt_mpi(char *s, size_t size, pgpv_bignum_t *bn, const char *name, int pbits)
+{
+ size_t cc;
+ char *buf;
+
+ cc = snprintf(s, size, "%s=", name);
+ if (pbits) {
+ cc += snprintf(&s[cc], size - cc, "[%u bits] ", bn->bits);
+ }
+ buf = BN_bn2hex(bn->bn);
+ cc += snprintf(&s[cc], size - cc, "%s\n", buf);
+ free(buf);
+ return cc;
+}
+
+#define ALG_IS_RSA(alg) (((alg) == PUBKEY_RSA_ENCRYPT_OR_SIGN) || \
+ ((alg) == PUBKEY_RSA_ENCRYPT) || \
+ ((alg) == PUBKEY_RSA_SIGN))
+
+#define ALG_IS_DSA(alg) ((alg) == PUBKEY_DSA)
+
+/* format key mpis into memory */
+static unsigned
+fmt_key_mpis(pgpv_pubkey_t *pubkey, uint8_t *buf, size_t size)
+{
+ size_t cc;
+
+ cc = 0;
+ buf[cc++] = pubkey->version;
+ cc += fmt_32(&buf[cc], (uint32_t)pubkey->birth);
+ buf[cc++] = pubkey->keyalg;
+ switch(pubkey->keyalg) {
+ case PUBKEY_RSA_ENCRYPT_OR_SIGN:
+ case PUBKEY_RSA_ENCRYPT:
+ case PUBKEY_RSA_SIGN:
+ cc += fmt_binary_mpi(&pubkey->bn[RSA_N], &buf[cc], size - cc);
+ cc += fmt_binary_mpi(&pubkey->bn[RSA_E], &buf[cc], size - cc);
+ break;
+ case PUBKEY_DSA:
+ cc += fmt_binary_mpi(&pubkey->bn[DSA_P], &buf[cc], size - cc);
+ cc += fmt_binary_mpi(&pubkey->bn[DSA_Q], &buf[cc], size - cc);
+ cc += fmt_binary_mpi(&pubkey->bn[DSA_G], &buf[cc], size - cc);
+ cc += fmt_binary_mpi(&pubkey->bn[DSA_Y], &buf[cc], size - cc);
+ break;
+ default:
+ cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_P], &buf[cc], size - cc);
+ cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_G], &buf[cc], size - cc);
+ cc += fmt_binary_mpi(&pubkey->bn[ELGAMAL_Y], &buf[cc], size - cc);
+ break;
+ }
+ return (unsigned)cc;
+}
+
+/* calculate the fingerprint, RFC 4880, section 12.2 */
+static int
+pgpv_calc_fingerprint(pgpv_fingerprint_t *fingerprint, pgpv_pubkey_t *pubkey)
+{
+ digest_t fphash;
+ uint16_t cc;
+ uint8_t ch = 0x99;
+ uint8_t buf[8192 + 2 + 1];
+ uint8_t len[2];
+
+ memset(&fphash, 0x0, sizeof(fphash));
+ if (pubkey->version == 4) {
+ /* v4 keys */
+ fingerprint->hashalg = digest_get_alg("sha1");
+ digest_init(&fphash, (unsigned)fingerprint->hashalg);
+ cc = fmt_key_mpis(pubkey, buf, sizeof(buf));
+ digest_update(&fphash, &ch, 1);
+ fmt_16(len, cc);
+ digest_update(&fphash, len, 2);
+ digest_update(&fphash, buf, cc);
+ fingerprint->len = digest_final(fingerprint->v, &fphash);
+ return 1;
+ }
+ if (ALG_IS_RSA(pubkey->keyalg)) {
+ /* v3 keys are RSA */
+ fingerprint->hashalg = digest_get_alg("md5");
+ digest_init(&fphash, (unsigned)fingerprint->hashalg);
+ if (pubkey->bn[RSA_N].bn && pubkey->bn[RSA_E].bn) {
+ cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf));
+ digest_update(&fphash, &buf[2], cc - 2);
+ cc = fmt_binary_mpi(&pubkey->bn[RSA_E], buf, sizeof(buf));
+ digest_update(&fphash, &buf[2], cc - 2);
+ fingerprint->len = digest_final(fingerprint->v, &fphash);
+ return 1;
+ }
+ }
+ if (pubkey->bn[RSA_N].bn) {
+ if ((cc = fmt_binary_mpi(&pubkey->bn[RSA_N], buf, sizeof(buf))) >= PGPV_KEYID_LEN) {
+ memcpy(fingerprint->v, &buf[cc - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
+ fingerprint->len = PGPV_KEYID_LEN;
+ return 1;
+ }
+ }
+ /* exhausted all avenues, really */
+ memset(fingerprint->v, 0xff, fingerprint->len = PGPV_KEYID_LEN);
+ return 1;
+}
+
+/* format a fingerprint into memory */
+static size_t
+fmt_fingerprint(char *s, size_t size, pgpv_fingerprint_t *fingerprint, const char *name)
+{
+ unsigned i;
+ size_t cc;
+
+ cc = snprintf(s, size, "%s ", name);
+ for (i = 0 ; i < fingerprint->len ; i++) {
+ cc += snprintf(&s[cc], size - cc, "%02hhx%s",
+ fingerprint->v[i], (i % 2 == 1) ? " " : "");
+ }
+ cc += snprintf(&s[cc], size - cc, "\n");
+ return cc;
+}
+
+/* calculate keyid from a pubkey */
+static int
+pgpv_calc_keyid(pgpv_pubkey_t *key)
+{
+ pgpv_calc_fingerprint(&key->fingerprint, key);
+ memcpy(key->keyid, &key->fingerprint.v[key->fingerprint.len - PGPV_KEYID_LEN], PGPV_KEYID_LEN);
+ return 1;
+}
+
+/* convert a hex string to a 64bit key id (in big endian byte order */
+static void
+str_to_keyid(const char *s, uint8_t *keyid)
+{
+ uint64_t u64;
+
+ u64 = (uint64_t)strtoull(s, NULL, 16);
+ u64 = ((u64 & 0x00000000000000FFUL) << 56) |
+ ((u64 & 0x000000000000FF00UL) << 40) |
+ ((u64 & 0x0000000000FF0000UL) << 24) |
+ ((u64 & 0x00000000FF000000UL) << 8) |
+ ((u64 & 0x000000FF00000000UL) >> 8) |
+ ((u64 & 0x0000FF0000000000UL) >> 24) |
+ ((u64 & 0x00FF000000000000UL) >> 40) |
+ ((u64 & 0xFF00000000000000UL) >> 56);
+ memcpy(keyid, &u64, PGPV_KEYID_LEN);
+}
+
+#define PKT_ALWAYS_ON 0x80
+#define PKT_NEWFMT_MASK 0x40
+#define PKT_NEWFMT_TAG_MASK 0x3f
+#define PKT_OLDFMT_TAG_MASK 0x3c
+
+#define SUBPKT_CRITICAL_MASK 0x80
+#define SUBPKT_TAG_MASK 0x7f
+
+#define SUBPKT_SIG_BIRTH 2
+#define SUBPKT_SIG_EXPIRY 3
+#define SUBPKT_EXPORT_CERT 4
+#define SUBPKT_TRUST_SIG 5
+#define SUBPKT_REGEXP 6
+#define SUBPKT_REVOCABLE 7
+#define SUBPKT_KEY_EXPIRY 9
+#define SUBPKT_BWD_COMPAT 10
+#define SUBPKT_PREF_SYMMETRIC_ALG 11
+#define SUBPKT_REVOCATION_KEY 12
+#define SUBPKT_ISSUER 16
+#define SUBPKT_NOTATION 20
+#define SUBPKT_PREF_HASH_ALG 21
+#define SUBPKT_PREF_COMPRESS_ALG 22
+#define SUBPKT_KEY_SERVER_PREFS 23
+#define SUBPKT_PREF_KEY_SERVER 24
+#define SUBPKT_PRIMARY_USER_ID 25
+#define SUBPKT_POLICY_URI 26
+#define SUBPKT_KEY_FLAGS 27
+#define SUBPKT_SIGNER_ID 28
+#define SUBPKT_REVOCATION_REASON 29
+#define SUBPKT_FEATURES 30
+#define SUBPKT_SIGNATURE_TARGET 31
+#define SUBPKT_EMBEDDED_SIGNATURE 32
+
+#define UNCOMPRESSED 0
+#define ZIP_COMPRESSION 1
+#define ZLIB_COMPRESSION 2
+#define BZIP2_COMPRESSION 3
+
+/* get a 16 bit integer, in host order */
+static uint16_t
+get_16(uint8_t *p)
+{
+ uint16_t u16;
+
+ memcpy(&u16, p, sizeof(u16));
+ return ntohs(u16);
+}
+
+/* get a 32 bit integer, in host order */
+static uint32_t
+get_32(uint8_t *p)
+{
+ uint32_t u32;
+
+ memcpy(&u32, p, sizeof(u32));
+ return ntohl(u32);
+}
+
+#define HOURSECS (int64_t)(60 * 60)
+#define DAYSECS (int64_t)(24 * 60 * 60)
+#define MONSECS (int64_t)(30 * DAYSECS)
+#define YEARSECS (int64_t)(365 * DAYSECS)
+
+/* format (human readable) time into memory */
+static size_t
+fmt_time(char *s, size_t size, const char *header, int64_t n, const char *trailer, int relative)
+{
+ struct tm tm;
+ time_t elapsed;
+ time_t now;
+ time_t t;
+ size_t cc;
+
+ t = (time_t)n;
+ now = time(NULL);
+ elapsed = now - t;
+ gmtime_r(&t, &tm);
+ cc = snprintf(s, size, "%s%04d-%02d-%02d", header,
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
+ if (relative) {
+ cc += snprintf(&s[cc], size - cc, " (%lldy %lldm %lldd %lldh %s)",
+ llabs((long long)elapsed / YEARSECS),
+ llabs(((long long)elapsed % YEARSECS) / MONSECS),
+ llabs(((long long)elapsed % MONSECS) / DAYSECS),
+ llabs(((long long)elapsed % DAYSECS) / HOURSECS),
+ (now > t) ? "ago" : "ahead");
+ }
+ cc += snprintf(&s[cc], size - cc, "%s", trailer);
+ return cc;
+}
+
+/* dump key mpis to stdout */
+static void
+print_key_mpis(pgpv_bignum_t *v, uint8_t keyalg)
+{
+ char s[8192];
+
+ switch(keyalg) {
+ case PUBKEY_RSA_ENCRYPT_OR_SIGN:
+ case PUBKEY_RSA_ENCRYPT:
+ case PUBKEY_RSA_SIGN:
+ fmt_mpi(s, sizeof(s), &v[RSA_N], "rsa.n", 1);
+ printf("%s", s);
+ fmt_mpi(s, sizeof(s), &v[RSA_E], "rsa.e", 1);
+ printf("%s", s);
+ break;
+ case PUBKEY_ELGAMAL_ENCRYPT:
+ fmt_mpi(s, sizeof(s), &v[ELGAMAL_P], "elgamal.p", 1);
+ printf("%s", s);
+ fmt_mpi(s, sizeof(s), &v[ELGAMAL_Y], "elgamal.y", 1);
+ printf("%s", s);
+ break;
+ case PUBKEY_DSA:
+ fmt_mpi(s, sizeof(s), &v[DSA_P], "dsa.p", 1);
+ printf("%s", s);
+ fmt_mpi(s, sizeof(s), &v[DSA_Q], "dsa.q", 1);
+ printf("%s", s);
+ fmt_mpi(s, sizeof(s), &v[DSA_G], "dsa.g", 1);
+ printf("%s", s);
+ fmt_mpi(s, sizeof(s), &v[DSA_Y], "dsa.y", 1);
+ printf("%s", s);
+ break;
+ default:
+ printf("hi, unusual keyalg %u\n", keyalg);
+ break;
+ }
+}
+
+/* get an mpi, including 2 byte length */
+static int
+get_mpi(pgpv_bignum_t *mpi, uint8_t *p, size_t pktlen, size_t *off)
+{
+ size_t bytes;
+
+ mpi->bits = get_16(p);
+ if ((bytes = (size_t)BITS_TO_BYTES(mpi->bits)) > pktlen) {
+ return 0;
+ }
+ *off += sizeof(mpi->bits);
+ mpi->bn = BN_bin2bn(&p[sizeof(mpi->bits)], (int)bytes, NULL);
+ *off += bytes;
+ return 1;
+}
+
+/* read mpis in signature */
+static int
+read_signature_mpis(pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
+{
+ size_t off;
+
+ off = 0;
+ switch(sigpkt->sig.keyalg) {
+ case PUBKEY_RSA_ENCRYPT_OR_SIGN:
+ case PUBKEY_RSA_SIGN:
+ case PUBKEY_RSA_ENCRYPT:
+ if (!get_mpi(&sigpkt->sig.bn[RSA_SIG], p, pktlen, &off)) {
+ printf("sigpkt->version %d, rsa sig weird\n", sigpkt->sig.version);
+ return 0;
+ }
+ break;
+ case PUBKEY_DSA:
+ case PUBKEY_ECDSA:
+ case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN: /* deprecated */
+ if (!get_mpi(&sigpkt->sig.bn[DSA_R], p, pktlen, &off) ||
+ !get_mpi(&sigpkt->sig.bn[DSA_S], &p[off], pktlen, &off)) {
+ printf("sigpkt->version %d, dsa/elgamal sig weird\n", sigpkt->sig.version);
+ return 0;
+ }
+ break;
+ default:
+ printf("weird type of sig! %d\n", sigpkt->sig.keyalg);
+ return 0;
+ }
+ return 1;
+}
+
+/* add the signature sub packet to the signature packet */
+static int
+add_subpacket(pgpv_sigpkt_t *sigpkt, uint8_t tag, uint8_t *p, uint16_t len)
+{
+ pgpv_sigsubpkt_t subpkt;
+
+ memset(&subpkt, 0x0, sizeof(subpkt));
+ subpkt.s.size = len;
+ subpkt.critical = 0;
+ subpkt.tag = tag;
+ subpkt.s.data = p;
+ ARRAY_APPEND(sigpkt->subpkts, subpkt);
+ return 1;
+}
+
+/* read the subpackets in the signature */
+static int
+read_sig_subpackets(pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
+{
+ pgpv_sigsubpkt_t subpkt;
+ const int is_subpkt = 0;
+ unsigned lenlen;
+ unsigned i;
+ uint8_t *start;
+
+ start = p;
+ for (i = 0 ; (unsigned)(p - start) < sigpkt->subslen ; i++) {
+ memset(&subpkt, 0x0, sizeof(subpkt));
+ subpkt.s.size = get_pkt_len(1, p, 0, is_subpkt);
+ lenlen = get_pkt_len_len(1, p, is_subpkt);
+ if (lenlen > pktlen) {
+ printf("weird lenlen %u\n", lenlen);
+ return 0;
+ }
+ p += lenlen;
+ subpkt.critical = (*p & SUBPKT_CRITICAL_MASK);
+ subpkt.tag = (*p & SUBPKT_TAG_MASK);
+ p += 1;
+ switch(subpkt.tag) {
+ case SUBPKT_SIG_BIRTH:
+ sigpkt->sig.birth = (int64_t)get_32(p);
+ break;
+ case SUBPKT_SIG_EXPIRY:
+ sigpkt->sig.expiry = (int64_t)get_32(p);
+ break;
+ case SUBPKT_KEY_EXPIRY:
+ sigpkt->sig.keyexpiry = (int64_t)get_32(p);
+ break;
+ case SUBPKT_ISSUER:
+ sigpkt->sig.signer = p;
+ break;
+ case SUBPKT_SIGNER_ID:
+ sigpkt->sig.signer = p;
+ break;
+ case SUBPKT_TRUST_SIG:
+ sigpkt->sig.trustsig = *p;
+ break;
+ case SUBPKT_REGEXP:
+ sigpkt->sig.regexp = (char *)(void *)p;
+ break;
+ case SUBPKT_REVOCABLE:
+ sigpkt->sig.revocable = *p;
+ break;
+ case SUBPKT_PREF_SYMMETRIC_ALG:
+ sigpkt->sig.pref_symm_alg = *p;
+ break;
+ case SUBPKT_REVOCATION_KEY:
+ sigpkt->sig.revoke_sensitive = (*p & 0x40);
+ sigpkt->sig.revoke_alg = p[1];
+ sigpkt->sig.revoke_fingerprint = &p[2];
+ break;
+ case SUBPKT_NOTATION:
+ sigpkt->sig.notation = *p;
+ break;
+ case SUBPKT_PREF_HASH_ALG:
+ sigpkt->sig.pref_hash_alg = *p;
+ break;
+ case SUBPKT_PREF_COMPRESS_ALG:
+ sigpkt->sig.pref_compress_alg = *p;
+ break;
+ case SUBPKT_PREF_KEY_SERVER:
+ sigpkt->sig.pref_key_server = (char *)(void *)p;
+ break;
+ case SUBPKT_KEY_SERVER_PREFS:
+ sigpkt->sig.key_server_modify = *p;
+ break;
+ case SUBPKT_KEY_FLAGS:
+ sigpkt->sig.type_key = *p;
+ break;
+ case SUBPKT_PRIMARY_USER_ID:
+ sigpkt->sig.primary_userid = *p;
+ break;
+ case SUBPKT_POLICY_URI:
+ sigpkt->sig.policy = (char *)(void *)p;
+ break;
+ case SUBPKT_FEATURES:
+ sigpkt->sig.features = (char *)(void *)p;
+ break;
+ case SUBPKT_REVOCATION_REASON:
+ sigpkt->sig.revoked = *p++ + 1;
+ sigpkt->sig.why_revoked = (char *)(void *)p;
+ break;
+ default:
+ printf("Ignoring unusual/reserved signature subpacket %d\n", subpkt.tag);
+ break;
+ }
+ subpkt.s.data = p;
+ p += subpkt.s.size - 1;
+ ARRAY_APPEND(sigpkt->subpkts, subpkt);
+ }
+ return 1;
+}
+
+/* parse signature packet */
+static int
+read_sigpkt(pgpv_t *pgp, uint8_t mement, pgpv_sigpkt_t *sigpkt, uint8_t *p, size_t pktlen)
+{
+ unsigned lenlen;
+ uint8_t *base;
+
+ make_ref(pgp, mement, &sigpkt->sig.hashstart);
+ base = p;
+ switch(sigpkt->sig.version = *p++) {
+ case 2:
+ case 3:
+ if ((lenlen = *p++) != 5) {
+ printf("read_sigpkt: hashed length not 5\n");
+ return 0;
+ }
+ sigpkt->sig.hashlen = lenlen;
+ /* put birthtime into a subpacket */
+ sigpkt->sig.type = *p++;
+ add_subpacket(sigpkt, SUBPKT_SIG_BIRTH, p, sizeof(uint32_t));
+ sigpkt->sig.birth = (int64_t)get_32(p);
+ p += sizeof(uint32_t);
+ sigpkt->sig.signer = p;
+ add_subpacket(sigpkt, SUBPKT_SIGNER_ID, p, PGPV_KEYID_LEN);
+ p += PGPV_KEYID_LEN;
+ sigpkt->sig.keyalg = *p++;
+ sigpkt->sig.hashalg = *p++;
+ sigpkt->sig.hash2 = p;
+ if (!read_signature_mpis(sigpkt, sigpkt->sig.mpi = p + 2, pktlen)) {
+ printf("read_sigpkt: can't read sigs v3\n");
+ return 0;
+ }
+ break;
+ case 4:
+ sigpkt->sig.type = *p++;
+ sigpkt->sig.keyalg = *p++;
+ sigpkt->sig.hashalg = *p++;
+ sigpkt->subslen = get_16(p);
+ p += sizeof(sigpkt->subslen);
+ if (!read_sig_subpackets(sigpkt, p, pktlen)) {
+ printf("read_sigpkt: can't read sig subpackets, v4\n");
+ return 0;
+ }
+ if (!sigpkt->sig.signer) {
+ sigpkt->sig.signer = get_ref(&sigpkt->sig.hashstart) + 16;
+ }
+ p += sigpkt->subslen;
+ sigpkt->sig.hashlen = (unsigned)(p - base);
+ sigpkt->unhashlen = get_16(p);
+ p += sizeof(sigpkt->unhashlen) + sigpkt->unhashlen;
+ sigpkt->sig.hash2 = p;
+ if (!read_signature_mpis(sigpkt, sigpkt->sig.mpi = p + 2, pktlen)) {
+ printf("read_sigpkt: can't read sigs, v4\n");
+ return 0;
+ }
+ break;
+ default:
+ printf("read_sigpkt: unusual signature version (%u)\n", sigpkt->sig.version);
+ break;
+ }
+ return 1;
+}
+
+
+/* this parses compressed data, decompresses it, and calls the parser again */
+static int
+read_compressed(pgpv_t *pgp, pgpv_compress_t *compressed, uint8_t *p, size_t len)
+{
+ pgpv_mem_t *unzmem;
+ bz_stream bz;
+ z_stream z;
+ int ok = 0;
+
+ compressed->compalg = *p;
+ compressed->s.size = len;
+ if ((compressed->s.data = calloc(1, len)) == NULL) {
+ printf("read_compressed: can't allocate %zu length\n", len);
+ return 0;
+ }
+ switch(compressed->compalg) {
+ case UNCOMPRESSED:
+ printf("not implemented %d compression yet\n", compressed->compalg);
+ return 0;
+ default:
+ break;
+ }
+ ARRAY_EXPAND(pgp->areas);
+ ARRAY_COUNT(pgp->areas) += 1;
+ unzmem = &ARRAY_LAST(pgp->areas);
+ unzmem->size = len * 10;
+ unzmem->dealloc = FREE_MEM;
+ if ((unzmem->mem = calloc(1, unzmem->size)) == NULL) {
+ printf("read_compressed: calloc failed!\n");
+ return 0;
+ }
+ switch(compressed->compalg) {
+ case ZIP_COMPRESSION:
+ case ZLIB_COMPRESSION:
+ memset(&z, 0x0, sizeof(z));
+ z.next_in = p + 1;
+ z.avail_in = (unsigned)(len - 1);
+ z.total_in = (unsigned)(len - 1);
+ z.next_out = unzmem->mem;
+ z.avail_out = (unsigned)unzmem->size;
+ z.total_out = (unsigned)unzmem->size;
+ break;
+ case BZIP2_COMPRESSION:
+ memset(&bz, 0x0, sizeof(bz));
+ bz.avail_in = (unsigned)(len - 1);
+ bz.next_in = (char *)(void *)p + 1;
+ bz.next_out = (char *)(void *)unzmem->mem;
+ bz.avail_out = (unsigned)unzmem->size;
+ break;
+ }
+ switch(compressed->compalg) {
+ case ZIP_COMPRESSION:
+ ok = (inflateInit2(&z, -15) == Z_OK);
+ break;
+ case ZLIB_COMPRESSION:
+ ok = (inflateInit(&z) == Z_OK);
+ break;
+ case BZIP2_COMPRESSION:
+ ok = (BZ2_bzDecompressInit(&bz, 1, 0) == BZ_OK);
+ break;
+ }
+ if (!ok) {
+ printf("read_compressed: initialisation failed!\n");
+ return 0;
+ }
+ switch(compressed->compalg) {
+ case ZIP_COMPRESSION:
+ case ZLIB_COMPRESSION:
+ ok = (inflate(&z, Z_FINISH) == Z_STREAM_END);
+ unzmem->size = z.total_out;
+ break;
+ case BZIP2_COMPRESSION:
+ ok = (BZ2_bzDecompress(&bz) == BZ_STREAM_END);
+ unzmem->size = ((uint64_t)bz.total_out_hi32 << 32) | bz.total_out_lo32;
+ break;
+ }
+ if (!ok) {
+ printf("read_compressed: inflate failed!\n");
+ return 0;
+ }
+ return 1;
+}
+
+/* parse one pass signature packet */
+static int
+read_onepass_sig(pgpv_onepass_t *onepasspkt, uint8_t *mem)
+{
+ onepasspkt->version = mem[0];
+ onepasspkt->type = mem[1];
+ onepasspkt->hashalg = mem[2];
+ onepasspkt->keyalg = mem[3];
+ memcpy(onepasspkt->keyid, &mem[4], sizeof(onepasspkt->keyid));
+ onepasspkt->nested = mem[12];
+ return 1;
+}
+
+/* parse public key packet */
+static int
+read_pubkey(pgpv_pubkey_t *pubkey, uint8_t *mem, size_t pktlen, int pbn)
+{
+ size_t off;
+
+ off = 0;
+ pubkey->version = mem[off++];
+ pubkey->birth = get_32(&mem[off]);
+ off += 4;
+ if (pubkey->version == 2 || pubkey->version == 3) {
+ pubkey->expiry = get_16(&mem[off]) * DAYSECS;
+ off += 2;
+ }
+ if ((pubkey->keyalg = mem[off++]) == 0) {
+ pubkey->keyalg = PUBKEY_RSA_ENCRYPT_OR_SIGN;
+ printf("got unusual pubkey keyalg %u\n", mem[off - 1]);
+ }
+ switch(pubkey->keyalg) {
+ case PUBKEY_RSA_ENCRYPT_OR_SIGN:
+ case PUBKEY_RSA_ENCRYPT:
+ case PUBKEY_RSA_SIGN:
+ if (!get_mpi(&pubkey->bn[RSA_N], &mem[off], pktlen, &off) ||
+ !get_mpi(&pubkey->bn[RSA_E], &mem[off], pktlen, &off)) {
+ return 0;
+ }
+ break;
+ case PUBKEY_ELGAMAL_ENCRYPT:
+ case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
+ if (!get_mpi(&pubkey->bn[ELGAMAL_P], &mem[off], pktlen, &off) ||
+ !get_mpi(&pubkey->bn[ELGAMAL_Y], &mem[off], pktlen, &off)) {
+ return 0;
+ }
+ break;
+ case PUBKEY_DSA:
+ if (!get_mpi(&pubkey->bn[DSA_P], &mem[off], pktlen, &off) ||
+ !get_mpi(&pubkey->bn[DSA_Q], &mem[off], pktlen, &off) ||
+ !get_mpi(&pubkey->bn[DSA_G], &mem[off], pktlen, &off) ||
+ !get_mpi(&pubkey->bn[DSA_Y], &mem[off], pktlen, &off)) {
+ return 0;
+ }
+ break;
+ default:
+ printf("hi, different type of pubkey here %u\n", pubkey->keyalg);
+ break;
+ }
+ if (pbn) {
+ print_key_mpis(pubkey->bn, pubkey->keyalg);
+ }
+ return 1;
+}
+
+/* parse a user attribute */
+static int
+read_userattr(pgpv_userattr_t *userattr, uint8_t *p, size_t pktlen)
+{
+ pgpv_string_t subattr;
+ const int is_subpkt = 0;
+ const int indian = 1;
+ unsigned lenlen;
+ uint16_t imagelen;
+ size_t cc;
+
+ userattr->len = pktlen;
+ for (cc = 0 ; cc < pktlen ; cc += subattr.size + lenlen + 1) {
+ subattr.size = get_pkt_len(1, p, 0, is_subpkt);
+ lenlen = get_pkt_len_len(1, p, is_subpkt);
+ if (lenlen > pktlen) {
+ printf("weird lenlen %u\n", lenlen);
+ return 0;
+ }
+ p += lenlen;
+ if (*p++ != 1) {
+ printf("image type (%u) != 1. weird packet\n", *(p - 1));
+ }
+ memcpy(&imagelen, p, sizeof(imagelen));
+ if (!*(const char *)(const void *)&indian) {
+ /* big endian - byteswap length */
+ imagelen = (((unsigned)imagelen & 0xff) << 8) | (((unsigned)imagelen >> 8) & 0xff);
+ }
+ subattr.data = p + 3;
+ p += subattr.size;
+ ARRAY_APPEND(userattr->subattrs, subattr);
+ }
+ return 1;
+}
+
+#define LITDATA_BINARY 'b'
+#define LITDATA_TEXT 't'
+#define LITDATA_UTF8 'u'
+
+/* parse literal packet */
+static int
+read_litdata(pgpv_t *pgp, pgpv_litdata_t *litdata, uint8_t *p, size_t size)
+{
+ size_t cc;
+
+ cc = 0;
+ switch(litdata->format = p[cc++]) {
+ case LITDATA_BINARY:
+ case LITDATA_TEXT:
+ case LITDATA_UTF8:
+ litdata->namelen = 0;
+ break;
+ default:
+ printf("weird litdata format %u\n", litdata->format);
+ break;
+ }
+ litdata->namelen = p[cc++];
+ litdata->filename = &p[cc];
+ cc += litdata->namelen;
+ litdata->secs = get_32(&p[cc]);
+ cc += 4;
+ litdata->s.data = &p[cc];
+ litdata->len = litdata->s.size = size - cc;
+ litdata->mem = ARRAY_COUNT(pgp->areas) - 1;
+ litdata->offset = cc;
+ return 1;
+}
+
+/* parse a single packet */
+static int
+read_pkt(pgpv_t *pgp, pgpv_mem_t *mem)
+{
+ const int isprimary = 1;
+ pgpv_pkt_t pkt;
+ pgpv_mem_t *newmem;
+ unsigned lenlen;
+ uint8_t ispartial;
+ size_t size;
+
+ memset(&pkt, 0x0, sizeof(pkt));
+ pkt.tag = mem->mem[mem->cc++];
+ if (!(pkt.tag & PKT_ALWAYS_ON)) {
+ printf("BAD PACKET - bit 7 not 1, offset %zu!\n", mem->cc - 1);
+ }
+ pkt.newfmt = (pkt.tag & PKT_NEWFMT_MASK);
+ pkt.tag = (pkt.newfmt) ?
+ (pkt.tag & PKT_NEWFMT_TAG_MASK) :
+ (((unsigned)pkt.tag & PKT_OLDFMT_TAG_MASK) >> 2);
+ ispartial = (pkt.newfmt && IS_PARTIAL(mem->mem[mem->cc]));
+ pkt.s.size = get_pkt_len(pkt.newfmt, &mem->mem[mem->cc], mem->size - mem->cc, isprimary);
+ lenlen = get_pkt_len_len(pkt.newfmt, &mem->mem[mem->cc], isprimary);
+ pkt.offset = mem->cc;
+ mem->cc += lenlen;
+ pkt.mement = (uint8_t)(mem - ARRAY_ARRAY(pgp->areas));
+ pkt.s.data = &mem->mem[mem->cc];
+ if (strchr(mem->allowed, pkt.tag) == NULL) {
+ printf("packet %d not allowed for operation %s\n", pkt.tag, pgp->op);
+ return 0;
+ }
+ size = pkt.s.size;
+ if (ispartial) {
+ pkt.s.size = fixup_partials(pgp, &mem->mem[mem->cc - lenlen], pkt.s.size, mem->size, &size);
+ newmem = &ARRAY_LAST(pgp->areas);
+ pkt.mement = (uint8_t)(newmem - ARRAY_ARRAY(pgp->areas));
+ pkt.s.data = newmem->mem;
+ size -= 1;
+ }
+ switch(pkt.tag) {
+ case SIGNATURE_PKT:
+ if (!read_sigpkt(pgp, pkt.mement, &pkt.u.sigpkt, pkt.s.data, pkt.s.size)) {
+ return 0;
+ }
+ break;
+ case ONEPASS_SIGNATURE_PKT:
+ read_onepass_sig(&pkt.u.onepass, pkt.s.data);
+ break;
+ case PUBKEY_PKT:
+ case PUB_SUBKEY_PKT:
+ break;
+ case LITDATA_PKT:
+ read_litdata(pgp, &pkt.u.litdata, pkt.s.data, pkt.s.size);
+ break;
+ case TRUST_PKT:
+ pkt.u.trust.level = pkt.s.data[0];
+ pkt.u.trust.amount = pkt.s.data[1];
+ break;
+ case USERID_PKT:
+ pkt.u.userid.size = pkt.s.size;
+ pkt.u.userid.data = pkt.s.data;
+ break;
+ case COMPRESSED_DATA_PKT:
+ read_compressed(pgp, &pkt.u.compressed, pkt.s.data, pkt.s.size);
+ ARRAY_APPEND(pgp->pkts, pkt);
+ read_all_packets(pgp, &ARRAY_LAST(pgp->areas), pgp->op);
+ break;
+ case USER_ATTRIBUTE_PKT:
+ read_userattr(&pkt.u.userattr, pkt.s.data, pkt.s.size);
+ break;
+ default:
+ printf("hi, need to implement %d, offset %zu\n", pkt.tag, mem->cc);
+ break;
+ }
+ mem->cc += size;
+ if (pkt.tag != COMPRESSED_DATA_PKT) {
+ /* compressed was added earlier to preserve pkt ordering */
+ ARRAY_APPEND(pgp->pkts, pkt);
+ }
+ return 1;
+}
+
+/* checks the tag type of a packet */
+static int
+pkt_is(pgpv_t *pgp, int wanted)
+{
+ return (ARRAY_ELEMENT(pgp->pkts, pgp->pkt).tag == wanted);
+}
+
+/* checks the packet is a signature packet, and the signature type is the expected one */
+static int
+pkt_sigtype_is(pgpv_t *pgp, int wanted)
+{
+ if (!pkt_is(pgp, SIGNATURE_PKT)) {
+ return 0;
+ }
+ return (ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.sigpkt.sig.type == wanted);
+}
+
+/* check for expected type of packet, and move to the next */
+static int
+pkt_accept(pgpv_t *pgp, int expected)
+{
+ int got;
+
+ if ((got = ARRAY_ELEMENT(pgp->pkts, pgp->pkt).tag) == expected) {
+ pgp->pkt += 1;
+ return 1;
+ }
+ printf("problem at token %zu, expcted %d, got %d\n", pgp->pkt, expected, got);
+ return 0;
+}
+
+/* recognise signature (and trust) packet */
+static int
+recog_signature(pgpv_t *pgp, pgpv_signature_t *signature)
+{
+ if (!pkt_is(pgp, SIGNATURE_PKT)) {
+ printf("recog_signature: not a signature packet\n");
+ return 0;
+ }
+ memcpy(signature, &ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.sigpkt.sig, sizeof(*signature));
+ pgp->pkt += 1;
+ if (pkt_is(pgp, TRUST_PKT)) {
+ pkt_accept(pgp, TRUST_PKT);
+ }
+ return 1;
+}
+
+/* recognise user id packet */
+static int
+recog_userid(pgpv_t *pgp, pgpv_signed_userid_t *userid)
+{
+ pgpv_signature_t signature;
+ pgpv_pkt_t *pkt;
+
+ memset(userid, 0x0, sizeof(*userid));
+ if (!pkt_is(pgp, USERID_PKT)) {
+ printf("recog_userid: not %d\n", USERID_PKT);
+ return 0;
+ }
+ pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
+ userid->userid.size = pkt->s.size;
+ userid->userid.data = pkt->s.data;
+ pgp->pkt += 1;
+ while (pkt_is(pgp, SIGNATURE_PKT)) {
+ if (!recog_signature(pgp, &signature)) {
+ printf("recog_userid: can't recognise signature/trust\n");
+ return 0;
+ }
+ ARRAY_APPEND(userid->sigs, signature);
+ if (signature.primary_userid) {
+ userid->primary_userid = signature.primary_userid;
+ }
+ if (signature.revoked) {
+ userid->revoked = signature.revoked;
+ }
+ }
+ return 1;
+}
+
+/* recognise user attributes packet */
+static int
+recog_userattr(pgpv_t *pgp, pgpv_signed_userattr_t *userattr)
+{
+ pgpv_signature_t signature;
+
+ memset(userattr, 0x0, sizeof(*userattr));
+ if (!pkt_is(pgp, USER_ATTRIBUTE_PKT)) {
+ printf("recog_userattr: not %d\n", USER_ATTRIBUTE_PKT);
+ return 0;
+ }
+ userattr->userattr = ARRAY_ELEMENT(pgp->pkts, pgp->pkt).u.userattr;
+ pgp->pkt += 1;
+ while (pkt_is(pgp, SIGNATURE_PKT)) {
+ if (!recog_signature(pgp, &signature)) {
+ printf("recog_userattr: can't recognise signature/trust\n");
+ return 0;
+ }
+ ARRAY_APPEND(userattr->sigs, signature);
+ if (signature.revoked) {
+ userattr->revoked = signature.revoked;
+ }
+ }
+ return 1;
+}
+
+/* recognise a sub key */
+static int
+recog_subkey(pgpv_t *pgp, pgpv_signed_subkey_t *subkey)
+{
+ pgpv_signature_t signature;
+ pgpv_pkt_t *pkt;
+
+ pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
+ memset(subkey, 0x0, sizeof(*subkey));
+ read_pubkey(&subkey->subkey, pkt->s.data, pkt->s.size, 0);
+ pgp->pkt += 1;
+ if (pkt_sigtype_is(pgp, SIGTYPE_KEY_REVOCATION) ||
+ pkt_sigtype_is(pgp, SIGTYPE_SUBKEY_REVOCATION) ||
+ pkt_sigtype_is(pgp, SIGTYPE_CERT_REVOCATION)) {
+ recog_signature(pgp, &signature);
+ subkey->revoc_self_sig = signature;
+ }
+ do {
+ if (!pkt_is(pgp, SIGNATURE_PKT)) {
+ printf("recog_subkey: not signature packet at %zu\n", pgp->pkt);
+ return 0;
+ }
+ if (!recog_signature(pgp, &signature)) {
+ printf("recog_subkey: bad signature/trust at %zu\n", pgp->pkt);
+ return 0;
+ }
+ ARRAY_APPEND(subkey->sigs, signature);
+ if (signature.keyexpiry) {
+ /* XXX - check it's a good key expiry */
+ subkey->subkey.expiry = signature.keyexpiry;
+ }
+ } while (pkt_is(pgp, SIGNATURE_PKT));
+ return 1;
+}
+
+/* use a sparse map for the text strings here to save space */
+static const char *keyalgs[] = {
+ "[Unknown]",
+ "RSA (Encrypt or Sign)",
+ "RSA (Encrypt Only)",
+ "RSA (Sign Only)",
+ "Elgamal (Encrypt Only)",
+ "DSA",
+ "Elliptic Curve",
+ "ECDSA",
+ "Elgamal (Encrypt or Sign)"
+};
+
+#define MAX_KEYALG 21
+
+static const char *keyalgmap = "\0\01\02\03\0\0\0\0\0\0\0\0\0\0\0\0\04\05\06\07\010\011";
+
+/* return human readable name for key algorithm */
+static const char *
+fmtkeyalg(uint8_t keyalg)
+{
+ return keyalgs[(uint8_t)keyalgmap[(keyalg >= MAX_KEYALG) ? 0 : keyalg]];
+}
+
+/* return the number of bits in the public key */
+static unsigned
+numkeybits(const pgpv_pubkey_t *pubkey)
+{
+ switch(pubkey->keyalg) {
+ case PUBKEY_RSA_ENCRYPT_OR_SIGN:
+ case PUBKEY_RSA_ENCRYPT:
+ case PUBKEY_RSA_SIGN:
+ return pubkey->bn[RSA_N].bits;
+ case PUBKEY_DSA:
+ case PUBKEY_ECDSA:
+ return BITS_TO_BYTES(pubkey->bn[DSA_Q].bits) * 64;
+ case PUBKEY_ELGAMAL_ENCRYPT:
+ case PUBKEY_ELGAMAL_ENCRYPT_OR_SIGN:
+ return pubkey->bn[ELGAMAL_P].bits;
+ default:
+ return 0;
+ }
+}
+
+/* print a public key */
+static size_t
+fmt_pubkey(char *s, size_t size, pgpv_pubkey_t *pubkey, const char *leader)
+{
+ size_t cc;
+
+ cc = snprintf(s, size, "%s %u/%s ", leader, numkeybits(pubkey), fmtkeyalg(pubkey->keyalg));
+ cc += fmt_binary(&s[cc], size - cc, pubkey->keyid, PGPV_KEYID_LEN);
+ cc += fmt_time(&s[cc], size - cc, " ", pubkey->birth, "", 0);
+ if (pubkey->expiry) {
+ cc += fmt_time(&s[cc], size - cc, " [Expiry ", pubkey->birth + pubkey->expiry, "]", 0);
+ }
+ cc += snprintf(&s[cc], size - cc, "\n");
+ cc += fmt_fingerprint(&s[cc], size - cc, &pubkey->fingerprint, "fingerprint: ");
+ return cc;
+}
+
+/* we add 1 to revocation value to denote compromised */
+#define COMPROMISED (0x02 + 1)
+
+/* format a userid - used to order the userids when formatting */
+static size_t
+fmt_userid(char *s, size_t size, pgpv_primarykey_t *primary, uint8_t u)
+{
+ pgpv_signed_userid_t *userid;
+
+ userid = &ARRAY_ELEMENT(primary->signed_userids, u);
+ return snprintf(s, size, "uid %.*s%s\n",
+ (int)userid->userid.size, userid->userid.data,
+ (userid->revoked == COMPROMISED) ? " [COMPROMISED AND REVOKED]" :
+ (userid->revoked) ? " [REVOKED]" : "");
+}
+
+/* print a primary key, per RFC 4880 */
+static size_t
+fmt_primary(char *s, size_t size, pgpv_primarykey_t *primary)
+{
+ unsigned i;
+ 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);
+ }
+ }
+ 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;
+}
+
+
+/* check the padding on the signature */
+static int
+rsa_padding_check_none(uint8_t *to, int tlen, const uint8_t *from, int flen, int num)
+{
+ USE_ARG(num);
+ if (flen > tlen) {
+ printf("from length larger than to length\n");
+ return -1;
+ }
+ (void) memset(to, 0x0, tlen - flen);
+ (void) memcpy(to + tlen - flen, from, flen);
+ return tlen;
+}
+
+#define RSA_MAX_MODULUS_BITS 16384
+#define RSA_SMALL_MODULUS_BITS 3072
+#define RSA_MAX_PUBEXP_BITS 64 /* exponent limit enforced for "large" modulus only */
+
+/* check against the exponent/moudulo operation */
+static int
+lowlevel_rsa_public_check(const uint8_t *encbuf, int enclen, uint8_t *dec, const rsa_pubkey_t *rsa)
+{
+ uint8_t *decbuf;
+ BIGNUM *decbn;
+ BIGNUM *encbn;
+ int decbytes;
+ int nbytes;
+ int r;
+
+ nbytes = 0;
+ r = -1;
+ decbuf = NULL;
+ decbn = encbn = NULL;
+ if (BN_num_bits(rsa->n) > RSA_MAX_MODULUS_BITS) {
+ printf("rsa r modulus too large\n");
+ goto err;
+ }
+ if (BN_cmp(rsa->n, rsa->e) <= 0) {
+ printf("rsa r bad n value\n");
+ goto err;
+ }
+ if (BN_num_bits(rsa->n) > RSA_SMALL_MODULUS_BITS &&
+ BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS) {
+ printf("rsa r bad exponent limit\n");
+ goto err;
+ }
+ if ((encbn = BN_new()) == NULL ||
+ (decbn = BN_new()) == NULL ||
+ (decbuf = calloc(1, nbytes = BN_num_bytes(rsa->n))) == NULL) {
+ printf("allocation failure\n");
+ goto err;
+ }
+ if (enclen > nbytes) {
+ printf("rsa r > mod len\n");
+ goto err;
+ }
+ if (BN_bin2bn(encbuf, enclen, encbn) == NULL) {
+ printf("null encrypted BN\n");
+ goto err;
+ }
+ if (BN_cmp(encbn, rsa->n) >= 0) {
+ printf("rsa r data too large for modulus\n");
+ goto err;
+ }
+ if (BN_mod_exp(decbn, encbn, rsa->e, rsa->n, NULL) < 0) {
+ printf("BN_mod_exp < 0\n");
+ goto err;
+ }
+ decbytes = BN_num_bytes(decbn);
+ (void) BN_bn2bin(decbn, decbuf);
+ if ((r = rsa_padding_check_none(dec, nbytes, decbuf, decbytes, 0)) < 0) {
+ printf("rsa r padding check failed\n");
+ }
+err:
+ BN_free(encbn);
+ BN_free(decbn);
+ if (decbuf != NULL) {
+ (void) memset(decbuf, 0x0, nbytes);
+ free(decbuf);
+ }
+ return r;
+}
+
+/* verify */
+static int
+rsa_public_decrypt(int enclen, const unsigned char *enc, unsigned char *dec, RSA *rsa, int padding)
+{
+ rsa_pubkey_t pub;
+ int ret;
+
+ if (enc == NULL || dec == NULL || rsa == NULL) {
+ return 0;
+ }
+ USE_ARG(padding);
+ (void) memset(&pub, 0x0, sizeof(pub));
+ pub.n = BN_dup(rsa->n);
+ pub.e = BN_dup(rsa->e);
+ ret = lowlevel_rsa_public_check(enc, enclen, dec, &pub);
+ BN_free(pub.n);
+ BN_free(pub.e);
+ return ret;
+}
+
+#define SUBKEY_LEN(x) (80 + 80)
+#define SIG_LEN 80
+#define UID_LEN 80
+
+/* return worst case number of bytes needed to format a primary key */
+static size_t
+estimate_primarykey_size(pgpv_primarykey_t *primary)
+{
+ size_t cc;
+
+ cc = SUBKEY_LEN("signature") +
+ (ARRAY_COUNT(primary->signed_userids) * UID_LEN) +
+ (ARRAY_COUNT(primary->signed_subkeys) * SUBKEY_LEN("encrypt uids"));
+ return cc;
+}
+
+/* use public decrypt to verify a signature */
+static int
+pgpv_rsa_public_decrypt(uint8_t *out, const uint8_t *in, size_t length, const pgpv_pubkey_t *pubkey)
+{
+ RSA *orsa;
+ int n;
+
+ if ((orsa = calloc(1, sizeof(*orsa))) == NULL) {
+ return 0;
+ }
+ orsa->n = pubkey->bn[RSA_N].bn;
+ orsa->e = pubkey->bn[RSA_E].bn;
+ n = rsa_public_decrypt((int)length, in, out, orsa, RSA_NO_PADDING);
+ orsa->n = orsa->e = NULL;
+ free(orsa);
+ return n;
+}
+
+/* verify rsa signature */
+static int
+rsa_verify(uint8_t *calculated, unsigned calclen, uint8_t hashalg, pgpv_bignum_t *bn, pgpv_pubkey_t *pubkey)
+{
+ unsigned prefixlen;
+ unsigned decryptc;
+ unsigned i;
+ uint8_t decrypted[8192];
+ uint8_t sigbn[8192];
+ uint8_t prefix[64];
+ size_t keysize;
+
+ keysize = BITS_TO_BYTES(pubkey->bn[RSA_N].bits);
+ BN_bn2bin(bn[RSA_SIG].bn, sigbn);
+ decryptc = pgpv_rsa_public_decrypt(decrypted, sigbn, BITS_TO_BYTES(bn[RSA_SIG].bits), pubkey);
+ if (decryptc != keysize || (decrypted[0] != 0 || decrypted[1] != 1)) {
+ return 0;
+ }
+ if ((prefixlen = digest_get_prefix((unsigned)hashalg, prefix, sizeof(prefix))) == 0) {
+ printf("rsa_verify: unknown hash algorithm: %d\n", hashalg);
+ return 0;
+ }
+ for (i = 2 ; i < keysize - prefixlen - calclen - 1 ; i++) {
+ if (decrypted[i] != 0xff) {
+ return 0;
+ }
+ }
+ if (decrypted[i++] != 0x0) {
+ return 0;
+ }
+ if (memcmp(&decrypted[i], prefix, prefixlen) != 0) {
+ printf("rsa_verify: wrong hash algorithm\n");
+ return 0;
+ }
+ return memcmp(&decrypted[i + prefixlen], calculated, calclen) == 0;
+}
+
+/* return 1 if bn <= 0 */
+static int
+bignum_is_bad(BIGNUM *bn)
+{
+ return BN_is_zero(bn) || BN_is_negative(bn);
+}
+
+#define BAD_BIGNUM(s, k) \
+ (bignum_is_bad((s)->bn) || BN_cmp((s)->bn, (k)->bn) >= 0)
+
+#ifndef DSA_MAX_MODULUS_BITS
+#define DSA_MAX_MODULUS_BITS 10000
+#endif
+
+/* verify DSA signature */
+static int
+verify_dsa_sig(uint8_t *calculated, unsigned calclen, pgpv_bignum_t *sig, pgpv_pubkey_t *pubkey)
+{
+ unsigned qbits;
+ uint8_t calcnum[128];
+ uint8_t signum[128];
+ BIGNUM *M;
+ BIGNUM *W;
+ BIGNUM *t1;
+ int ret;
+
+ if (pubkey[DSA_P].bn == NULL || pubkey[DSA_Q].bn == NULL || pubkey[DSA_G].bn == NULL) {
+ return 0;
+ }
+ M = W = t1 = NULL;
+ qbits = pubkey->bn[DSA_Q].bits;
+ switch(qbits) {
+ case 160:
+ case 224:
+ case 256:
+ break;
+ default:
+ printf("dsa: bad # of Q bits\n");
+ return 0;
+ }
+ if (pubkey->bn[DSA_P].bits > DSA_MAX_MODULUS_BITS) {
+ printf("dsa: p too large\n");
+ return 0;
+ }
+ if (calclen > SHA256_DIGEST_LENGTH) {
+ printf("dsa: digest too long\n");
+ return 0;
+ }
+ ret = 0;
+ if ((M = BN_new()) == NULL || (W = BN_new()) == NULL || (t1 = BN_new()) == NULL ||
+ BAD_BIGNUM(&sig[DSA_R], &pubkey->bn[DSA_Q]) ||
+ BAD_BIGNUM(&sig[DSA_S], &pubkey->bn[DSA_Q]) ||
+ BN_mod_inverse(W, sig[DSA_S].bn, pubkey->bn[DSA_Q].bn, NULL) == NULL) {
+ goto done;
+ }
+ if (calclen > qbits / 8) {
+ calclen = qbits / 8;
+ }
+ if (BN_bin2bn(calculated, (int)calclen, M) == NULL ||
+ !BN_mod_mul(M, M, W, pubkey->bn[DSA_Q].bn, NULL) ||
+ !BN_mod_mul(W, sig[DSA_R].bn, W, pubkey->bn[DSA_Q].bn, NULL) ||
+ !BN_mod_exp(t1, pubkey->bn[DSA_G].bn, M, pubkey->bn[DSA_P].bn, NULL) ||
+ !BN_mod_exp(W, pubkey->bn[DSA_Y].bn, W, pubkey->bn[DSA_P].bn, NULL) ||
+ !BN_mod_mul(t1, t1, W, pubkey->bn[DSA_P].bn, NULL) ||
+ !BN_div(NULL, t1, t1, pubkey->bn[DSA_Q].bn, NULL)) {
+ goto done;
+ }
+ /* only compare the first q bits */
+ BN_bn2bin(t1, calcnum);
+ BN_bn2bin(sig[DSA_R].bn, signum);
+ ret = memcmp(calcnum, signum, BITS_TO_BYTES(qbits)) == 0;
+done:
+ if (M) {
+ BN_free(M);
+ }
+ if (W) {
+ BN_free(W);
+ }
+ if (t1) {
+ BN_free(t1);
+ }
+ return ret;
+}
+
+#define TIME_SNPRINTF(_cc, _buf, _size, _fmt, _val) do { \
+ time_t _t; \
+ char *_s; \
+ \
+ _t = _val; \
+ _s = ctime(&_t); \
+ _cc += snprintf(_buf, _size, _fmt, _s); \
+} while(/*CONSTCOND*/0)
+
+/* check dates on signature and key are valid */
+static size_t
+valid_dates(pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, char *buf, size_t size)
+{
+ time_t now;
+ time_t t;
+ size_t cc;
+
+ cc = 0;
+ if (signature->birth < pubkey->birth) {
+ TIME_SNPRINTF(cc, buf, size, "Signature time (%.24s) was before pubkey creation ", signature->birth);
+ TIME_SNPRINTF(cc, &buf[cc], size - cc, "(%s)\n", pubkey->birth);
+ return cc;
+ }
+ now = time(NULL);
+ if (signature->expiry != 0) {
+ if ((t = signature->birth + signature->expiry) < now) {
+ TIME_SNPRINTF(cc, buf, size, "Signature expired on %.24s\n", t);
+ return cc;
+ }
+ }
+ if (now < signature->birth) {
+ TIME_SNPRINTF(cc, buf, size, "Signature not valid before %.24s\n", signature->birth);
+ return cc;
+ }
+ return 0;
+}
+
+/* check if the signing key has expired */
+static int
+key_expired(pgpv_pubkey_t *pubkey, char *buf, size_t size)
+{
+ time_t now;
+ time_t t;
+ size_t cc;
+
+ now = time(NULL);
+ cc = 0;
+ if (pubkey->expiry != 0) {
+ if ((t = pubkey->birth + pubkey->expiry) < now) {
+ TIME_SNPRINTF(cc, buf, size, "Pubkey expired on %.24s\n", t);
+ return (int)cc;
+ }
+ }
+ if (now < pubkey->birth) {
+ TIME_SNPRINTF(cc, buf, size, "Pubkey not valid before %.24s\n", pubkey->birth);
+ return (int)cc;
+ }
+ return 0;
+}
+
+/* find the leading onepass packet */
+static size_t
+find_onepass(pgpv_cursor_t *cursor, size_t datastart)
+{
+ size_t pkt;
+
+ for (pkt = datastart ; pkt < ARRAY_COUNT(cursor->pgp->pkts) ; pkt++) {
+ if (ARRAY_ELEMENT(cursor->pgp->pkts, pkt).tag == ONEPASS_SIGNATURE_PKT) {
+ return pkt + 1;
+ }
+ }
+ snprintf(cursor->why, sizeof(cursor->why), "No signature to verify");
+ return 0;
+}
+
+static const char *armor_begins[] = {
+ "-----BEGIN PGP SIGNED MESSAGE-----\n",
+ "-----BEGIN PGP MESSAGE-----\n",
+ NULL
+};
+
+/* return non-zero if the buf introduces an armored message */
+static int
+is_armored(const char *buf, size_t size)
+{
+ const char **arm;
+ const char *nl;
+ size_t n;
+
+ if ((nl = memchr(buf, '\n', size)) == NULL) {
+ return 0;
+ }
+ n = (size_t)(nl - buf);
+ for (arm = armor_begins ; *arm ; arm++) {
+ if (strncmp(buf, *arm, n) == 0) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#define SIGSTART "-----BEGIN PGP SIGNATURE-----\n"
+#define SIGEND "-----END PGP SIGNATURE-----\n"
+
+/* for ascii armor, we don't get a onepass packet - make one */
+static const char *cons_onepass = "\304\015\003\0\0\0\0\377\377\377\377\377\377\377\377\1";
+
+/* read ascii armor */
+static int
+read_ascii_armor(pgpv_cursor_t *cursor, pgpv_mem_t *mem, const char *filename)
+{
+ pgpv_onepass_t *onepass;
+ pgpv_sigpkt_t *sigpkt;
+ pgpv_pkt_t litdata;
+ uint8_t binsig[8192];
+ uint8_t *datastart;
+ uint8_t *sigend;
+ uint8_t *p;
+ size_t binsigsize;
+
+ /* cons up litdata pkt */
+ memset(&litdata, 0x0, sizeof(litdata));
+ litdata.u.litdata.mem = ARRAY_COUNT(cursor->pgp->areas) - 1;
+ p = mem->mem;
+ /* jump over signed message line */
+ if ((p = memmem(mem->mem, mem->size, "\n\n", 2)) == NULL) {
+ snprintf(cursor->why, sizeof(cursor->why), "malformed armor at offset 0");
+ return 0;
+ }
+ p += 2;
+ litdata.tag = LITDATA_PKT;
+ litdata.s.data = p;
+ litdata.u.litdata.offset = (size_t)(p - mem->mem);
+ litdata.u.litdata.filename = (uint8_t *)strdup(filename);
+ if ((p = memmem(datastart = p, mem->size - litdata.offset, SIGSTART, strlen(SIGSTART))) == NULL) {
+ snprintf(cursor->why, sizeof(cursor->why),
+ "malformed armor - no sig - at %zu", (size_t)(p - mem->mem));
+ return 0;
+ }
+ litdata.u.litdata.len = litdata.s.size = (size_t)(p - datastart);
+ p += strlen(SIGSTART);
+ if ((p = memmem(p, mem->size, "\n\n", 2)) == NULL) {
+ snprintf(cursor->why, sizeof(cursor->why),
+ "malformed armed signature at %zu", (size_t)(p - mem->mem));
+ return 0;
+ }
+ p += 2;
+ sigend = memmem(p, mem->size, SIGEND, strlen(SIGEND));
+ binsigsize = b64decode((char *)p, (size_t)(sigend - p), binsig, sizeof(binsig));
+
+ read_binary_memory(cursor->pgp, "signature", cons_onepass, 15);
+ ARRAY_APPEND(cursor->pgp->pkts, litdata);
+ read_binary_memory(cursor->pgp, "signature", binsig, binsigsize - 3);
+ /* XXX - hardwired - 3 is format and length */
+
+ /* fix up packets in the packet array now we have them there */
+ onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, ARRAY_COUNT(cursor->pgp->pkts) - 1 - 2).u.onepass;
+ sigpkt = &ARRAY_LAST(cursor->pgp->pkts).u.sigpkt;
+ memcpy(onepass->keyid, sigpkt->sig.signer, sizeof(onepass->keyid));
+ onepass->hashalg = sigpkt->sig.hashalg;
+ onepass->keyalg = sigpkt->sig.keyalg;
+ return 1;
+}
+
+/* read ascii armor from a file */
+static int
+read_ascii_armor_file(pgpv_cursor_t *cursor, const char *filename)
+{
+ /* cons up litdata pkt */
+ read_file(cursor->pgp, filename);
+ return read_ascii_armor(cursor, &ARRAY_LAST(cursor->pgp->areas), filename);
+}
+
+/* read ascii armor from memory */
+static int
+read_ascii_armor_memory(pgpv_cursor_t *cursor, const void *p, size_t size)
+{
+ pgpv_mem_t *mem;
+
+ /* cons up litdata pkt */
+ ARRAY_EXPAND(cursor->pgp->areas);
+ ARRAY_COUNT(cursor->pgp->areas) += 1;
+ mem = &ARRAY_LAST(cursor->pgp->areas);
+ memset(mem, 0x0, sizeof(*mem));
+ mem->size = size;
+ mem->mem = __UNCONST(p);
+ mem->dealloc = 0;
+ return read_ascii_armor(cursor, mem, "[stdin]");
+}
+
+/* set up the data to verify */
+static int
+setup_data(pgpv_cursor_t *cursor, pgpv_t *pgp, const void *p, ssize_t size)
+{
+ FILE *fp;
+ char buf[BUFSIZ];
+
+ if (cursor == NULL || pgp == NULL || p == NULL) {
+ return 0;
+ }
+ memset(cursor, 0x0, sizeof(*cursor));
+ ARRAY_APPEND(pgp->datastarts, pgp->pkt);
+ cursor->pgp = pgp;
+ if (size < 0) {
+ /* we have a file name in p */
+ if ((fp = fopen(p, "r")) == NULL) {
+ snprintf(cursor->why, sizeof(cursor->why), "No such file '%s'", (const char *)p);
+ return 0;
+ }
+ if (fgets(buf, (int)sizeof(buf), fp) == NULL) {
+ fclose(fp);
+ snprintf(cursor->why, sizeof(cursor->why), "can't read file '%s'", (const char *)p);
+ return 0;
+ }
+ if (is_armored(buf, sizeof(buf))) {
+ read_ascii_armor_file(cursor, p);
+ } else {
+ read_binary_file(pgp, "signature", "%s", p);
+ }
+ fclose(fp);
+ } else {
+ if (is_armored(p, (size_t)size)) {
+ read_ascii_armor_memory(cursor, p, (size_t)size);
+ } else {
+ read_binary_memory(pgp, "signature", p, (size_t)size);
+ }
+ }
+ return 1;
+}
+
+/* get the data and size from litdata packet */
+static uint8_t *
+get_literal_data(pgpv_cursor_t *cursor, pgpv_litdata_t *litdata, size_t *size)
+{
+ pgpv_mem_t *mem;
+
+ if (litdata->s.data == NULL && litdata->s.size == 0) {
+ mem = &ARRAY_ELEMENT(cursor->pgp->areas, litdata->mem);
+ *size = litdata->len;
+ return &mem->mem[litdata->offset];
+ }
+ *size = litdata->s.size;
+ return litdata->s.data;
+}
+
+/*
+RFC 4880 describes the structure of v4 keys as:
+
+ Primary-Key
+ [Revocation Self Signature]
+ [Direct Key Signature...]
+ User ID [Signature ...]
+ [User ID [Signature ...] ...]
+ [User Attribute [Signature ...] ...]
+ [[Subkey [Binding-Signature-Revocation]
+ Primary-Key-Binding-Signature] ...]
+
+and that's implemented below as a recursive descent parser.
+It has had to be modified, though: see the comment
+
+ some keys out there have user ids where they shouldn't
+
+to look like:
+
+ Primary-Key
+ [Revocation Self Signature]
+ [Direct Key Signature...]
+ [User ID [Signature ...]
+ [User ID [Signature ...] ...]
+ [User Attribute [Signature ...] ...]
+ [Subkey [Binding-Signature-Revocation]
+ Primary-Key-Binding-Signature] ...]
+
+to accommodate keyrings set up by gpg
+*/
+
+/* recognise a primary key */
+static int
+recog_primary_key(pgpv_t *pgp, pgpv_primarykey_t *primary)
+{
+ pgpv_signed_userattr_t userattr;
+ pgpv_signed_userid_t userid;
+ pgpv_signed_subkey_t subkey;
+ pgpv_signature_t signature;
+ pgpv_pkt_t *pkt;
+
+ pkt = &ARRAY_ELEMENT(pgp->pkts, pgp->pkt);
+ memset(primary, 0x0, sizeof(*primary));
+ read_pubkey(&primary->primary, pkt->s.data, pkt->s.size, 0);
+ pgp->pkt += 1;
+ if (pkt_sigtype_is(pgp, SIGTYPE_KEY_REVOCATION)) {
+ if (!recog_signature(pgp, &primary->revoc_self_sig)) {
+ printf("recog_primary_key: no signature/trust at PGPV_SIGTYPE_KEY_REVOCATION\n");
+ return 0;
+ }
+ }
+ while (pkt_sigtype_is(pgp, SIGTYPE_DIRECT_KEY)) {
+ if (!recog_signature(pgp, &signature)) {
+ printf("recog_primary_key: no signature/trust at PGPV_SIGTYPE_DIRECT_KEY\n");
+ return 0;
+ }
+ if (signature.keyexpiry) {
+ /* XXX - check it's a good key expiry */
+ primary->primary.expiry = signature.keyexpiry;
+ }
+ ARRAY_APPEND(primary->direct_sigs, signature);
+ }
+ /* some keys out there have user ids where they shouldn't */
+ do {
+ if (!recog_userid(pgp, &userid)) {
+ printf("recog_primary_key: not userid\n");
+ return 0;
+ }
+ ARRAY_APPEND(primary->signed_userids, userid);
+ if (userid.primary_userid) {
+ primary->primary_userid = ARRAY_COUNT(primary->signed_userids) - 1;
+ }
+ while (pkt_is(pgp, USERID_PKT)) {
+ if (!recog_userid(pgp, &userid)) {
+ printf("recog_primary_key: not signed secondary userid\n");
+ return 0;
+ }
+ ARRAY_APPEND(primary->signed_userids, userid);
+ if (userid.primary_userid) {
+ primary->primary_userid = ARRAY_COUNT(primary->signed_userids) - 1;
+ }
+ }
+ while (pkt_is(pgp, USER_ATTRIBUTE_PKT)) {
+ if (!recog_userattr(pgp, &userattr)) {
+ printf("recog_primary_key: not signed user attribute\n");
+ return 0;
+ }
+ ARRAY_APPEND(primary->signed_userattrs, userattr);
+ }
+ while (pkt_is(pgp, PUB_SUBKEY_PKT)) {
+ if (!recog_subkey(pgp, &subkey)) {
+ printf("recog_primary_key: not signed public subkey\n");
+ return 0;
+ }
+ pgpv_calc_keyid(&subkey.subkey);
+ ARRAY_APPEND(primary->signed_subkeys, subkey);
+ }
+ } while (pgp->pkt < ARRAY_COUNT(pgp->pkts) && pkt_is(pgp, USERID_PKT));
+ primary->fmtsize = estimate_primarykey_size(primary);
+ return 1;
+}
+
+/* parse all of the packets for a given operation */
+static int
+read_all_packets(pgpv_t *pgp, pgpv_mem_t *mem, const char *op)
+{
+ pgpv_primarykey_t primary;
+
+ if (op == NULL) {
+ return 0;
+ }
+ if (strcmp(pgp->op = op, "pubring") == 0) {
+ mem->allowed = PUBRING_ALLOWED;
+ /* pubrings have thousands of small packets */
+ ARRAY_EXPAND_SIZED(pgp->pkts, 0, 5000);
+ } else if (strcmp(op, "signature") == 0) {
+ mem->allowed = SIGNATURE_ALLOWED;
+ } else {
+ mem->allowed = "";
+ }
+ for (mem->cc = 0; mem->cc < mem->size ; ) {
+ if (!read_pkt(pgp, mem)) {
+ return 0;
+ }
+ }
+ 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);
+ ARRAY_APPEND(pgp->primaries, primary);
+ }
+ if (pgp->pkt < ARRAY_COUNT(pgp->pkts)) {
+ printf("short pubring recognition???\n");
+ }
+ }
+ pgp->pkt = ARRAY_COUNT(pgp->pkts);
+ return 1;
+}
+
+/* create a filename, read it, and then parse according to "op" */
+static int
+read_binary_file(pgpv_t *pgp, const char *op, const char *fmt, ...)
+{
+ va_list args;
+ char buf[1024];
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+ if (!read_file(pgp, buf)) {
+ return 0;
+ }
+ return read_all_packets(pgp, &ARRAY_LAST(pgp->areas), op);
+}
+
+/* parse memory according to "op" */
+static int
+read_binary_memory(pgpv_t *pgp, const char *op, const void *memory, size_t size)
+{
+ pgpv_mem_t *mem;
+
+ ARRAY_EXPAND(pgp->areas);
+ ARRAY_COUNT(pgp->areas) += 1;
+ mem = &ARRAY_LAST(pgp->areas);
+ memset(mem, 0x0, sizeof(*mem));
+ mem->size = size;
+ mem->mem = __UNCONST(memory);
+ mem->dealloc = 0;
+ return read_all_packets(pgp, mem, op);
+}
+
+/* fixup the detached signature packets */
+static int
+fixup_detached(pgpv_cursor_t *cursor, const char *f)
+{
+ pgpv_onepass_t *onepass;
+ const char *dot;
+ pgpv_pkt_t sigpkt;
+ pgpv_pkt_t litdata;
+ pgpv_mem_t *mem;
+ size_t el;
+ char original[MAXPATHLEN];
+
+ /* cons up litdata pkt */
+ if ((dot = strrchr(f, '.')) == NULL || strcasecmp(dot, ".sig") != 0) {
+ printf("weird filename '%s'\n", f);
+ return 0;
+ }
+ /* hold sigpkt in a temp var while we insert onepass and litdata */
+ el = ARRAY_COUNT(cursor->pgp->pkts) - 1;
+ sigpkt = ARRAY_ELEMENT(cursor->pgp->pkts, el);
+ ARRAY_DELETE(cursor->pgp->pkts, el);
+ ARRAY_EXPAND(cursor->pgp->pkts);
+ /* get onepass packet, append to packets */
+ read_binary_memory(cursor->pgp, "signature", cons_onepass, 15);
+ onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, el).u.onepass;
+ /* read the original file into litdata */
+ snprintf(original, sizeof(original), "%.*s", (int)(dot - f), f);
+ if (!read_file(cursor->pgp, original)) {
+ printf("can't read file '%s'\n", original);
+ return 0;
+ }
+ memset(&litdata, 0x0, sizeof(litdata));
+ mem = &ARRAY_LAST(cursor->pgp->areas);
+ litdata.tag = LITDATA_PKT;
+ litdata.s.data = mem->mem;
+ litdata.u.litdata.format = LITDATA_BINARY;
+ litdata.u.litdata.offset = 0;
+ litdata.u.litdata.filename = (uint8_t *)strdup(original);
+ litdata.u.litdata.mem = ARRAY_COUNT(cursor->pgp->areas) - 1;
+ litdata.u.litdata.len = litdata.s.size = mem->size;
+ ARRAY_APPEND(cursor->pgp->pkts, litdata);
+ ARRAY_APPEND(cursor->pgp->pkts, sigpkt);
+ memcpy(onepass->keyid, sigpkt.u.sigpkt.sig.signer, sizeof(onepass->keyid));
+ onepass->hashalg = sigpkt.u.sigpkt.sig.hashalg;
+ onepass->keyalg = sigpkt.u.sigpkt.sig.keyalg;
+ return 1;
+}
+
+/* match the calculated signature against the oen in the signature packet */
+static int
+match_sig(pgpv_cursor_t *cursor, pgpv_signature_t *signature, pgpv_pubkey_t *pubkey, uint8_t *data, size_t size)
+{
+ unsigned calclen;
+ uint8_t calculated[64];
+ int match;
+
+ calclen = pgpv_digest_memory(calculated, sizeof(calculated),
+ data, size,
+ get_ref(&signature->hashstart), signature->hashlen,
+ (signature->type == SIGTYPE_TEXT) ? 't' : 'b');
+ if (ALG_IS_RSA(signature->keyalg)) {
+ match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
+ } else if (ALG_IS_DSA(signature->keyalg)) {
+ match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
+ } else {
+ snprintf(cursor->why, sizeof(cursor->why), "Signature type %u not recognised", signature->keyalg);
+ return 0;
+ }
+ if (!match && signature->type == SIGTYPE_TEXT) {
+ /* second try for cleartext data, ignoring trailing whitespace */
+ calclen = pgpv_digest_memory(calculated, sizeof(calculated),
+ data, size,
+ get_ref(&signature->hashstart), signature->hashlen, 'w');
+ if (ALG_IS_RSA(signature->keyalg)) {
+ match = rsa_verify(calculated, calclen, signature->hashalg, signature->bn, pubkey);
+ } else if (ALG_IS_DSA(signature->keyalg)) {
+ match = verify_dsa_sig(calculated, calclen, signature->bn, pubkey);
+ }
+ }
+ if (!match) {
+ snprintf(cursor->why, sizeof(cursor->why), "Signature on data did not match");
+ return 0;
+ }
+ if (valid_dates(signature, pubkey, cursor->why, sizeof(cursor->why)) > 0) {
+ return 0;
+ }
+ if (key_expired(pubkey, cursor->why, sizeof(cursor->why))) {
+ return 0;
+ }
+ if (signature->revoked) {
+ snprintf(cursor->why, sizeof(cursor->why), "Signature was revoked");
+ return 0;
+ }
+ return 1;
+}
+
+/* check return value from getenv */
+static const char *
+nonnull_getenv(const char *key)
+{
+ char *value;
+
+ return ((value = getenv(key)) == NULL) ? "" : value;
+}
+
+/************************************************************************/
+/* start of exported functions */
+/************************************************************************/
+
+/* close all stuff */
+int
+pgpv_close(pgpv_t *pgp)
+{
+ unsigned i;
+
+ if (pgp == NULL) {
+ return 0;
+ }
+ for (i = 0 ; i < ARRAY_COUNT(pgp->areas) ; i++) {
+ if (ARRAY_ELEMENT(pgp->areas, i).size > 0) {
+ closemem(&ARRAY_ELEMENT(pgp->areas, i));
+ }
+ }
+ return 1;
+}
+
+/* return the formatted entry for the primary key desired */
+size_t
+pgpv_get_entry(pgpv_t *pgp, unsigned ent, char **ret)
+{
+ size_t cc;
+
+ if (ret == NULL || pgp == NULL || ent >= ARRAY_COUNT(pgp->primaries)) {
+ return 0;
+ }
+ *ret = NULL;
+ cc = ARRAY_ELEMENT(pgp->primaries, ent).fmtsize;
+ if ((*ret = calloc(1, cc)) == NULL) {
+ return 0;
+ }
+ return fmt_primary(*ret, cc, &ARRAY_ELEMENT(pgp->primaries, ent));
+}
+
+/* find key id */
+int
+pgpv_find_keyid(pgpv_t *pgp, const char *strkeyid, uint8_t *keyid)
+{
+ unsigned i;
+ uint8_t binkeyid[PGPV_KEYID_LEN];
+ size_t off;
+ size_t cmp;
+
+ if (strkeyid == NULL && keyid == NULL) {
+ return 0;
+ }
+ if (strkeyid) {
+ str_to_keyid(strkeyid, binkeyid);
+ cmp = strlen(strkeyid) / 2;
+ } else {
+ memcpy(binkeyid, keyid, sizeof(binkeyid));
+ cmp = PGPV_KEYID_LEN;
+ }
+ off = PGPV_KEYID_LEN - cmp;
+ for (i = 0 ; i < ARRAY_COUNT(pgp->primaries) ; i++) {
+ if (memcmp(&ARRAY_ELEMENT(pgp->primaries, i).primary.keyid[off], &binkeyid[off], cmp) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* verify the signed packets we have */
+size_t
+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 j;
+
+ if (cursor == NULL || pgp == NULL || p == NULL) {
+ return 0;
+ }
+ if (!setup_data(cursor, pgp, p, size)) {
+ snprintf(cursor->why, sizeof(cursor->why), "No input data");
+ return 0;
+ }
+ if (ARRAY_COUNT(cursor->pgp->pkts) == ARRAY_LAST(cursor->pgp->datastarts) + 1) {
+ /* got detached signature here */
+ if (!fixup_detached(cursor, p)) {
+ snprintf(cursor->why, sizeof(cursor->why), "Can't read signed file '%s'", (const char *)p);
+ return 0;
+ }
+ }
+ if ((pkt = find_onepass(cursor, ARRAY_LAST(cursor->pgp->datastarts))) == 0) {
+ snprintf(cursor->why, sizeof(cursor->why), "No signature found");
+ return 0;
+ }
+ pkt -= 1;
+ onepass = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.onepass;
+ litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 1).u.litdata;
+ signature = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt + 2).u.sigpkt.sig;
+ /* sanity check values in signature and onepass agree */
+ if (signature->birth == 0) {
+ fmt_time(cursor->why, sizeof(cursor->why), "Signature creation time [",
+ signature->birth, "] out of range", 0);
+ return 0;
+ }
+ if (memcmp(onepass->keyid, signature->signer, PGPV_KEYID_LEN) != 0) {
+ fmt_binary(strkeyid, sizeof(strkeyid), onepass->keyid, (unsigned)sizeof(onepass->keyid));
+ snprintf(cursor->why, sizeof(cursor->why), "Signature key id %s does not match onepass keyid",
+ strkeyid);
+ return 0;
+ }
+ if (onepass->hashalg != signature->hashalg) {
+ snprintf(cursor->why, sizeof(cursor->why), "Signature hashalg %u does not match onepass hashalg %u",
+ signature->hashalg, onepass->hashalg);
+ return 0;
+ }
+ if (onepass->keyalg != signature->keyalg) {
+ snprintf(cursor->why, sizeof(cursor->why), "Signature keyalg %u does not match onepass keyalg %u",
+ signature->keyalg, onepass->keyalg);
+ return 0;
+ }
+ if ((j = pgpv_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)) {
+ return 0;
+ }
+ ARRAY_APPEND(cursor->datacookies, pkt);
+ ARRAY_APPEND(cursor->found, primary);
+ return pkt + 1;
+}
+
+/* set up the pubkey keyring */
+int
+pgpv_read_pubring(pgpv_t *pgp, const void *keyring, ssize_t size)
+{
+ if (pgp == NULL) {
+ return 0;
+ }
+ if (keyring) {
+ return (size > 0) ?
+ read_binary_memory(pgp, "pubring", keyring, (size_t)size) :
+ read_binary_file(pgp, "pubring", "%s", keyring);
+ }
+ return read_binary_file(pgp, "pubring", "%s/%s", nonnull_getenv("HOME"), ".gnupg/pubring.gpg");
+}
+
+/* get verified data as a string, return its size */
+size_t
+pgpv_get_verified(pgpv_cursor_t *cursor, size_t cookie, char **ret)
+{
+ pgpv_litdata_t *litdata;
+ uint8_t *data;
+ size_t size;
+ size_t pkt;
+
+ if (ret == NULL || cursor == NULL || cookie == 0) {
+ return 0;
+ }
+ *ret = NULL;
+ if ((pkt = find_onepass(cursor, cookie - 1)) == 0) {
+ return 0;
+ }
+ litdata = &ARRAY_ELEMENT(cursor->pgp->pkts, pkt).u.litdata;
+ data = get_literal_data(cursor, litdata, &size);
+ if ((*ret = calloc(1, size)) == NULL) {
+ return 0;
+ }
+ memcpy(*ret, data, size);
+ return size;
+}
diff --git a/security/libnetpgpverify/files/src/libverify/pgpsum.c b/security/libnetpgpverify/files/src/libverify/pgpsum.c
new file mode 100644
index 00000000000..3516e053b0b
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/pgpsum.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <err.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "digest.h"
+#include "pgpsum.h"
+
+#ifndef USE_ARG
+#define USE_ARG(x) /*LINTED*/(void)&(x)
+#endif
+
+/* add the ascii armor line endings (except for last line) */
+static size_t
+don_armor(digest_t *hash, uint8_t *in, size_t insize, int doarmor)
+{
+ uint8_t *from;
+ uint8_t *newp;
+ uint8_t *p;
+ uint8_t dos_line_end[2];
+
+ dos_line_end[0] = '\r';
+ dos_line_end[1] = '\n';
+ for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) {
+ for (newp = p ; doarmor == 'w' && newp > from ; --newp) {
+ if (*(newp - 1) != ' ' && *(newp - 1) != '\t') {
+ break;
+ }
+ }
+ digest_update(hash, from, (size_t)(newp - from));
+ digest_update(hash, dos_line_end, sizeof(dos_line_end));
+ }
+ digest_update(hash, from, insize - (size_t)(from - in));
+ return 1;
+}
+
+#ifdef NETPGPV_DEBUG
+/* just for giggles, write what we're about to checksum */
+static int
+writefile(uint8_t *mem, size_t insize)
+{
+ size_t cc;
+ size_t wc;
+ char template[256];
+ int fd;
+
+ snprintf(template, sizeof(template), "netpgpvmd.XXXXXX");
+ if ((fd = mkstemp(template)) < 0) {
+ fprintf(stderr, "can't mkstemp %s\n", template);
+ return 0;
+ }
+ for (cc = 0 ; cc < insize ; cc += wc) {
+ if ((wc = write(fd, &mem[cc], insize - cc)) <= 0) {
+ fprintf(stderr, "short write\n");
+ break;
+ }
+ }
+ close(fd);
+ return 1;
+}
+#endif
+
+/* return non-zero if this is actually an armored piece already */
+static int
+already_armored(uint8_t *in, size_t insize)
+{
+ uint8_t *from;
+ uint8_t *p;
+
+ for (from = in ; (p = memchr(from, '\n', insize - (size_t)(from - in))) != NULL ; from = p + 1) {
+ if (*(p - 1) != '\r') {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* calculate the checksum for the data we have */
+static int
+calcsum(uint8_t *out, size_t size, uint8_t *mem, size_t cc, const uint8_t *hashed, size_t hashsize, int doarmor)
+{
+ digest_t hash;
+ uint32_t len32;
+ uint16_t len16;
+ uint8_t hashalg;
+ uint8_t trailer[6];
+
+ USE_ARG(size);
+ /* hashed data is non-null (previously checked) */
+ hashalg = hashed[3];
+ memcpy(&len16, &hashed[4], sizeof(len16));
+ len32 = ntohs(len16) + 6;
+ len32 = htonl(len32);
+ trailer[0] = 0x04;
+ trailer[1] = 0xff;
+ memcpy(&trailer[2], &len32, sizeof(len32));
+#ifdef NETPGPV_DEBUG
+ writefile(mem, cc);
+#endif
+ digest_init(&hash, (const unsigned)hashalg);
+ if (strchr("tw", doarmor) != NULL && !already_armored(mem, cc)) {
+ /* this took me ages to find - something causes gpg to truncate its input */
+ don_armor(&hash, mem, cc - 1, doarmor);
+ } else {
+ digest_update(&hash, mem, cc);
+ }
+ if (hashed) {
+ digest_update(&hash, hashed, hashsize);
+ }
+ digest_update(&hash, trailer, sizeof(trailer));
+ return digest_final(out, &hash);
+}
+
+/* open the file, mmap it, and then get the checksum on that */
+int
+pgpv_digest_file(uint8_t *data, size_t size, const char *name, const uint8_t *hashed, size_t hashsize, int doarmor)
+{
+ struct stat st;
+ uint8_t *mem;
+ size_t cc;
+ FILE *fp;
+ int ret;
+
+ if (hashed == NULL || data == NULL || name == NULL) {
+ fprintf(stderr, "no hashed data provided\n");
+ return 0;
+ }
+ ret = 0;
+ mem = NULL;
+ cc = 0;
+ if ((fp = fopen(name, "r")) == NULL) {
+ warn("%s - not found", name);
+ return 0;
+ }
+ if (fstat(fileno(fp), &st) < 0) {
+ warn("%s - can't stat", name);
+ goto done;
+ }
+ cc = (size_t)(st.st_size);
+ if ((mem = mmap(NULL, cc, PROT_READ, MAP_SHARED, fileno(fp), 0)) == MAP_FAILED) {
+ warn("%s - can't mmap", name);
+ goto done;
+ }
+ ret = calcsum(data, size, mem, cc, hashed, hashsize, doarmor);
+done:
+ if (data) {
+ munmap(mem, cc);
+ }
+ fclose(fp);
+ return ret;
+}
+
+/* calculate the digest over memory too */
+int
+pgpv_digest_memory(uint8_t *data, size_t size, void *mem, size_t cc, const uint8_t *hashed, size_t hashsize, int doarmor)
+{
+ if (hashed == NULL || data == NULL || mem == NULL) {
+ fprintf(stderr, "no hashed data provided\n");
+ return 0;
+ }
+ return calcsum(data, size, mem, cc, hashed, hashsize, doarmor);
+}
diff --git a/security/libnetpgpverify/files/src/libverify/pgpsum.h b/security/libnetpgpverify/files/src/libverify/pgpsum.h
new file mode 100644
index 00000000000..75eb2276248
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/pgpsum.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef PGPSUM_H_
+#define PGPSUM_H_ 20121003
+
+#include <sys/types.h>
+
+#include <inttypes.h>
+
+int pgpv_digest_file(uint8_t */*buf*/, size_t /*size*/, const char */*name*/, const uint8_t */*hashed*/, size_t /*hashsize*/, int /*doarmor*/);
+int pgpv_digest_memory(uint8_t */*buf*/, size_t /*size*/, void */*memory*/, size_t /*cc*/, const uint8_t */*hashed*/, size_t /*hashsize*/, int /*doarmor*/);
+
+#endif
diff --git a/security/libnetpgpverify/files/src/libverify/verify.h b/security/libnetpgpverify/files/src/libverify/verify.h
new file mode 100644
index 00000000000..36ffaacab5b
--- /dev/null
+++ b/security/libnetpgpverify/files/src/libverify/verify.h
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 2012 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.
+ */
+#ifndef NETPGP_VERIFY_H_
+#define NETPGP_VERIFY_H_ 20120928
+
+#include <sys/types.h>
+
+#include <inttypes.h>
+
+#ifndef PGPV_ARRAY
+/* creates 2 unsigned vars called "name"c and "name"size in current scope */
+/* also creates an array called "name"s in current scope */
+#define PGPV_ARRAY(type, name) \
+ unsigned name##c; unsigned name##vsize; type *name##s
+#endif
+
+/* 64bit key ids */
+#define PGPV_KEYID_LEN 8
+#define PGPV_STR_KEYID_LEN (PGPV_KEYID_LEN + PGPV_KEYID_LEN + 1)
+
+/* bignum structure */
+typedef struct pgpv_bignum_t {
+ void *bn; /* hide the implementation details */
+ uint16_t bits; /* cached number of bits */
+} pgpv_bignum_t;
+
+/* right now, our max binary digest length is 20 bytes */
+#define PGPV_MAX_HASH_LEN 20
+
+/* fingerprint */
+typedef struct pgpv_fingerprint_t {
+ uint8_t hashalg; /* algorithm for digest */
+ uint8_t v[PGPV_MAX_HASH_LEN]; /* the digest */
+ uint32_t len; /* its length */
+} pgpv_fingerprint_t;
+
+/* specify size for array of bignums */
+#define PGPV_MAX_PUBKEY_BN 4
+
+/* public key */
+typedef struct pgpv_pubkey_t {
+ pgpv_fingerprint_t fingerprint; /* key fingerprint i.e. digest */
+ uint8_t keyid[PGPV_KEYID_LEN]; /* last 8 bytes of v4 keys */
+ int64_t birth; /* creation time */
+ int64_t expiry; /* expiry time */
+ pgpv_bignum_t bn[PGPV_MAX_PUBKEY_BN]; /* bignums */
+ uint8_t keyalg; /* key algorithm */
+ uint8_t hashalg; /* hash algorithm */
+ uint8_t version; /* key version */
+} pgpv_pubkey_t;
+
+#define PGPV_MAX_SESSKEY_BN 2
+
+/* a (size, byte array) string */
+typedef struct pgpv_string_t {
+ size_t size;
+ uint8_t *data;
+} pgpv_string_t;
+
+typedef struct pgpv_ref_t {
+ void *vp;
+ size_t offset;
+ unsigned mem;
+} pgpv_ref_t;
+
+#define PGPV_MAX_SECKEY_BN 4
+
+typedef struct pgpv_compress_t {
+ pgpv_string_t s;
+ uint8_t compalg;
+} pgpv_compress_t;
+
+/* a packet dealing with trust */
+typedef struct pgpv_trust_t {
+ uint8_t level;
+ uint8_t amount;
+} pgpv_trust_t;
+
+/* a signature sub packet */
+typedef struct pgpv_sigsubpkt_t {
+ pgpv_string_t s;
+ uint8_t tag;
+ uint8_t critical;
+} pgpv_sigsubpkt_t;
+
+#define PGPV_MAX_SIG_BN 2
+
+typedef struct pgpv_signature_t {
+ uint8_t *signer; /* key id of signer */
+ pgpv_ref_t hashstart;
+ uint8_t *hash2;
+ uint8_t *mpi;
+ int64_t birth;
+ int64_t keyexpiry;
+ int64_t expiry;
+ uint32_t hashlen;
+ uint8_t version;
+ uint8_t type;
+ uint8_t keyalg;
+ uint8_t hashalg;
+ uint8_t trustlevel;
+ uint8_t trustamount;
+ pgpv_bignum_t bn[PGPV_MAX_SIG_BN];
+ char *regexp;
+ char *pref_key_server;
+ char *policy;
+ char *features;
+ char *why_revoked;
+ uint8_t *revoke_fingerprint;
+ uint8_t revoke_alg;
+ uint8_t revoke_sensitive;
+ uint8_t trustsig;
+ uint8_t revocable;
+ uint8_t pref_symm_alg;
+ uint8_t pref_hash_alg;
+ uint8_t pref_compress_alg;
+ uint8_t key_server_modify;
+ uint8_t notation;
+ uint8_t type_key;
+ uint8_t primary_userid;
+ uint8_t revoked; /* subtract 1 to get real reason, 0 == not revoked */
+} pgpv_signature_t;
+
+/* a signature packet */
+typedef struct pgpv_sigpkt_t {
+ pgpv_signature_t sig;
+ uint16_t subslen;
+ uint16_t unhashlen;
+ PGPV_ARRAY(pgpv_sigsubpkt_t, subpkts);
+} pgpv_sigpkt_t;
+
+/* a one-pass signature packet */
+typedef struct pgpv_onepass_t {
+ uint8_t keyid[PGPV_KEYID_LEN];
+ uint8_t version;
+ uint8_t type;
+ uint8_t hashalg;
+ uint8_t keyalg;
+ uint8_t nested;
+} pgpv_onepass_t;
+
+/* a literal data packet */
+typedef struct pgpv_litdata_t {
+ uint8_t *filename;
+ pgpv_string_t s;
+ uint32_t secs;
+ uint8_t namelen;
+ char format;
+ unsigned mem;
+ size_t offset;
+ size_t len;
+} pgpv_litdata_t;
+
+/* user attributes - images */
+typedef struct pgpv_userattr_t {
+ size_t len;
+ PGPV_ARRAY(pgpv_string_t, subattrs);
+} pgpv_userattr_t;
+
+/* a general PGP packet */
+typedef struct pgpv_pkt_t {
+ uint8_t tag;
+ uint8_t newfmt;
+ uint8_t allocated;
+ uint8_t mement;
+ size_t offset;
+ pgpv_string_t s;
+ union {
+ pgpv_sigpkt_t sigpkt;
+ pgpv_onepass_t onepass;
+ pgpv_litdata_t litdata;
+ pgpv_compress_t compressed;
+ pgpv_trust_t trust;
+ pgpv_pubkey_t pubkey;
+ pgpv_string_t userid;
+ pgpv_userattr_t userattr;
+ } u;
+} pgpv_pkt_t;
+
+/* a memory structure */
+typedef struct pgpv_mem_t {
+ size_t size;
+ size_t cc;
+ uint8_t *mem;
+ FILE *fp;
+ uint8_t dealloc;
+ const char *allowed; /* the types of packet that are allowed */
+} pgpv_mem_t;
+
+/* packet parser */
+
+typedef struct pgpv_signed_userid_t {
+ pgpv_string_t userid;
+ PGPV_ARRAY(pgpv_signature_t, sigs);
+ uint8_t primary_userid;
+ uint8_t revoked;
+} pgpv_signed_userid_t;
+
+typedef struct pgpv_signed_userattr_t {
+ pgpv_userattr_t userattr;
+ PGPV_ARRAY(pgpv_signature_t, sigs);
+ uint8_t revoked;
+} pgpv_signed_userattr_t;
+
+typedef struct pgpv_signed_subkey_t {
+ pgpv_pubkey_t subkey;
+ pgpv_signature_t revoc_self_sig;
+ PGPV_ARRAY(pgpv_signature_t, sigs);
+} pgpv_signed_subkey_t;
+
+typedef struct pgpv_primarykey_t {
+ pgpv_pubkey_t primary;
+ pgpv_signature_t revoc_self_sig;
+ PGPV_ARRAY(pgpv_signature_t, direct_sigs);
+ PGPV_ARRAY(pgpv_signed_userid_t, signed_userids);
+ PGPV_ARRAY(pgpv_signed_userattr_t, signed_userattrs);
+ PGPV_ARRAY(pgpv_signed_subkey_t, signed_subkeys);
+ size_t fmtsize;
+ uint8_t primary_userid;
+} pgpv_primarykey_t;
+
+/* everything stems from this structure */
+typedef struct pgpv_t {
+ PGPV_ARRAY(pgpv_pkt_t, pkts); /* packet array */
+ PGPV_ARRAY(pgpv_primarykey_t, primaries); /* array of primary keys */
+ PGPV_ARRAY(pgpv_mem_t, areas); /* areas we read packets from */
+ 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 */
+} pgpv_t;
+
+#define PGPV_REASON_LEN 128
+
+/* when searching, we define a cursor, and fill in an array of subscripts */
+typedef struct pgpv_cursor_t {
+ pgpv_t *pgp; /* pointer to pgp tree */
+ char *field; /* field we're searching on */
+ char *op; /* operation we're doing */
+ char *value; /* value we're searching for */
+ void *ptr; /* for regexps etc */
+ PGPV_ARRAY(uint32_t, found); /* array of matched subscripts */
+ PGPV_ARRAY(size_t, datacookies); /* cookies to retrieve matched data */
+ int64_t sigtime; /* time of signature */
+ char why[PGPV_REASON_LEN]; /* reason for bad signature */
+} pgpv_cursor_t;
+
+#ifndef __BEGIN_DECLS
+# if defined(__cplusplus)
+# define __BEGIN_DECLS extern "C" {
+# define __END_DECLS }
+# else
+# define __BEGIN_DECLS
+# define __END_DECLS
+# endif
+#endif
+
+__BEGIN_DECLS
+
+int pgpv_read_pubring(pgpv_t */*pgp*/, const void */*keyringfile/mem*/, 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*/);
+
+int pgpv_close(pgpv_t */*pgp*/);
+
+__END_DECLS
+
+#endif