summaryrefslogtreecommitdiff
path: root/packaging/rpm-beecrypt.diff
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/rpm-beecrypt.diff')
-rw-r--r--packaging/rpm-beecrypt.diff1725
1 files changed, 1725 insertions, 0 deletions
diff --git a/packaging/rpm-beecrypt.diff b/packaging/rpm-beecrypt.diff
new file mode 100644
index 0000000..55036f7
--- /dev/null
+++ b/packaging/rpm-beecrypt.diff
@@ -0,0 +1,1725 @@
+--- ./config.h.in.orig 2011-07-15 09:37:41.000000000 +0000
++++ ./config.h.in 2011-07-18 16:34:29.000000000 +0000
+@@ -13,6 +13,9 @@
+ /* Define to 1 if you have the `basename' function. */
+ #undef HAVE_BASENAME
+
++/* Define to 1 if you have the <beecrypt/api.h> header file. */
++#undef HAVE_BEECRYPT_API_H
++
+ /* Define as 1 if you bzip2 1.0 */
+ #undef HAVE_BZ2_1_0
+
+@@ -77,7 +80,7 @@
+ /* Define as 1 if your zlib has gzseek() */
+ #undef HAVE_GZSEEK
+
+-/* Define if you have the iconv() function. */
++/* Define if you have the iconv() function and it works. */
+ #undef HAVE_ICONV
+
+ /* Define to 1 if you have the <inttypes.h> header file. */
+@@ -227,6 +230,10 @@
+ */
+ #undef LT_OBJDIR
+
++/* Define to the sub-directory in which libtool stores uninstalled libraries.
++ */
++#undef LT_OBJDIR
++
+ /* Define to 1 if `major', `minor', and `makedev' are declared in <mkdev.h>.
+ */
+ #undef MAJOR_IN_MKDEV
+@@ -311,6 +318,9 @@
+ /* Build with acl support? */
+ #undef WITH_ACL
+
++/* Build with beecrypt instead of nss3 support? */
++#undef WITH_BEECRYPT
++
+ /* Build with capability support? */
+ #undef WITH_CAP
+
+--- ./configure.ac.orig 2011-07-15 09:37:20.000000000 +0000
++++ ./configure.ac 2011-07-18 16:34:29.000000000 +0000
+@@ -252,12 +252,43 @@ AC_CHECK_HEADERS([dwarf.h], [
+ AM_CONDITIONAL(LIBDWARF,[test "$WITH_LIBDWARF" = yes])
+
+ #=================
++# Check for beecrypt library if requested.
++AC_ARG_WITH(beecrypt, [ --with-beecrypt build with beecrypt support ],,[with_beecrypt=yes])
++AC_ARG_WITH(internal_beecrypt, [ --with-internal-beecrypt build with internal beecrypt library ],,[with_internal_beecrypt=yes])
++AM_CONDITIONAL([WITH_INTERNAL_BEECRYPT],[test "$with_internal_beecrypt" = yes])
++if test "$with_internal_beecrypt" = yes ; then
++ with_beecrypt=yes
++fi
++AM_CONDITIONAL([WITH_BEECRYPT],[test "$with_beecrypt" = yes])
++
++WITH_BEECRYPT_INCLUDE=
++WITH_BEECRYPT_LIB=
++if test "$with_beecrypt" = yes ; then
++ AC_DEFINE(WITH_BEECRYPT, 1, [Build with beecrypt instead of nss3 support?])
++ if test "$with_internal_beecrypt" = yes ; then
++ WITH_BEECRYPT_INCLUDE="-I\$(top_srcdir)/beecrypt"
++ AC_DEFINE(HAVE_BEECRYPT_API_H, 1, [Define to 1 if you have the <beecrypt/api.h> header file.])
++ else
++ AC_CHECK_LIB(beecrypt, mpfprintln, [
++ WITH_BEECRYPT_LIB="-lbeecrypt"
++ ],[
++ AC_MSG_ERROR([missing required library 'beecrypt'])
++ ])
++ AC_CHECK_HEADER([beecrypt/api.h], [AC_DEFINE(HAVE_BEECRYPT_API_H, 1, [Define to 1 if you have the <beecrypt/api.h> header file.])
++ ])
++ fi
++fi
++AC_SUBST(WITH_BEECRYPT_LIB)
++AC_SUBST(WITH_BEECRYPT_INCLUDE)
++
++#=================
+ # Check for NSS library.
+ # We need nss.h from NSS which needs nspr.h. Unfortunately both glibc and NSS
+ # have a header named nss.h... so make extra check for NSS's sechash.h
+ # which we use too and hopefully is slightly more unique to NSS.
+ WITH_NSS_INCLUDE=
+ WITH_NSS_LIB=
++if test "$with_beecrypt" != yes ; then
+ AC_CHECK_HEADERS([nspr.h nss.h sechash.h], [], [
+ AC_MSG_ERROR([missing required NSPR / NSS header])
+ ])
+@@ -266,6 +297,7 @@ AC_CHECK_LIB(nss3, NSS_NoDB_Init, [
+ ], [
+ AC_MSG_ERROR([missing required NSS library 'nss3'])
+ ])
++fi
+ AC_SUBST(WITH_NSS_INCLUDE)
+ AC_SUBST(WITH_NSS_LIB)
+
+--- ./rpmio/Makefile.am.orig 2011-07-15 09:36:33.000000000 +0000
++++ ./rpmio/Makefile.am 2011-07-18 16:36:35.000000000 +0000
+@@ -2,6 +2,7 @@
+
+ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_builddir)/include/
+ AM_CPPFLAGS += @WITH_NSS_INCLUDE@
++AM_CPPFLAGS += @WITH_BEECRYPT_INCLUDE@
+ AM_CPPFLAGS += @WITH_POPT_INCLUDE@
+ AM_CPPFLAGS += -I$(top_srcdir)/misc
+ AM_CPPFLAGS += -DRPMCONFIGDIR="\"@RPMCONFIGDIR@\""
+@@ -17,10 +18,17 @@ librpmio_la_SOURCES = \
+ rpmstring.c rpmfileutil.c \
+ rpmkeyring.c
+
++if WITH_BEECRYPT
++librpmio_la_SOURCES += digest_beecrypt.c
++else
++librpmio_la_SOURCES += digest_nss.c
++endif
++
+ librpmio_la_LDFLAGS = -version-info 2:1:0
+ librpmio_la_LIBADD = \
+ ../misc/libmisc.la \
+ @WITH_NSS_LIB@ \
++ @WITH_BEECRYPT_LIB@ \
+ @WITH_BZ2_LIB@ \
+ @WITH_ZLIB_LIB@ \
+ @WITH_LIBELF_LIB@ \
+@@ -28,6 +36,15 @@ librpmio_la_LIBADD = \
+ @WITH_LZMA_LIB@ \
+ -lpthread
+
++if WITH_INTERNAL_BEECRYPT
++librpmio_la_LIBADD += $(libbeecrypt_la)
++
++libbeecrypt_la = $(top_builddir)/beecrypt/libbeecrypt_nolibdir.la
++
++$(top_builddir)/beecrypt/libbeecrypt_nolibdir.la: $(top_builddir)/beecrypt/libbeecrypt.la
++ sed -e 's/libdir=.*/libdir=/' < $(top_builddir)/beecrypt/libbeecrypt.la > $(top_builddir)/beecrypt/libbeecrypt_nolibdir.la
++endif
++
+ if WITH_LUA
+ AM_CPPFLAGS += -I$(top_srcdir)/luaext/
+ AM_CPPFLAGS += @LUA_CFLAGS@
+--- ./rpmio/base64.c.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./rpmio/base64.c 2011-07-18 16:34:29.000000000 +0000
+@@ -4,8 +4,11 @@
+ #include <arpa/inet.h>
+ #include <stdlib.h>
+
++#include "system.h"
++
+ #include "rpmio/base64.h"
+
++#ifndef WITH_BEECRYPT
+
+ static char base64_encode_value(char value_in)
+ {
+@@ -253,3 +256,4 @@ int main(int argc, char *argv[])
+ }
+ #endif
+
++#endif /* WITH_BEECRYPT */
+--- ./rpmio/digest.c.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./rpmio/digest.c 2011-07-18 16:34:29.000000000 +0000
+@@ -4,25 +4,12 @@
+
+ #include "system.h"
+
++#include <rpm/rpmpgp.h>
+ #include "rpmio/digest.h"
++#include "rpmio/rpmio_internal.h"
+
+ #include "debug.h"
+
+-#ifdef SHA_DEBUG
+-#define DPRINTF(_a) fprintf _a
+-#else
+-#define DPRINTF(_a)
+-#endif
+-
+-
+-/**
+- * MD5/SHA1 digest private data.
+- */
+-struct DIGEST_CTX_s {
+- rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
+- HASHContext *hashctx; /*!< Internal NSS hash context. */
+- int algo; /*!< Used hash algorithm */
+-};
+
+ #define DIGESTS_MAX 11
+ struct rpmDigestBundle_s {
+@@ -109,138 +96,3 @@ DIGEST_CTX rpmDigestBundleDupCtx(rpmDige
+ return dup;
+ }
+
+-DIGEST_CTX
+-rpmDigestDup(DIGEST_CTX octx)
+-{
+- DIGEST_CTX nctx = NULL;
+- if (octx) {
+- HASHContext *hctx = HASH_Clone(octx->hashctx);
+- if (hctx) {
+- nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
+- nctx->hashctx = hctx;
+- }
+- }
+- return nctx;
+-}
+-
+-RPM_GNUC_PURE
+-static HASH_HashType getHashType(int hashalgo)
+-{
+- switch (hashalgo) {
+- case PGPHASHALGO_MD5:
+- return HASH_AlgMD5;
+- break;
+- case PGPHASHALGO_MD2:
+- return HASH_AlgMD2;
+- break;
+- case PGPHASHALGO_SHA1:
+- return HASH_AlgSHA1;
+- break;
+- case PGPHASHALGO_SHA256:
+- return HASH_AlgSHA256;
+- break;
+- case PGPHASHALGO_SHA384:
+- return HASH_AlgSHA384;
+- break;
+- case PGPHASHALGO_SHA512:
+- return HASH_AlgSHA512;
+- break;
+- case PGPHASHALGO_RIPEMD160:
+- case PGPHASHALGO_TIGER192:
+- case PGPHASHALGO_HAVAL_5_160:
+- default:
+- return HASH_AlgNULL;
+- break;
+- }
+-}
+-
+-size_t
+-rpmDigestLength(int hashalgo)
+-{
+- return HASH_ResultLen(getHashType(hashalgo));
+-}
+-
+-DIGEST_CTX
+-rpmDigestInit(int hashalgo, rpmDigestFlags flags)
+-{
+- HASH_HashType type = getHashType(hashalgo);
+- HASHContext *hashctx = NULL;
+- DIGEST_CTX ctx = NULL;
+-
+- if (type == HASH_AlgNULL || rpmInitCrypto() < 0)
+- goto exit;
+-
+- if ((hashctx = HASH_Create(type)) != NULL) {
+- ctx = xcalloc(1, sizeof(*ctx));
+- ctx->flags = flags;
+- ctx->algo = hashalgo;
+- ctx->hashctx = hashctx;
+- HASH_Begin(ctx->hashctx);
+- }
+-
+-DPRINTF((stderr, "*** Init(%x) ctx %p hashctx %p\n", flags, ctx, ctx->hashctx));
+-exit:
+- return ctx;
+-}
+-
+-int
+-rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
+-{
+- size_t partlen;
+- const unsigned char *ptr = data;
+-
+- if (ctx == NULL)
+- return -1;
+-
+-DPRINTF((stderr, "*** Update(%p,%p,%zd) hashctx %p \"%s\"\n", ctx, data, len, ctx->hashctx, ((char *)data)));
+- partlen = ~(unsigned int)0xFF;
+- while (len > 0) {
+- if (len < partlen) {
+- partlen = len;
+- }
+- HASH_Update(ctx->hashctx, ptr, partlen);
+- ptr += partlen;
+- len -= partlen;
+- }
+- return 0;
+-}
+-
+-int
+-rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
+-{
+- unsigned char * digest;
+- unsigned int digestlen;
+-
+- if (ctx == NULL)
+- return -1;
+- digestlen = HASH_ResultLenContext(ctx->hashctx);
+- digest = xmalloc(digestlen);
+-
+-DPRINTF((stderr, "*** Final(%p,%p,%p,%zd) hashctx %p digest %p\n", ctx, datap, lenp, asAscii, ctx->hashctx, digest));
+-/* FIX: check rc */
+- HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
+-
+- /* Return final digest. */
+- if (!asAscii) {
+- if (lenp) *lenp = digestlen;
+- if (datap) {
+- *datap = digest;
+- digest = NULL;
+- }
+- } else {
+- if (lenp) *lenp = (2*digestlen) + 1;
+- if (datap) {
+- const uint8_t * s = (const uint8_t *) digest;
+- *datap = pgpHexStr(s, digestlen);
+- }
+- }
+- if (digest) {
+- memset(digest, 0, digestlen); /* In case it's sensitive */
+- free(digest);
+- }
+- HASH_Destroy(ctx->hashctx);
+- memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+- free(ctx);
+- return 0;
+-}
+-
+--- ./rpmio/digest.h.orig 2011-07-12 11:28:13.000000000 +0000
++++ ./rpmio/digest.h 2011-07-18 16:34:29.000000000 +0000
+@@ -1,11 +1,6 @@
+ #ifndef _RPMDIGEST_H
+ #define _RPMDIGEST_H
+
+-#include <nss.h>
+-#include <sechash.h>
+-#include <keyhi.h>
+-#include <cryptohi.h>
+-
+ #include <rpm/rpmpgp.h>
+ #include "rpmio/base64.h"
+
+@@ -42,8 +37,18 @@ struct pgpDig_s {
+ struct pgpDigParams_s pubkey;
+
+ /* DSA/RSA parameters */
+- SECKEYPublicKey *keydata;
+- SECItem *sigdata;
++ void *keydata;
++ void *sigdata;
+ };
+
++void pgpCleanRSADSA(pgpDig dig);
++
++int pgpSetSigMpiRSA(pgpDig dig, int num, const uint8_t *p);
++int pgpSetPubMpiRSA(pgpDig dig, int num, const uint8_t *p);
++int pgpVerifyRSA(pgpDig dig, uint8_t *hash, size_t hashlen);
++
++int pgpSetSigMpiDSA(pgpDig dig, int num, const uint8_t *p);
++int pgpSetPubMpiDSA(pgpDig dig, int num, const uint8_t *p);
++int pgpVerifyDSA(pgpDig dig, uint8_t *hash, size_t hashlen);
++
+ #endif /* _RPMDIGEST_H */
+--- ./rpmio/digest_beecrypt.c.orig 2011-07-18 16:34:29.000000000 +0000
++++ ./rpmio/digest_beecrypt.c 2011-07-18 16:34:29.000000000 +0000
+@@ -0,0 +1,493 @@
++#include "system.h"
++
++#include <beecrypt.h>
++#include <dsa.h>
++#include <endianness.h>
++#include <md5.h>
++#include <mp.h>
++#include <rsa.h>
++#include <rsapk.h>
++#include <sha1.h>
++#if HAVE_BEECRYPT_API_H
++#include <sha256.h>
++#include <sha384.h>
++#include <sha512.h>
++#endif
++
++#include <rpm/rpmpgp.h>
++#include "rpmio/digest.h"
++#include "rpmio/rpmio_internal.h"
++
++#include "debug.h"
++
++/* interface to beecrpyt crypto framework */
++
++/**************************** init ************************************/
++
++int rpmInitCrypto(void) {
++ return 0;
++}
++
++int rpmFreeCrypto(void) {
++ return 0;
++}
++
++/**************************** helpers ************************************/
++
++static inline unsigned int pgpMpiBits(const uint8_t *p)
++{
++ return ((p[0] << 8) | p[1]);
++}
++
++static inline size_t pgpMpiLen(const uint8_t *p)
++{
++ return (2 + ((pgpMpiBits(p)+7)>>3));
++}
++
++static inline char * pgpHexCvt(char *t, const byte *s, int nbytes)
++ /*@modifies *t @*/
++{
++ static char hex[] = "0123456789abcdef";
++ while (nbytes-- > 0) {
++ unsigned int i;
++ i = *s++;
++ *t++ = hex[ (i >> 4) & 0xf ];
++ *t++ = hex[ (i ) & 0xf ];
++ }
++ *t = '\0';
++ return t;
++}
++
++static const char * pgpMpiHex(const byte *p)
++{
++ static char prbuf[2048];
++ char *t = prbuf;
++ t = pgpHexCvt(t, p+2, pgpMpiLen(p)-2);
++ return prbuf;
++}
++
++static int pgpHexSet(int lbits, mpnumber * mpn, const byte * p)
++{
++ unsigned int mbits = pgpMpiBits(p);
++ unsigned int nbits;
++ unsigned int nbytes;
++ char *t;
++ unsigned int ix;
++
++ nbits = (lbits > mbits ? lbits : mbits);
++ nbytes = ((nbits + 7) >> 3);
++ t = xmalloc(2*nbytes+1);
++ ix = 2 * ((nbits - mbits) >> 3);
++
++ if (ix > 0) memset(t, (int)'0', ix);
++ strcpy(t+ix, pgpMpiHex(p));
++ (void) mpnsethex(mpn, t);
++ t = _free(t);
++ return 0;
++}
++
++void pgpCleanRSADSA(pgpDig dig)
++{
++ if (!dig)
++ return;
++ if (dig->keydata) {
++ dig->keydata= _free(dig->keydata);
++ }
++ if (dig->sigdata) {
++ dig->sigdata = _free(dig->sigdata);
++ }
++}
++
++
++/****************************** RSA **************************************/
++
++struct pgpDigSigRSA_s {
++ mpnumber c;
++};
++
++struct pgpDigPubRSA_s {
++ rsapk rsa_pk;
++};
++
++int
++pgpSetSigMpiRSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigSigRSA_s *sig;
++ if (num != 0)
++ return 1;
++ if (!dig->sigdata)
++ dig->sigdata = xcalloc(1, sizeof(*sig));
++ sig = dig->sigdata;
++ if (!sig)
++ return 1;
++ (void) mpnsethex(&sig->c, pgpMpiHex(p));
++ return 0;
++}
++
++int
++pgpSetPubMpiRSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigPubRSA_s *pub;
++
++ if (!dig->keydata)
++ dig->keydata = xcalloc(1, sizeof(*pub));
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ (void) mpbsethex(&pub->rsa_pk.n, pgpMpiHex(p));
++ return 0;
++ case 1:
++ (void) mpnsethex(&pub->rsa_pk.e, pgpMpiHex(p));
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++static inline unsigned char nibble(char c)
++{
++ if (c >= '0' && c <= '9')
++ return (c - '0');
++ if (c >= 'A' && c <= 'F')
++ return (c - 'A') + 10;
++ if (c >= 'a' && c <= 'f')
++ return (c - 'a') + 10;
++ return 0;
++}
++
++int pgpVerifyRSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ const char * prefix = NULL;
++ int res;
++ mpnumber rsahm;
++ struct pgpDigSigRSA_s *sig;
++ struct pgpDigPubRSA_s *pub;
++
++ sig = dig->sigdata;
++ pub = dig->keydata;
++ if (!sig || !pub)
++ return 1;
++
++ switch (dig->signature.hash_algo) {
++ case PGPHASHALGO_MD5:
++ prefix = "3020300c06082a864886f70d020505000410";
++ break;
++ case PGPHASHALGO_SHA1:
++ prefix = "3021300906052b0e03021a05000414";
++ break;
++ case PGPHASHALGO_MD2:
++ prefix = "3020300c06082a864886f70d020205000410";
++ break;
++ case PGPHASHALGO_SHA256:
++ prefix = "3031300d060960864801650304020105000420";
++ break;
++ case PGPHASHALGO_SHA384:
++ prefix = "3041300d060960864801650304020205000430";
++ break;
++ case PGPHASHALGO_SHA512:
++ prefix = "3051300d060960864801650304020305000440";
++ break;
++ /* fallthrough for unsupported / unknown types */
++ default:
++ return 1;
++ }
++
++ /* Generate RSA modulus parameter. */
++ { unsigned int nbits = MP_WORDS_TO_BITS(sig->c.size);
++ unsigned int nb = (nbits + 7) >> 3;
++ byte *buf, *bp;
++
++ if (nb < 3)
++ return 1;
++ buf = xmalloc(nb);
++ memset(buf, 0xff, nb);
++ buf[0] = 0x00;
++ buf[1] = 0x01;
++ bp = buf + nb - strlen(prefix)/2 - hashlen - 1;
++ if (bp < buf)
++ return 1;
++ *bp++ = 0;
++ for (; *prefix; prefix += 2)
++ *bp++ = (nibble(prefix[0]) << 4) | nibble(prefix[1]);
++ memcpy(bp, hash, hashlen);
++ mpnzero(&rsahm);
++ (void) mpnsetbin(&rsahm, buf, nb);
++ buf = _free(buf);
++ }
++#if HAVE_BEECRYPT_API_H
++ res = rsavrfy(&pub->rsa_pk.n, &pub->rsa_pk.e, &sig->c, &rsahm) == 1 ? 0 : 1;
++#else
++ res = rsavrfy(&pub->rsa_pk, &rsahm, &sig->c) == 1 ? 0 : 1;
++#endif
++ mpnfree(&rsahm);
++ return res;
++}
++
++
++/****************************** DSA **************************************/
++
++struct pgpDigSigDSA_s {
++ mpnumber r;
++ mpnumber s;
++};
++
++struct pgpDigPubDSA_s {
++ mpbarrett p;
++ mpbarrett q;
++ mpnumber g;
++ mpnumber y;
++};
++
++int
++pgpSetSigMpiDSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigSigDSA_s *sig;
++
++ if (!dig->sigdata)
++ dig->sigdata = xcalloc(1, sizeof(*sig));
++ sig = dig->sigdata;
++ if (!sig)
++ return 1;
++ switch(num) {
++ case 0:
++ return pgpHexSet(160, &sig->r, p);
++ case 1:
++ return pgpHexSet(160, &sig->s, p);
++ default:
++ return 1;
++ }
++}
++
++int
++pgpSetPubMpiDSA(pgpDig dig, int num, const uint8_t *p)
++{
++ struct pgpDigPubDSA_s *pub;
++
++ if (!dig->keydata)
++ dig->keydata = xcalloc(1, sizeof(*pub));
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ mpbsethex(&pub->p, pgpMpiHex(p));
++ return 0;
++ case 1:
++ mpbsethex(&pub->q, pgpMpiHex(p));
++ return 0;
++ case 2:
++ mpnsethex(&pub->g, pgpMpiHex(p));
++ return 0;
++ case 3:
++ mpnsethex(&pub->y, pgpMpiHex(p));
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int pgpVerifyDSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ struct pgpDigSigDSA_s *sig;
++ struct pgpDigPubDSA_s *pub;
++ mpnumber hm;
++ int res;
++
++ sig = dig->sigdata;
++ pub = dig->keydata;
++ if (!sig || !pub)
++ return 1;
++ mpnzero(&hm);
++ mpnsetbin(&hm, hash, hashlen);
++ res = dsavrfy(&pub->p, &pub->q, &pub->g, &hm, &pub->y, &sig->r, &sig->s) == 1 ? 0 : 1;
++ mpnfree(&hm);
++ return res;
++}
++
++/**************************** digest ************************************/
++
++#ifdef SHA_DEBUG
++#define DPRINTF(_a) fprintf _a
++#else
++#define DPRINTF(_a)
++#endif
++
++/**
++ * MD5/SHA1 digest private data.
++ */
++struct DIGEST_CTX_s {
++ rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
++ int algo; /*!< Used hash algorithm */
++ uint32_t datalen; /*!< No. bytes in block of plaintext data. */
++ uint32_t paramlen; /*!< No. bytes of digest parameters. */
++ uint32_t digestlen; /*!< No. bytes of digest. */
++ void * param; /*!< Digest parameters. */
++ int (*Reset) (void * param)
++ /*@modifies param @*/; /*!< Digest initialize. */
++ int (*Update) (void * param, const byte * data, size_t size)
++ /*@modifies param @*/; /*!< Digest transform. */
++ int (*Digest) (void * param, /*@out@*/ byte * digest)
++ /*@modifies param, digest @*/; /*!< Digest finish. */
++};
++
++DIGEST_CTX
++rpmDigestDup(DIGEST_CTX octx)
++{
++ DIGEST_CTX nctx;
++ nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
++ nctx->param = memcpy(xcalloc(1, nctx->paramlen), octx->param, nctx->paramlen);
++ return nctx;
++}
++
++size_t
++rpmDigestLength(int hashalgo)
++{
++ switch (hashalgo) {
++ case PGPHASHALGO_MD5:
++ return 16;
++ case PGPHASHALGO_SHA1:
++ return 20;
++#if HAVE_BEECRYPT_API_H
++ case PGPHASHALGO_SHA256:
++ return 32;
++ case PGPHASHALGO_SHA384:
++ return 48;
++ case PGPHASHALGO_SHA512:
++ return 64;
++#endif
++ default:
++ return 0;
++ }
++}
++
++DIGEST_CTX
++rpmDigestInit(int hashalgo, rpmDigestFlags flags)
++{
++ DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
++ int xx;
++
++ ctx->flags = flags;
++ ctx->algo = hashalgo;
++
++ switch (hashalgo) {
++ case PGPHASHALGO_MD5:
++ ctx->digestlen = 16;
++ ctx->datalen = 64;
++ ctx->paramlen = sizeof(md5Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) md5Reset;
++ ctx->Update = (void *) md5Update;
++ ctx->Digest = (void *) md5Digest;
++ break;
++ case PGPHASHALGO_SHA1:
++ ctx->digestlen = 20;
++ ctx->datalen = 64;
++ ctx->paramlen = sizeof(sha1Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha1Reset;
++ ctx->Update = (void *) sha1Update;
++ ctx->Digest = (void *) sha1Digest;
++ break;
++#if HAVE_BEECRYPT_API_H
++ case PGPHASHALGO_SHA256:
++ ctx->digestlen = 32;
++ ctx->datalen = 64;
++ ctx->paramlen = sizeof(sha256Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha256Reset;
++ ctx->Update = (void *) sha256Update;
++ ctx->Digest = (void *) sha256Digest;
++ break;
++ case PGPHASHALGO_SHA384:
++ ctx->digestlen = 48;
++ ctx->datalen = 128;
++ ctx->paramlen = sizeof(sha384Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha384Reset;
++ ctx->Update = (void *) sha384Update;
++ ctx->Digest = (void *) sha384Digest;
++ break;
++ case PGPHASHALGO_SHA512:
++ ctx->digestlen = 64;
++ ctx->datalen = 128;
++ ctx->paramlen = sizeof(sha512Param);
++ ctx->param = xcalloc(1, ctx->paramlen);
++ ctx->Reset = (void *) sha512Reset;
++ ctx->Update = (void *) sha512Update;
++ ctx->Digest = (void *) sha512Digest;
++ break;
++#endif
++ case PGPHASHALGO_RIPEMD160:
++ case PGPHASHALGO_MD2:
++ case PGPHASHALGO_TIGER192:
++ case PGPHASHALGO_HAVAL_5_160:
++ default:
++ free(ctx);
++ return NULL;
++ }
++
++ xx = (*ctx->Reset) (ctx->param);
++
++DPRINTF((stderr, "*** Init(%x) ctx %p param %p\n", flags, ctx, ctx->param));
++ return ctx;
++}
++
++/* LCL: ctx->param may be modified, but ctx is abstract @*/
++int
++rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
++{
++ if (ctx == NULL)
++ return -1;
++
++DPRINTF((stderr, "*** Update(%p,%p,%d) param %p \"%s\"\n", ctx, data, len, ctx->param, ((char *)data)));
++ return (*ctx->Update) (ctx->param, data, len);
++}
++
++int
++rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
++{
++ byte * digest;
++ char * t;
++ int i;
++
++ if (ctx == NULL)
++ return -1;
++ digest = xmalloc(ctx->digestlen);
++
++DPRINTF((stderr, "*** Final(%p,%p,%p,%d) param %p digest %p\n", ctx, datap, lenp, asAscii, ctx->param, digest));
++ /* FIX: check rc */
++ (void) (*ctx->Digest) (ctx->param, digest);
++
++ /* Return final digest. */
++ if (!asAscii) {
++ if (lenp) *lenp = ctx->digestlen;
++ if (datap) {
++ *datap = digest;
++ digest = NULL;
++ }
++ } else {
++ if (lenp) *lenp = (2*ctx->digestlen) + 1;
++ if (datap) {
++ const byte * s = (const byte *) digest;
++ static const char hex[] = "0123456789abcdef";
++
++ *datap = t = xmalloc((2*ctx->digestlen) + 1);
++ for (i = 0 ; i < ctx->digestlen; i++) {
++ *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
++ *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ];
++ }
++ *t = '\0';
++ }
++ }
++ if (digest) {
++ memset(digest, 0, ctx->digestlen); /* In case it's sensitive */
++ free(digest);
++ }
++ memset(ctx->param, 0, ctx->paramlen); /* In case it's sensitive */
++ free(ctx->param);
++ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
++ free(ctx);
++ return 0;
++}
+--- ./rpmio/digest_nss.c.orig 2011-07-18 16:34:29.000000000 +0000
++++ ./rpmio/digest_nss.c 2011-07-18 16:34:29.000000000 +0000
+@@ -0,0 +1,500 @@
++#include <nss.h>
++#include <sechash.h>
++#include <keyhi.h>
++#include <cryptohi.h>
++
++#include "system.h"
++
++#include <rpm/rpmpgp.h>
++#include "rpmio/rpmio_internal.h"
++#include "rpmio/digest.h"
++
++#include "debug.h"
++
++/* interface to nss crypto framework */
++
++/**************************** init ************************************/
++
++static int _crypto_initialized = 0;
++static int _new_process = 1;
++
++/*
++ * Only flag for re-initialization here, in the common case the child
++ * exec()'s something else shutting down NSS here would be waste of time.
++ */
++static void at_forkchild(void) {
++ _new_process = 1;
++}
++
++int rpmInitCrypto(void) {
++ int rc = 0;
++
++ /* Lazy NSS shutdown for re-initialization after fork() */
++ if (_new_process && _crypto_initialized) {
++ rpmFreeCrypto();
++ }
++
++ /* Initialize NSS if not already done */
++ if (!_crypto_initialized) {
++ if (NSS_NoDB_Init(NULL) != SECSuccess) {
++ rc = -1;
++ } else {
++ _crypto_initialized = 1;
++ }
++ }
++
++ /* Register one post-fork handler per process */
++ if (_new_process) {
++ if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
++ rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
++ }
++ _new_process = 0;
++ }
++ return rc;
++}
++
++int rpmInitCrypto(void) {
++ int rc = 0;
++
++ if (!_crypto_initialized) {
++ if (NSS_NoDB_Init(NULL) != SECSuccess) {
++ rc = -1;
++ } else {
++ _crypto_initialized = 1;
++ }
++ }
++ return rc;
++}
++
++int rpmFreeCrypto(void)
++{
++ int rc = 0;
++ if (_crypto_initialized) {
++ rc = (NSS_Shutdown() != SECSuccess);
++ _crypto_initialized = 0;
++ }
++ return rc;
++}
++
++/**************************** helpers ************************************/
++
++static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
++{
++ PRArenaPool *arena;
++ SECKEYPublicKey *key;
++
++ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
++ if (arena == NULL)
++ return NULL;
++
++ key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
++
++ if (key == NULL) {
++ PORT_FreeArena(arena, PR_FALSE);
++ return NULL;
++ }
++
++ key->keyType = type;
++ key->pkcs11ID = CK_INVALID_HANDLE;
++ key->pkcs11Slot = NULL;
++ key->arena = arena;
++ return key;
++}
++
++static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
++{
++ size_t nbytes = pgpMpiLen(p)-2;
++
++ if (item == NULL) {
++ if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
++ return item;
++ } else {
++ if (arena != NULL)
++ item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
++ else
++ item->data = PORT_Realloc(item->data, nbytes);
++
++ if (item->data == NULL) {
++ if (arena == NULL)
++ SECITEM_FreeItem(item, PR_TRUE);
++ return NULL;
++ }
++ }
++
++ memcpy(item->data, p+2, nbytes);
++ item->len = nbytes;
++ return item;
++}
++
++static int pgpMpiSet(unsigned int lbits,
++ void *dest, const uint8_t * p, const uint8_t * pend)
++{
++ unsigned int mbits = pgpMpiBits(p);
++ unsigned int nbits;
++ size_t nbytes;
++ char *t = dest;
++ unsigned int ix;
++
++ if ((p + ((mbits+7) >> 3)) > pend)
++ return 1;
++
++ if (mbits > lbits)
++ return 1;
++
++ nbits = (lbits > mbits ? lbits : mbits);
++ nbytes = ((nbits + 7) >> 3);
++ ix = (nbits - mbits) >> 3;
++
++ if (ix > 0) memset(t, '\0', ix);
++ memcpy(t+ix, p+2, nbytes-ix);
++
++ return 0;
++}
++
++void pgpCleanRSADSA(pgpDig dig)
++{
++ if (!dig)
++ return;
++ if (dig->keydata) {
++ SECKEY_DestroyPublicKey(dig->keydata);
++ dig->keydata = NULL;
++ }
++ if (dig->sigdata) {
++ SECITEM_ZfreeItem(dig->sigdata, PR_TRUE);
++ dig->sigdata = NULL;
++ }
++}
++
++/****************************** RSA **************************************/
++
++int
++pgpSetSigMpiRSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECItem *sig;
++
++ if (num != 0)
++ return 1;
++ sig = dig->rsasigdata;
++ sig = pgpMpiItem(NULL, sig, p);
++ dig->rsasigdata = sig;
++ if (sig == NULL)
++ return 1;
++ return 0;
++}
++
++int
++pgpSetPubMpiRSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECKEYPublicKey *pub;
++
++ if (!dig->keydata)
++ dig->keydata = pgpNewPublicKey(rsaKey);
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ pgpMpiItem(pub->arena, &pub->u.rsa.modulus, p);
++ return 0;
++ case 1:
++ pgpMpiItem(pub->arena, &pub->u.rsa.publicExponent, p);
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int pgpVerifyRSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ SECOidTag sigalg;
++ SECItem digest;
++ SECKEYPublicKey *pub;
++ SECItem *sig;
++ SECItem *newsig = NULL;
++ size_t siglen;
++ int res;
++
++ switch (dig->hash_algo) {
++ case PGPHASHALGO_MD5:
++ sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA1:
++ sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_MD2:
++ sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA256:
++ sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA384:
++ sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
++ break;
++ case PGPHASHALGO_SHA512:
++ sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
++ break;
++ /* fallthrough for unsupported / unknown types */
++ default:
++ sigalg = SEC_OID_UNKNOWN;
++ break;
++ }
++ digest.type = siBuffer;
++ digest.data = hash;
++ digest.len = hashlen;
++
++ pub = dig->keydata;
++ sig = dig->sigdata;
++ siglen = SECKEY_SignatureLen(dig->keydata);
++
++ /* Zero-pad signature data up to expected size if necessary */
++ if (siglen > sig->len) {
++ size_t pad = siglen - sig->len;
++ if ((newsig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
++ return 1;
++ }
++ memset(newsig->data, 0, pad);
++ memcpy(newsig->data+pad, sig->data, sig->len);
++ sig = newsig;
++ }
++
++ if (VFY_VerifyDigest(&digest, pub, sig, sigalg, NULL) == SECSuccess)
++ res = 0;
++ else
++ res = 1;
++
++ if (newsig) {
++ SECITEM_ZfreeItem(newsig, 1);
++ }
++ return res;
++}
++
++
++/****************************** DSA **************************************/
++
++int
++pgpSetSigMpiDSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECItem *sig, *new;
++
++ switch(num) {
++ case 0:
++ sig = SECITEM_AllocItem(NULL, NULL, 2*DSA_SUBPRIME_LEN);
++ dig->sigdata = sig;
++ memset(sig->data, 0, 2*DSA_SUBPRIME_LEN);
++ pgpMpiSet(DSA_SUBPRIME_LEN*8, sig->data, p, pend);
++ return 0;
++ case 1:
++ sig = dig->sigdata;
++ if (!sig)
++ return 1;
++ pgpMpiSet(DSA_SUBPRIME_LEN*8, sig->data + DSA_SUBPRIME_LEN, p, pend);
++ new = SECITEM_AllocItem(NULL, NULL, 0);
++ if (!new)
++ return 1;
++ if (DSAU_EncodeDerSig(new, sig) != SECSuccess)
++ return 1;
++ SECITEM_FreeItem(sig, PR_TRUE);
++ dig->sigdata = new;
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int
++pgpSetPubMpiDSA(struct pgpDig_s *dig, int num, const uint8_t *p, const uint8_t *pend)
++{
++ SECKEYPublicKey *pub;
++
++ if (!dig->keydata)
++ dig->keydata = pgpNewPublicKey(dsaKey);
++ pub = dig->keydata;
++ if (!pub)
++ return 1;
++ switch(num) {
++ case 0:
++ pgpMpiItem(pub->arena, &pub->u.dsa.params.prime, p);
++ return 0;
++ case 1:
++ pgpMpiItem(pub->arena, &pub->u.dsa.params.subPrime, p);
++ return 0;
++ case 2:
++ pgpMpiItem(pub->arena, &pub->u.dsa.params.base, p);
++ return 0;
++ case 3:
++ pgpMpiItem(pub->arena, &pub->u.dsa.publicValue, p);
++ return 0;
++ default:
++ return 1;
++ }
++}
++
++int pgpVerifyDSA(pgpDig dig, uint8_t *hash, size_t hashlen)
++{
++ SECItem digest;
++ SECKEYPublicKey *pub;
++ SECItem *sig;
++
++ sig = dig->sigdata;
++ pub = dig->keydata;
++ digest.type = siBuffer;
++ digest.data = hash;
++ digest.len = hashlen;
++ if (VFY_VerifyDigest(&digest, pub, sig, SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, NULL) == SECSuccess)
++ return 0;
++ else
++ return 1;
++}
++
++
++/**************************** digest ************************************/
++
++
++#ifdef SHA_DEBUG
++#define DPRINTF(_a) fprintf _a
++#else
++#define DPRINTF(_a)
++#endif
++
++
++/**
++ * MD5/SHA1 digest private data.
++ */
++struct DIGEST_CTX_s {
++ rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
++ HASHContext *hashctx; /*!< Internal NSS hash context. */
++ int algo; /*!< Used hash algorithm */
++};
++
++DIGEST_CTX
++rpmDigestDup(DIGEST_CTX octx)
++{
++ DIGEST_CTX nctx;
++ nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
++ nctx->hashctx = HASH_Clone(octx->hashctx);
++ if (nctx->hashctx == NULL) {
++ fprintf(stderr, "HASH_Clone failed\n");
++ exit(EXIT_FAILURE); /* FIX: callers do not bother checking error return */
++ }
++ return nctx;
++}
++
++RPM_GNUC_PURE
++static HASH_HashType getHashType(int hashalgo)
++{
++ switch (hashalgo) {
++ case PGPHASHALGO_MD5:
++ return HASH_AlgMD5;
++ break;
++ case PGPHASHALGO_MD2:
++ return HASH_AlgMD2;
++ break;
++ case PGPHASHALGO_SHA1:
++ return HASH_AlgSHA1;
++ break;
++ case PGPHASHALGO_SHA256:
++ return HASH_AlgSHA256;
++ break;
++ case PGPHASHALGO_SHA384:
++ return HASH_AlgSHA384;
++ break;
++ case PGPHASHALGO_SHA512:
++ return HASH_AlgSHA512;
++ break;
++ case PGPHASHALGO_RIPEMD160:
++ case PGPHASHALGO_TIGER192:
++ case PGPHASHALGO_HAVAL_5_160:
++ default:
++ return HASH_AlgNULL;
++ break;
++ }
++}
++
++size_t
++rpmDigestLength(int hashalgo)
++{
++ return HASH_ResultLen(getHashType(hashalgo));
++}
++
++DIGEST_CTX
++rpmDigestInit(int hashalgo, rpmDigestFlags flags)
++{
++ HASH_HashType type;
++ HASHContext *hashctx = NULL;
++ DIGEST_CTX ctx = NULL;
++
++ if (type == HASH_AlgNULL || rpmInitCrypto() < 0)
++ return NULL;
++
++ if ((hashctx = HASH_Create(type)) == NULL)
++ return NULL;
++ ctx = xcalloc(1, sizeof(*ctx));
++ ctx->flags = flags;
++ ctx->algo = hashalgo;
++ ctx->hashctx = hashctx;
++ HASH_Begin(ctx->hashctx);
++
++DPRINTF((stderr, "*** Init(%x) ctx %p hashctx %p\n", flags, ctx, ctx->hashctx));
++ return ctx;
++}
++
++int
++rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
++{
++ size_t partlen;
++ const unsigned char *ptr = data;
++
++ if (ctx == NULL)
++ return -1;
++
++DPRINTF((stderr, "*** Update(%p,%p,%zd) hashctx %p \"%s\"\n", ctx, data, len, ctx->hashctx, ((char *)data)));
++ partlen = ~(unsigned int)0xFF;
++ while (len > 0) {
++ if (len < partlen) {
++ partlen = len;
++ }
++ HASH_Update(ctx->hashctx, ptr, partlen);
++ ptr += partlen;
++ len -= partlen;
++ }
++ return 0;
++}
++
++int
++rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
++{
++ unsigned char * digest;
++ unsigned int digestlen;
++
++ if (ctx == NULL)
++ return -1;
++ digestlen = HASH_ResultLenContext(ctx->hashctx);
++ digest = xmalloc(digestlen);
++
++DPRINTF((stderr, "*** Final(%p,%p,%p,%zd) hashctx %p digest %p\n", ctx, datap, lenp, asAscii, ctx->hashctx, digest));
++/* FIX: check rc */
++ HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
++
++ /* Return final digest. */
++ if (!asAscii) {
++ if (lenp) *lenp = digestlen;
++ if (datap) {
++ *datap = digest;
++ digest = NULL;
++ }
++ } else {
++ if (lenp) *lenp = (2*digestlen) + 1;
++ if (datap) {
++ const uint8_t * s = (const uint8_t *) digest;
++ *datap = pgpHexStr(s, digestlen);
++ }
++ }
++ if (digest) {
++ memset(digest, 0, digestlen); /* In case it's sensitive */
++ free(digest);
++ }
++ HASH_Destroy(ctx->hashctx);
++ memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
++ free(ctx);
++ return 0;
++}
+--- ./rpmio/rpmpgp.c.orig 2011-07-15 09:32:41.000000000 +0000
++++ ./rpmio/rpmpgp.c 2011-07-18 16:42:25.000000000 +0000
+@@ -20,9 +20,6 @@ static int _debug = 0;
+
+ static int _print = 0;
+
+-static int _crypto_initialized = 0;
+-static int _new_process = 1;
+-
+ typedef const struct pgpValTbl_s {
+ int val;
+ char const * const str;
+@@ -315,89 +312,6 @@ int pgpValTok(pgpValTbl vs, const char *
+ } while ((++vs)->val != -1);
+ return vs->val;
+ }
+-/**
+- * @return 0 on success
+- */
+-static int pgpMpiSet(const char * pre, unsigned int lbits,
+- uint8_t *dest, const uint8_t * p, const uint8_t * pend)
+-{
+- unsigned int mbits = pgpMpiBits(p);
+- unsigned int nbits;
+- size_t nbytes;
+- uint8_t *t = dest;
+- unsigned int ix;
+-
+- if ((p + ((mbits+7) >> 3)) > pend)
+- return 1;
+-
+- if (mbits > lbits)
+- return 1;
+-
+- nbits = (lbits > mbits ? lbits : mbits);
+- nbytes = ((nbits + 7) >> 3);
+- ix = (nbits - mbits) >> 3;
+-
+-if (_debug)
+-fprintf(stderr, "*** mbits %u nbits %u nbytes %zu ix %u\n", mbits, nbits, nbytes, ix);
+- if (ix > 0) memset(t, '\0', ix);
+- memcpy(t+ix, p+2, nbytes-ix);
+-if (_debug)
+-fprintf(stderr, "*** %s %s\n", pre, pgpHexStr(dest, nbytes));
+-
+- return 0;
+-}
+-
+-/**
+- * @return NULL on error
+- */
+-static SECItem *pgpMpiItem(PRArenaPool *arena, SECItem *item, const uint8_t *p)
+-{
+- size_t nbytes = pgpMpiLen(p)-2;
+-
+- if (item == NULL) {
+- if ((item=SECITEM_AllocItem(arena, item, nbytes)) == NULL)
+- return item;
+- } else {
+- if (arena != NULL)
+- item->data = PORT_ArenaGrow(arena, item->data, item->len, nbytes);
+- else
+- item->data = PORT_Realloc(item->data, nbytes);
+-
+- if (item->data == NULL) {
+- if (arena == NULL)
+- SECITEM_FreeItem(item, PR_TRUE);
+- return NULL;
+- }
+- }
+-
+- memcpy(item->data, p+2, nbytes);
+- item->len = nbytes;
+- return item;
+-}
+-/*@=boundswrite@*/
+-
+-static SECKEYPublicKey *pgpNewPublicKey(KeyType type)
+-{
+- PRArenaPool *arena;
+- SECKEYPublicKey *key;
+-
+- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+- if (arena == NULL)
+- return NULL;
+-
+- key = PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey));
+-
+- if (key == NULL) {
+- PORT_FreeArena(arena, PR_FALSE);
+- return NULL;
+- }
+-
+- key->keyType = type;
+- key->pkcs11ID = CK_INVALID_HANDLE;
+- key->pkcs11Slot = NULL;
+- key->arena = arena;
+- return key;
+-}
+
+ /** \ingroup rpmpgp
+ * Is buffer at beginning of an OpenPGP packet?
+@@ -593,29 +507,16 @@ static int pgpPrtSigParams(pgpTag tag, u
+ {
+ const uint8_t * pend = h + hlen;
+ size_t i;
+- SECItem dsaraw;
+- unsigned char dsabuf[2*DSA_SUBPRIME_LEN];
+ char *mpi;
+
+- dsaraw.type = 0;
+- dsaraw.data = dsabuf;
+- dsaraw.len = sizeof(dsabuf);
+-
+ for (i = 0; p < pend; i++, p += pgpMpiLen(p)) {
+ if (pubkey_algo == PGPPUBKEYALGO_RSA) {
+ if (i >= 1) break;
+ if (_dig &&
+ (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
+ {
+- switch (i) {
+- case 0: /* m**d */
+- _dig->sigdata = pgpMpiItem(NULL, _dig->sigdata, p);
+- if (_dig->sigdata == NULL)
+- return 1;
+- break;
+- default:
+- break;
+- }
++ if (pgpSetSigMpiRSA(_dig, i, p))
++ return 1;
+ }
+ pgpPrtStr("", pgpSigRSA[i]);
+ } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
+@@ -623,30 +524,8 @@ static int pgpPrtSigParams(pgpTag tag, u
+ if (_dig &&
+ (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT))
+ {
+- int xx;
+- xx = 0;
+- switch (i) {
+- case 0:
+- memset(dsaraw.data, '\0', 2*DSA_SUBPRIME_LEN);
+- /* r */
+- xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data, p, pend);
+- break;
+- case 1: /* s */
+- xx = pgpMpiSet(pgpSigDSA[i], DSA_SUBPRIME_LEN*8, dsaraw.data + DSA_SUBPRIME_LEN, p, pend);
+- if (_dig->sigdata != NULL)
+- SECITEM_FreeItem(_dig->sigdata, PR_FALSE);
+- else if ((_dig->sigdata=SECITEM_AllocItem(NULL, NULL, 0)) == NULL) {
+- xx = 1;
+- break;
+- }
+- if (DSAU_EncodeDerSig(_dig->sigdata, &dsaraw) != SECSuccess)
+- xx = 1;
+- break;
+- default:
+- xx = 1;
+- break;
+- }
+- if (xx) return xx;
++ if (pgpSetSigMpiDSA(_dig, i, p))
++ return 1;
+ }
+ pgpPrtStr("", pgpSigDSA[i]);
+ } else {
+@@ -842,49 +721,11 @@ static const uint8_t * pgpPrtPubkeyParam
+ char * mpi;
+ if (pubkey_algo == PGPPUBKEYALGO_RSA) {
+ if (i >= 2) break;
+- if (_dig) {
+- if (_dig->keydata == NULL) {
+- _dig->keydata = pgpNewPublicKey(rsaKey);
+- if (_dig->keydata == NULL)
+- return NULL;
+- }
+- switch (i) {
+- case 0: /* n */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.modulus, p);
+- break;
+- case 1: /* e */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.rsa.publicExponent, p);
+- break;
+- default:
+- break;
+- }
+- }
++ pgpSetPubMpiRSA(_dig, i, p);
+ pgpPrtStr("", pgpPublicRSA[i]);
+ } else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
+ if (i >= 4) break;
+- if (_dig) {
+- if (_dig->keydata == NULL) {
+- _dig->keydata = pgpNewPublicKey(dsaKey);
+- if (_dig->keydata == NULL)
+- return NULL;
+- }
+- switch (i) {
+- case 0: /* p */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.prime, p);
+- break;
+- case 1: /* q */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.subPrime, p);
+- break;
+- case 2: /* g */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.params.base, p);
+- break;
+- case 3: /* y */
+- pgpMpiItem(_dig->keydata->arena, &_dig->keydata->u.dsa.publicValue, p);
+- break;
+- default:
+- break;
+- }
+- }
++ pgpSetPubMpiDSA(_dig, i, p);
+ pgpPrtStr("", pgpPublicDSA[i]);
+ } else if (pubkey_algo == PGPPUBKEYALGO_ELGAMAL_ENCRYPT) {
+ if (i >= 3) break;
+@@ -1269,15 +1110,7 @@ void pgpCleanDig(pgpDig dig)
+ memset(&dig->signature, 0, sizeof(dig->signature));
+ memset(&dig->pubkey, 0, sizeof(dig->pubkey));
+
+- if (dig->keydata != NULL) {
+- SECKEY_DestroyPublicKey(dig->keydata);
+- dig->keydata = NULL;
+- }
+-
+- if (dig->sigdata != NULL) {
+- SECITEM_ZfreeItem(dig->sigdata, PR_TRUE);
+- dig->sigdata = NULL;
+- }
++ pgpCleanRSADSA(dig);
+ }
+ return;
+ }
+@@ -1319,39 +1152,6 @@ int pgpPrtPkts(const uint8_t * pkts, siz
+ return 0;
+ }
+
+-static SECOidTag getSigAlg(pgpDigParams sigp)
+-{
+- SECOidTag sigalg = SEC_OID_UNKNOWN;
+- if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA) {
+- /* assume SHA1 for now, NSS doesn't have SECOID's for other types */
+- sigalg = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST;
+- } else if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
+- switch (sigp->hash_algo) {
+- case PGPHASHALGO_MD5:
+- sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_MD2:
+- sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA1:
+- sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA256:
+- sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA384:
+- sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
+- break;
+- case PGPHASHALGO_SHA512:
+- sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
+- break;
+- default:
+- break;
+- }
+- }
+- return sigalg;
+-}
+-
+ char *pgpIdentItem(pgpDigParams digp)
+ {
+ char *id = NULL;
+@@ -1409,30 +1209,12 @@ rpmRC pgpVerifySig(pgpDig dig, DIGEST_CT
+ if (dig->keydata == NULL) {
+ res = RPMRC_NOKEY;
+ } else {
+- SECItem digest = { .type = siBuffer, .data = hash, .len = hashlen };
+- SECItem *sig = dig->sigdata;
+-
+- /* Zero-pad RSA signature to expected size if necessary */
+ if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA) {
+- size_t siglen = SECKEY_SignatureLen(dig->keydata);
+- if (siglen > sig->len) {
+- size_t pad = siglen - sig->len;
+- if ((sig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
+- goto exit;
+- }
+- memset(sig->data, 0, pad);
+- memcpy(sig->data+pad, dig->sigdata->data, dig->sigdata->len);
+- }
+- }
+-
+- /* XXX VFY_VerifyDigest() is deprecated in NSS 3.12 */
+- if (VFY_VerifyDigest(&digest, dig->keydata, sig,
+- getSigAlg(sigp), NULL) == SECSuccess) {
+- res = RPMRC_OK;
+- }
+-
+- if (sig != dig->sigdata) {
+- SECITEM_ZfreeItem(sig, 1);
++ if (!pgpVerifyRSA(dig, hash, hashlen))
++ res = RPMRC_OK;
++ } else if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA) {
++ if (!pgpVerifyDSA(dig, hash, hashlen))
++ res = RPMRC_OK;
+ }
+ }
+
+@@ -1620,50 +1402,3 @@ char * pgpArmorWrap(int atype, const uns
+ return val;
+ }
+
+-/*
+- * Only flag for re-initialization here, in the common case the child
+- * exec()'s something else shutting down NSS here would be waste of time.
+- */
+-static void at_forkchild(void)
+-{
+- _new_process = 1;
+-}
+-
+-int rpmInitCrypto(void) {
+- int rc = 0;
+-
+- /* Lazy NSS shutdown for re-initialization after fork() */
+- if (_new_process && _crypto_initialized) {
+- rpmFreeCrypto();
+- }
+-
+- /* Initialize NSS if not already done */
+- if (!_crypto_initialized) {
+- if (NSS_NoDB_Init(NULL) != SECSuccess) {
+- rc = -1;
+- } else {
+- _crypto_initialized = 1;
+- }
+- }
+-
+- /* Register one post-fork handler per process */
+- if (_new_process) {
+- if (pthread_atfork(NULL, NULL, at_forkchild) != 0) {
+- rpmlog(RPMLOG_WARNING, _("Failed to register fork handler: %m\n"));
+- }
+- _new_process = 0;
+- }
+- return rc;
+-}
+-
+-int rpmFreeCrypto(void)
+-{
+- int rc = 0;
+- if (_crypto_initialized) {
+- rc = (NSS_Shutdown() != SECSuccess);
+- _crypto_initialized = 0;
+- }
+- return rc;
+-}
+-
+-