A new user interface for you! Read more...

File rpm-beecrypt.diff of Package rpm

--- ./Makefile.am.orig	2009-06-23 11:40:57.000000000 +0000
+++ ./Makefile.am	2009-08-20 13:47:03.000000000 +0000
@@ -88,7 +88,8 @@ DISTCLEANFILES += find-requires
 
 rpm_SOURCES =		rpmqv.c debug.h system.h
 rpm_CPPFLAGS =		$(AM_CPPFLAGS) -DIAM_RPMDB -DIAM_RPMEIU -DIAM_RPMK -DIAM_RPMQV
-rpm_LDADD =		build/librpmbuild.la lib/librpm.la rpmio/librpmio.la
+rpm_LDADD =		lib/librpm.la rpmio/librpmio.la
+rpm_LDADD +=		build/.libs/spec.o build/.libs/misc.o build/.libs/names.o build/.libs/expression.o build/.libs/reqprov.o build/.libs/poptBT.o build/.libs/parse*.o
 rpm_LDADD +=		@WITH_LIBELF_LIB@ @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@
 
 rpmbuild_SOURCES =	build.c rpmqv.c build.h debug.h system.h
--- ./config.h.in.orig	2009-07-21 08:21:37.000000000 +0000
+++ ./config.h.in	2009-08-20 13:47:03.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
 
@@ -110,7 +113,7 @@
 /* Define as 1 if <netdb.h> defines h_errno */
 #undef HAVE_HERRNO
 
-/* 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 `inet_aton' function. */
@@ -359,6 +362,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
@@ -456,6 +463,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	2009-07-21 08:20:46.000000000 +0000
+++ ./configure.ac	2009-08-20 13:47:03.000000000 +0000
@@ -300,12 +300,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])
 ])
@@ -314,6 +345,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)
 
