--- ./config.h.in.orig 2012-05-22 10:55:46.000000000 +0000 +++ ./config.h.in 2012-05-31 16:41:07.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 header file. */ +#undef HAVE_BEECRYPT_API_H + /* Define to 1 if you have the header file. */ #undef HAVE_BZLIB_H @@ -206,6 +209,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 . */ #undef MAJOR_IN_MKDEV @@ -290,6 +297,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 2012-05-22 10:55:31.000000000 +0000 +++ ./configure.ac 2012-05-31 16:37:32.000000000 +0000 @@ -239,12 +239,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 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 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]) ]) @@ -253,6 +284,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 2012-03-20 08:07:25.000000000 +0000 +++ ./rpmio/Makefile.am 2012-05-31 16:39:58.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,12 +18,18 @@ 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 3:0:0 librpmio_la_LIBADD = \ ../misc/libmisc.la \ @WITH_NSS_LIB@ \ + @WITH_BEECRYPT_LIB@ \ @WITH_BZ2_LIB@ \ @WITH_ZLIB_LIB@ \ @WITH_LIBELF_LIB@ \ @@ -30,6 +37,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/digest_beecrypt.c.orig 2012-05-31 16:42:01.000000000 +0000 +++ ./rpmio/digest_beecrypt.c 2012-05-31 17:33:28.000000000 +0000 @@ -0,0 +1,526 @@ +#include "system.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#if HAVE_BEECRYPT_API_H +#include +#include +#include +#endif + +#include +#include "rpmio/digest.h" +#include "rpmio/rpmio_internal.h" +#include "debug.h" + +/** + * 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); /*!< Digest initialize. */ + int (*Update) (void * param, const byte * data, size_t size); /*!< Digest transform. */ + int (*Digest) (void * param, byte * digest); /*!< Digest finish. */ +}; + + +/**************************** init ************************************/ + +int rpmInitCrypto(void) { + return 0; +} + +int rpmFreeCrypto(void) { + return 0; +} + +/**************************** digest ************************************/ + +DIGEST_CTX rpmDigestDup(DIGEST_CTX octx) +{ + DIGEST_CTX nctx = NULL; + if (octx) { + 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)); + + 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; + } + + (*ctx->Reset)(ctx->param); + return ctx; +} + +int rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len) +{ + if (ctx == NULL) + return -1; + + 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); + + /* 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; +} + +/**************************** helpers ************************************/ + +static inline char * pgpHexCvt(char *t, const byte *s, int nbytes) +{ + 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, const byte *pend) +{ + static char prbuf[2048]; + char *t = prbuf; + int nbytes = pgpMpiLen(p) - 2; + if (nbytes > 1024 || nbytes > pend - (p + 2)) + return NULL; + t = pgpHexCvt(t, p+2, nbytes); + return prbuf; +} + +static int pgpHexSet(int lbits, mpnumber * mpn, const byte * p, const byte * pend) +{ + 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, pend)); + (void) mpnsethex(mpn, t); + t = _free(t); + return 0; +} + +static void pgpFreeSigRSADSA(pgpDigAlg sa) +{ + if (sa->data) + free(sa->data); + sa->data = 0; +} + +static void pgpFreeKeyRSADSA(pgpDigAlg sa) +{ + if (sa->data) + free(sa->data); + sa->data = 0; +} + + +/****************************** RSA **************************************/ + +struct pgpDigSigRSA_s { + mpnumber c; +}; + +struct pgpDigKeyRSA_s { + rsapk rsa_pk; +}; + +static int pgpSetSigMpiRSA(pgpDigAlg pgpsig, int num, + const uint8_t *p, const uint8_t *pend) +{ + struct pgpDigSigRSA_s *sig = pgpsig->data; + int rc = 1; + + switch (num) { + case 0: + sig = pgpsig->data = xcalloc(1, sizeof(*sig)); + (void) mpnsethex(&sig->c, pgpMpiHex(p, pend)); + rc = 0; + break; + } + return rc; +} + +static int pgpSetKeyMpiRSA(pgpDigAlg pgpkey, int num, + const uint8_t *p, const uint8_t *pend) +{ + struct pgpDigKeyRSA_s *key = pgpkey->data; + int rc = 1; + + if (!key) + key = pgpkey->data = xcalloc(1, sizeof(*key)); + switch (num) { + case 0: + (void) mpbsethex(&key->rsa_pk.n, pgpMpiHex(p, pend)); + rc = 0; + break; + case 1: + (void) mpnsethex(&key->rsa_pk.e, pgpMpiHex(p, pend)); + rc = 0; + break; + } + return rc; +} + +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; +} + +static int pgpVerifySigRSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo) +{ + struct pgpDigKeyRSA_s *key = pgpkey->data; + struct pgpDigSigRSA_s *sig = pgpsig->data; + const char * prefix = NULL; + mpnumber rsahm; + int rc = 1; + + if (!sig || !key) + return rc; + + switch (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; + 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 + rc = rsavrfy(&key->rsa_pk.n, &key->rsa_pk.e, &sig->c, &rsahm) == 1 ? 0 : 1; +#else + rc = rsavrfy(&key->rsa_pk, &rsahm, &sig->c) == 1 ? 0 : 1; +#endif + mpnfree(&rsahm); + return rc; +} + + +/****************************** DSA **************************************/ + +struct pgpDigSigDSA_s { + mpnumber r; + mpnumber s; +}; + +struct pgpDigKeyDSA_s { + mpbarrett p; + mpbarrett q; + mpnumber g; + mpnumber y; +}; + +static int pgpSetSigMpiDSA(pgpDigAlg pgpsig, int num, + const uint8_t *p, const uint8_t *pend) +{ + struct pgpDigSigDSA_s *sig = pgpsig->data; + int rc = 1; + + switch (num) { + case 0: + sig = pgpsig->data = xcalloc(1, sizeof(*sig)); + rc = pgpHexSet(160, &sig->r, p, pend); + break; + case 1: + rc = pgpHexSet(160, &sig->s, p, pend); + break; + } + return rc; +} + +static int pgpSetKeyMpiDSA(pgpDigAlg pgpkey, int num, + const uint8_t *p, const uint8_t *pend) +{ + struct pgpDigKeyDSA_s *key = pgpkey->data; + int rc = 1; + + if (!key) + key = pgpkey->data = xcalloc(1, sizeof(*key)); + + switch (num) { + case 0: + mpbsethex(&key->p, pgpMpiHex(p, pend)); + rc = 0; + break; + case 1: + mpbsethex(&key->q, pgpMpiHex(p, pend)); + rc = 0; + break; + case 2: + mpnsethex(&key->g, pgpMpiHex(p, pend)); + rc = 0; + break; + case 3: + mpnsethex(&key->y, pgpMpiHex(p, pend)); + rc = 0; + break; + } + return rc; +} + +static int pgpVerifySigDSA(pgpDigAlg pgpkey, pgpDigAlg pgpsig, uint8_t *hash, size_t hashlen, int hash_algo) +{ + struct pgpDigKeyDSA_s *key = pgpkey->data; + struct pgpDigSigDSA_s *sig = pgpsig->data; + mpnumber hm; + int rc = 1; + + if (sig && key) { + mpnzero(&hm); + mpnsetbin(&hm, hash, hashlen); + rc = dsavrfy(&key->p, &key->q, &key->g, &hm, &key->y, &sig->r, &sig->s) == 1 ? 0 : 1; + mpnfree(&hm); + } + return rc; +} + +static int pgpSetMpiNULL(pgpDigAlg pgpkey, int num, + const uint8_t *p, const uint8_t *pend) +{ + return 1; +} + +static int pgpVerifyNULL(pgpDigAlg pgpkey, pgpDigAlg pgpsig, + uint8_t *hash, size_t hashlen, int hash_algo) +{ + return 1; +} + +pgpDigAlg pgpPubkeyNew(int algo) +{ + pgpDigAlg ka = xcalloc(1, sizeof(*ka));; + + switch (algo) { + case PGPPUBKEYALGO_RSA: + ka->setmpi = pgpSetKeyMpiRSA; + ka->free = pgpFreeKeyRSADSA; + ka->mpis = 2; + break; + case PGPPUBKEYALGO_DSA: + ka->setmpi = pgpSetKeyMpiDSA; + ka->free = pgpFreeKeyRSADSA; + ka->mpis = 4; + break; + default: + ka->setmpi = pgpSetMpiNULL; + ka->mpis = -1; + break; + } + + ka->verify = pgpVerifyNULL; /* keys can't be verified */ + + return ka; +} + +pgpDigAlg pgpSignatureNew(int algo) +{ + pgpDigAlg sa = xcalloc(1, sizeof(*sa)); + + switch (algo) { + case PGPPUBKEYALGO_RSA: + sa->setmpi = pgpSetSigMpiRSA; + sa->free = pgpFreeSigRSADSA; + sa->verify = pgpVerifySigRSA; + sa->mpis = 1; + break; + case PGPPUBKEYALGO_DSA: + sa->setmpi = pgpSetSigMpiDSA; + sa->free = pgpFreeSigRSADSA; + sa->verify = pgpVerifySigDSA; + sa->mpis = 2; + break; + default: + sa->setmpi = pgpSetMpiNULL; + sa->verify = pgpVerifyNULL; + sa->mpis = -1; + break; + } + return sa; +}