--- ./lib/signature.c.orig	2009-06-23 11:40:58.000000000 +0000
+++ ./lib/signature.c	2009-08-20 13:47:03.000000000 +0000
@@ -1118,10 +1118,8 @@ verifyRSASignature(rpmKeyring keyring, r
 		DIGEST_CTX md5ctx)
 {
     pgpDigParams sigp = dig ? &dig->signature : NULL;
-    SECOidTag sigalg;
     rpmRC res = RPMRC_OK;
     int xx;
-    SECItem digest;
     const char *hdr, *signame = _("Unknown");;
     const char *sig = sigtd->data;
     int sigver;
@@ -1153,27 +1151,21 @@ verifyRSASignature(rpmKeyring keyring, r
     switch (sigp->hash_algo) {
     case PGPHASHALGO_MD5:
 	signame = "RSA/MD5";
-	sigalg = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
 	break;
     case PGPHASHALGO_SHA1:
 	signame = "RSA/SHA1";
-	sigalg = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
 	break;
     case PGPHASHALGO_MD2:
 	signame = "RSA/MD2";
-	sigalg = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
 	break;
     case PGPHASHALGO_SHA256:
 	signame = "RSA/SHA256";
-	sigalg = SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
 	break;
     case PGPHASHALGO_SHA384:
 	signame = "RSA/SHA384";
-	sigalg = SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
 	break;
     case PGPHASHALGO_SHA512:
 	signame = "RSA/SHA512";
-	sigalg = SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
 	break;
     /* fallthrough for unsupported / unknown types */
     case PGPHASHALGO_TIGER192:
@@ -1181,7 +1173,6 @@ verifyRSASignature(rpmKeyring keyring, r
     case PGPHASHALGO_RIPEMD160:
     default:
 	res = RPMRC_NOKEY;
-	sigalg = SEC_OID_UNKNOWN;
 	break;
     }
 
@@ -1212,9 +1203,6 @@ verifyRSASignature(rpmKeyring keyring, r
 	    res = RPMRC_FAIL;
 	    goto exit;
 	}
-	digest.type = siBuffer;
-	digest.data = dig->md5;
-	digest.len = dig->md5len;
     }
 
     /* Retrieve the matching public key. */
@@ -1222,29 +1210,8 @@ verifyRSASignature(rpmKeyring keyring, r
     if (res != RPMRC_OK)
 	goto exit;
 
-    {	SECItem *sig = dig->rsasig;
-	size_t siglen = SECKEY_SignatureLen(dig->rsa);
-
-	/* Zero-pad signature data up to expected size if necessary */
-	if (siglen > sig->len) {
-	    size_t pad = siglen - sig->len;
-	    if ((sig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
-		res = RPMRC_FAIL;
-		goto exit;
-	    }
-	    memset(sig->data, 0, pad);
-	    memcpy(sig->data+pad, dig->rsasig->data, dig->rsasig->len);
-	}
-	    
-	if (VFY_VerifyDigest(&digest, dig->rsa, sig, sigalg, NULL) == SECSuccess)
-	    res = RPMRC_OK;
-	else
-	    res = RPMRC_FAIL;
-
-	if (sig != dig->rsasig) {
-	    SECITEM_ZfreeItem(sig, 1);
-	}
-    }
+    if (pgpVerifyRSA(dig))
+	res = RPMRC_FAIL;
 
 exit:
     if (sigp != NULL) {
@@ -1273,7 +1240,6 @@ verifyDSASignature(rpmKeyring keyring, r
     pgpDigParams sigp = dig ? &dig->signature : NULL;
     rpmRC res;
     int xx;
-    SECItem digest;
     const char *hdr;
     int sigver;
     const char *sig = sigtd->data;
@@ -1320,9 +1286,6 @@ verifyDSASignature(rpmKeyring keyring, r
 	    res = RPMRC_FAIL;
 	    goto exit;
 	}
-	digest.type = siBuffer;
-	digest.data = dig->sha1;
-	digest.len = dig->sha1len;
     }
 
     /* Retrieve the matching public key. */
@@ -1330,10 +1293,7 @@ verifyDSASignature(rpmKeyring keyring, r
     if (res != RPMRC_OK)
 	goto exit;
 
-    if (VFY_VerifyDigest(&digest, dig->dsa, dig->dsasig,
-    		SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, NULL) == SECSuccess)
-	res = RPMRC_OK;
-    else
+    if (pgpVerifyDSA(dig))
 	res = RPMRC_FAIL;
 
 exit:
--- ./rpmio/Makefile.am.orig	2009-06-23 11:40:59.000000000 +0000
+++ ./rpmio/Makefile.am	2009-08-20 13:47:03.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_LUA_INCLUDE@
 AM_CPPFLAGS += @WITH_POPT_INCLUDE@
 AM_CPPFLAGS += -I$(top_srcdir)/misc
@@ -19,10 +20,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 0:0:0
 librpmio_la_LIBADD = \
 	../misc/libmisc.la \
 	@WITH_NSS_LIB@ \
+	@WITH_BEECRYPT_LIB@ \
 	@WITH_LUA_LIB@ \
 	@WITH_BZ2_LIB@ \
 	@WITH_ZLIB_LIB@ \
@@ -31,6 +39,17 @@ 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_LUAEXT
 AM_CPPFLAGS += -I$(top_builddir)/luaext/
 librpmio_la_LIBADD += $(top_builddir)/luaext/libluaext.la
--- ./rpmio/base64.c.orig	2009-06-23 11:40:59.000000000 +0000
+++ ./rpmio/base64.c	2009-08-20 13:47:03.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	2009-06-23 11:40:59.000000000 +0000
+++ ./rpmio/digest.c	2009-08-20 13:47:03.000000000 +0000
@@ -4,165 +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. */
-};
-
-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(pgpHashAlgo 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(pgpHashAlgo hashalgo)
-{
-    return HASH_ResultLen(getHashType(hashalgo));
-}
-
-DIGEST_CTX
-rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
-{
-    HASH_HashType type;
-    DIGEST_CTX ctx;
-
-    if (rpmInitCrypto() < 0)
-	return NULL;
-
-    ctx = xcalloc(1, sizeof(*ctx));
-    ctx->flags = flags;
-
-    type = getHashType(hashalgo);
-    if (type == HASH_AlgNULL) {
-	free(ctx);
-	return NULL;
-    }
-
-    ctx->hashctx = HASH_Create(type);
-    if (ctx->hashctx == NULL) {
-    	free(ctx);
-    	return NULL;
-    }
-
-    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;
-}
 
 void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int flags)
 {
--- ./rpmio/digest.h.orig	2009-06-23 11:40:59.000000000 +0000
+++ ./rpmio/digest.h	2009-08-20 13:47:03.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"
 #include "rpmio/rpmio_internal.h"
@@ -55,12 +50,22 @@ struct pgpDig_s {
     size_t md5len;		/*!< (rsa) V3 signature hash length. */
 
     /* DSA parameters */
-    SECKEYPublicKey *dsa;
-    SECItem *dsasig;
+    void *dsa;
+    void *dsasig;
 
     /* RSA parameters */
-    SECKEYPublicKey *rsa;
-    SECItem *rsasig;
+    void *rsa;
+    void *rsasig;
 };
 
+int pgpSetSigMpiRSA(pgpDig dig, int num, const uint8_t *p);
+int pgpSetPubMpiRSA(pgpDig dig, int num, const uint8_t *p);
+void pgpCleanRSA(pgpDig dig);
+int pgpVerifyRSA(pgpDig dig);
+
+int pgpSetSigMpiDSA(pgpDig dig, int num, const uint8_t *p);
+int pgpSetPubMpiDSA(pgpDig dig, int num, const uint8_t *p);
+void pgpCleanDSA(pgpDig dig);
+int pgpVerifyDSA(pgpDig dig);
+
 #endif /* _RPMDIGEST_H */
--- ./rpmio/digest_beecrypt.c.orig	2009-08-20 13:47:03.000000000 +0000
+++ ./rpmio/digest_beecrypt.c	2009-08-20 13:47:03.000000000 +0000
@@ -0,0 +1,503 @@
+#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;
+}
+
+
+/****************************** 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->rsasig)
+	dig->rsasig = xcalloc(1, sizeof(*sig));
+    sig = dig->rsasig;
+    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->rsa)
+	dig->rsa = xcalloc(1, sizeof(*pub));
+    pub = dig->rsa;
+    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;
+    }
+}
+
+void pgpCleanRSA(pgpDig dig)
+{
+    if (!dig)
+	return;
+    if (dig->rsa) {
+	dig->rsa = _free(dig->rsa);
+    }
+    if (dig->rsasig) {
+	dig->rsasig = _free(dig->rsasig);
+    }
+}
+
+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)
+{
+    const char * prefix = NULL;
+    int res;
+    mpnumber rsahm;
+    struct pgpDigSigRSA_s *sig;
+    struct pgpDigPubRSA_s *pub;
+
+    sig = dig->rsasig;
+    pub = dig->rsa;
+    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 - dig->md5len - 1;
+	if (bp < buf)
+	    return 1;
+	*bp++ = 0;
+	for (; *prefix; prefix += 2)
+	    *bp++ = (nibble(prefix[0]) << 4) | nibble(prefix[1]);
+	memcpy(bp, dig->md5, dig->md5len);
+        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->dsasig)
+	dig->dsasig = xcalloc(1, sizeof(*sig));
+    sig = dig->dsasig;
+    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->dsa)
+	dig->dsa = xcalloc(1, sizeof(*pub));
+    pub = dig->dsa;
+    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;
+    }
+}
+
+void pgpCleanDSA(pgpDig dig)
+{
+    if (!dig)
+	return;
+    if (dig->dsa) {
+	dig->dsa = _free(dig->dsa);
+    }
+    if (dig->dsasig) {
+	dig->dsasig = _free(dig->dsasig);
+    }
+}
+
+int pgpVerifyDSA(pgpDig dig)
+{
+    struct pgpDigSigDSA_s *sig;
+    struct pgpDigPubDSA_s *pub;
+    mpnumber hm;
+    int res;
+
+    sig = dig->dsasig;
+    pub = dig->dsa;
+    if (!sig || !pub)
+	return 1;
+    mpnzero(&hm);
+    mpnsetbin(&hm, dig->sha1, dig->sha1len);
+    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. */
+    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(pgpHashAlgo 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(pgpHashAlgo hashalgo, rpmDigestFlags flags)
+{
+    DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
+    int xx;
+
+    ctx->flags = flags;
+
+    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	2009-08-20 13:47:03.000000000 +0000
+++ ./rpmio/digest_nss.c	2009-08-20 13:49:53.000000000 +0000
@@ -0,0 +1,513 @@
+#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;
+}
+
+/****************************** 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->rsasig;
+    sig = pgpMpiItem(NULL, sig, p);
+    dig->rsasig = 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->rsa)
+	dig->rsa = pgpNewPublicKey(rsaKey);
+    pub = dig->rsa;
+    if (!pub)
+	return 1;
+    switch(num) {
+    case 0:
+	pgpMpiItem(dig->rsa->arena, &pub->u.rsa.modulus, p);
+	return 0;
+    case 1:
+	pgpMpiItem(dig->rsa->arena, &pub->u.rsa.publicExponent, p);
+	return 0;
+    default:
+	return 1;
+    }
+}
+
+void pgpCleanRSA(pgpDig dig)
+{
+    if (!dig)
+	return;
+    if (dig->rsa) {
+	SECKEY_DestroyPublicKey(dig->rsa);
+	dig->rsa = NULL;
+    }
+    if (dig->rsasig) {
+	SECITEM_ZfreeItem(dig->rsasig, PR_TRUE);
+	dig->rsasig = NULL;
+    }
+}
+
+int pgpVerifyRSA(pgpDig dig)
+{
+    SECOidTag sigalg;
+    SECItem digest;
+    SECItem *sig;
+    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 = dig->md5;
+    digest.len = dig->md5len;
+
+    sig = dig->rsasig;
+    siglen = SECKEY_SignatureLen(dig->rsa);
+
+    /* Zero-pad signature data up to expected size if necessary */
+    if (siglen > sig->len) {
+	size_t pad = siglen - sig->len;
+	if ((sig = SECITEM_AllocItem(NULL, NULL, siglen)) == NULL) {
+	    return 1;
+	}
+	memset(sig->data, 0, pad);
+	memcpy(sig->data+pad, dig->rsasig->data, dig->rsasig->len);
+    }
+
+    if (VFY_VerifyDigest(&digest, dig->rsa, sig, sigalg, NULL) == SECSuccess)
+	res = 0;
+    else
+	res = 1;
+
+    if (sig != dig->rsasig) {
+	SECITEM_ZfreeItem(sig, 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->dsasig = sig;
+	memset(sig->data, 0, 2*DSA_SUBPRIME_LEN);
+	pgpMpiSet(DSA_SUBPRIME_LEN*8, sig->data, p, pend);
+	return 0;
+    case 1:
+	sig = dig->dsasig;
+	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->dsasig = 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->dsa)
+	dig->dsa = pgpNewPublicKey(dsaKey);
+    pub = dig->dsa;
+    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;
+    }
+}
+
+void pgpCleanDSA(pgpDig dig)
+{
+    if (!dig)
+	return;
+    if (dig->dsa) {
+	SECKEY_DestroyPublicKey(dig->dsa);
+	dig->dsa = NULL;
+    }
+    if (dig->dsasig) {
+	SECITEM_ZfreeItem(dig->dsasig, PR_TRUE);
+	dig->dsasig = NULL;
+    }
+}
+
+int pgpVerifyDSA(pgpDig dig)
+{
+    SECItem digest;
+
+    digest.type = siBuffer;
+    digest.data = dig->sha1;
+    digest.len = dig->sha1len;
+    if (VFY_VerifyDigest(&digest, dig->dsa, dig->dsasig, 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. */
+};
+
+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(pgpHashAlgo 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(pgpHashAlgo hashalgo)
+{
+    return HASH_ResultLen(getHashType(hashalgo));
+}
+
+DIGEST_CTX
+rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
+{
+    HASH_HashType type;
+    DIGEST_CTX ctx;
+
+    if (rpmInitCrypto() < 0)
+	return NULL;
+
+    ctx = xcalloc(1, sizeof(*ctx));
+    ctx->flags = flags;
+
+    type = getHashType(hashalgo);
+    if (type == HASH_AlgNULL) {
+	free(ctx);
+	return NULL;
+    }
+
+    ctx->hashctx = HASH_Create(type);
+    if (ctx->hashctx == NULL) {
+    	free(ctx);
+    	return NULL;
+    }
+
+    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	2009-06-23 11:40:59.000000000 +0000
+++ ./rpmio/rpmpgp.c	2009-08-20 13:50:14.000000000 +0000
@@ -20,9 +20,6 @@ static int _debug = 0;
 
 static int _print = 0;
 
-static int _crypto_initialized = 0;
-static int _new_process = 1;
-
 static struct pgpValTbl_s const pgpSigTypeTbl[] = {
     { PGPSIGTYPE_BINARY,	"Binary document signature" },
     { PGPSIGTYPE_TEXT,		"Text document signature" },
@@ -291,99 +288,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,
-		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 (_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;
-}
-
-static SECKEYPublicKey *pgpNewRSAKey(void)
-{
-    return pgpNewPublicKey(rsaKey);
-}
-
-static SECKEYPublicKey *pgpNewDSAKey(void)
-{
-    return pgpNewPublicKey(dsaKey);
-}
 
 /** \ingroup rpmpgp
  * Is buffer at beginning of an OpenPGP packet?
@@ -579,29 +483,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->rsasig = pgpMpiItem(NULL, _dig->rsasig, p);
-		    if (_dig->rsasig == NULL)
-			return 1;
-		    break;
-		default:
-		    break;
-		}
+		if (pgpSetSigMpiRSA(_dig, i, p))
+		    return 1;
 	    }
 	    pgpPrtStr("", pgpSigRSA[i]);
 	} else if (pubkey_algo == PGPPUBKEYALGO_DSA) {
@@ -609,30 +500,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->dsasig != NULL)
-		    	SECITEM_FreeItem(_dig->dsasig, PR_FALSE);
-		    else if ((_dig->dsasig=SECITEM_AllocItem(NULL, NULL, 0)) == NULL) {
-		        xx = 1;
-		        break;
-		    }
-		    if (DSAU_EncodeDerSig(_dig->dsasig, &dsaraw) != SECSuccess)
-		    	xx = 1;
-		    break;
-		default:
-		    xx = 1;
-		    break;
-		}
-		if (xx) return xx;
+		if (pgpSetSigMpiDSA(_dig, i, p))
+		    return 1;
 	    }
 	    pgpPrtStr("", pgpSigDSA[i]);
 	} else {
@@ -824,49 +693,11 @@ static const uint8_t * pgpPrtPubkeyParam
 	char * mpi;
 	if (pubkey_algo == PGPPUBKEYALGO_RSA) {
 	    if (i >= 2) break;
-	    if (_dig) {
-		if (_dig->rsa == NULL) {
-		    _dig->rsa = pgpNewRSAKey();
-		    if (_dig->rsa == NULL)
-			break; /* error abort? */
-		}
-		switch (i) {
-		case 0:		/* n */
-		    pgpMpiItem(_dig->rsa->arena, &_dig->rsa->u.rsa.modulus, p);
-		    break;
-		case 1:		/* e */
-		    pgpMpiItem(_dig->rsa->arena, &_dig->rsa->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->dsa == NULL) {
-		    _dig->dsa = pgpNewDSAKey();
-		    if (_dig->dsa == NULL)
-			break; /* error abort? */
-		}
-		switch (i) {
-		case 0:		/* p */
-		    pgpMpiItem(_dig->dsa->arena, &_dig->dsa->u.dsa.params.prime, p);
-		    break;
-		case 1:		/* q */
-		    pgpMpiItem(_dig->dsa->arena, &_dig->dsa->u.dsa.params.subPrime, p);
-		    break;
-		case 2:		/* g */
-		    pgpMpiItem(_dig->dsa->arena, &_dig->dsa->u.dsa.params.base, p);
-		    break;
-		case 3:		/* y */
-		    pgpMpiItem(_dig->dsa->arena, &_dig->dsa->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;
@@ -1256,25 +1087,8 @@ void pgpCleanDig(pgpDig dig)
 	dig->md5 = _free(dig->md5);
 	dig->sha1 = _free(dig->sha1);
 
-	if (dig->dsa != NULL) {
-	    SECKEY_DestroyPublicKey(dig->dsa);
-	    dig->dsa = NULL;
-	}
-
-	if (dig->dsasig != NULL) {
-	    SECITEM_ZfreeItem(dig->dsasig, PR_TRUE);
-	    dig->dsasig = NULL;
-	}
-
-	if (dig->rsa != NULL) {
-	    SECKEY_DestroyPublicKey(dig->rsa);
-	    dig->rsa = NULL;
-	}
-
-	if (dig->rsasig != NULL) {
-	    SECITEM_ZfreeItem(dig->rsasig, PR_TRUE);
-	    dig->rsasig = NULL;
-	}
+	pgpCleanRSA(dig);
+	pgpCleanDSA(dig);
 
     }
     return;
@@ -1501,50 +1315,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;
-}
-	
-