2000-11-01 00:18:34 +08:00
|
|
|
/** \ingroup signature
|
|
|
|
* \file rpmio/digest.c
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "system.h"
|
2008-01-30 23:05:29 +08:00
|
|
|
|
2007-11-23 18:41:29 +08:00
|
|
|
#include "rpmio/digest.h"
|
2008-01-30 23:05:29 +08:00
|
|
|
|
2000-12-13 04:03:45 +08:00
|
|
|
#include "debug.h"
|
2000-11-01 00:18:34 +08:00
|
|
|
|
2001-09-26 22:45:50 +08:00
|
|
|
#ifdef SHA_DEBUG
|
|
|
|
#define DPRINTF(_a) fprintf _a
|
|
|
|
#else
|
|
|
|
#define DPRINTF(_a)
|
|
|
|
#endif
|
2000-11-01 00:18:34 +08:00
|
|
|
|
2001-04-29 09:05:43 +08:00
|
|
|
|
2000-11-01 00:18:34 +08:00
|
|
|
/**
|
|
|
|
* MD5/SHA1 digest private data.
|
|
|
|
*/
|
|
|
|
struct DIGEST_CTX_s {
|
|
|
|
rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
|
2007-11-02 16:02:40 +08:00
|
|
|
HASHContext *hashctx; /*!< Internal NSS hash context. */
|
2009-03-12 00:07:22 +08:00
|
|
|
pgpHashAlgo algo; /*!< Used hash algorithm */
|
2000-11-01 00:18:34 +08:00
|
|
|
};
|
|
|
|
|
2001-10-06 04:39:50 +08:00
|
|
|
DIGEST_CTX
|
|
|
|
rpmDigestDup(DIGEST_CTX octx)
|
|
|
|
{
|
2009-03-16 20:13:00 +08:00
|
|
|
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;
|
|
|
|
}
|
2007-11-02 16:02:40 +08:00
|
|
|
}
|
2001-10-06 04:39:50 +08:00
|
|
|
return nctx;
|
|
|
|
}
|
|
|
|
|
2009-03-12 03:41:57 +08:00
|
|
|
RPM_GNUC_PURE
|
|
|
|
static HASH_HashType getHashType(pgpHashAlgo hashalgo)
|
2000-11-01 00:18:34 +08:00
|
|
|
{
|
2001-10-19 09:35:57 +08:00
|
|
|
switch (hashalgo) {
|
|
|
|
case PGPHASHALGO_MD5:
|
2007-11-02 16:02:40 +08:00
|
|
|
return HASH_AlgMD5;
|
2001-10-19 09:35:57 +08:00
|
|
|
break;
|
2009-03-12 03:41:57 +08:00
|
|
|
case PGPHASHALGO_MD2:
|
|
|
|
return HASH_AlgMD2;
|
|
|
|
break;
|
2001-10-19 09:35:57 +08:00
|
|
|
case PGPHASHALGO_SHA1:
|
2007-11-02 16:02:40 +08:00
|
|
|
return HASH_AlgSHA1;
|
2001-10-19 09:35:57 +08:00
|
|
|
break;
|
2005-03-13 09:15:37 +08:00
|
|
|
case PGPHASHALGO_SHA256:
|
2007-11-02 16:02:40 +08:00
|
|
|
return HASH_AlgSHA256;
|
2005-03-13 09:15:37 +08:00
|
|
|
break;
|
|
|
|
case PGPHASHALGO_SHA384:
|
2007-11-02 16:02:40 +08:00
|
|
|
return HASH_AlgSHA384;
|
2005-03-13 09:15:37 +08:00
|
|
|
break;
|
|
|
|
case PGPHASHALGO_SHA512:
|
2007-11-02 16:02:40 +08:00
|
|
|
return HASH_AlgSHA512;
|
2005-03-13 09:15:37 +08:00
|
|
|
break;
|
2001-10-19 09:35:57 +08:00
|
|
|
case PGPHASHALGO_RIPEMD160:
|
|
|
|
case PGPHASHALGO_TIGER192:
|
|
|
|
case PGPHASHALGO_HAVAL_5_160:
|
|
|
|
default:
|
2007-11-02 16:02:40 +08:00
|
|
|
return HASH_AlgNULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
rpmDigestLength(pgpHashAlgo hashalgo)
|
|
|
|
{
|
|
|
|
return HASH_ResultLen(getHashType(hashalgo));
|
|
|
|
}
|
|
|
|
|
|
|
|
DIGEST_CTX
|
|
|
|
rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
|
|
|
|
{
|
2009-03-11 23:14:25 +08:00
|
|
|
HASH_HashType type = getHashType(hashalgo);
|
|
|
|
HASHContext *hashctx = NULL;
|
|
|
|
DIGEST_CTX ctx = NULL;
|
2007-11-02 16:02:40 +08:00
|
|
|
|
2009-01-08 19:17:22 +08:00
|
|
|
if (rpmInitCrypto() < 0)
|
2009-03-11 23:14:25 +08:00
|
|
|
goto exit;
|
2007-11-02 16:02:40 +08:00
|
|
|
|
|
|
|
type = getHashType(hashalgo);
|
|
|
|
if (type == HASH_AlgNULL) {
|
2009-03-11 23:14:25 +08:00
|
|
|
goto exit;
|
2000-11-01 00:18:34 +08:00
|
|
|
}
|
|
|
|
|
2009-03-11 23:14:25 +08:00
|
|
|
if ((hashctx = HASH_Create(type)) != NULL) {
|
|
|
|
ctx = xcalloc(1, sizeof(*ctx));
|
|
|
|
ctx->flags = flags;
|
2009-03-12 00:07:22 +08:00
|
|
|
ctx->algo = hashalgo;
|
2009-03-11 23:14:25 +08:00
|
|
|
ctx->hashctx = hashctx;
|
|
|
|
HASH_Begin(ctx->hashctx);
|
2007-11-02 16:02:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
DPRINTF((stderr, "*** Init(%x) ctx %p hashctx %p\n", flags, ctx, ctx->hashctx));
|
2009-03-11 23:14:25 +08:00
|
|
|
exit:
|
2000-11-01 00:18:34 +08:00
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
2001-10-19 09:35:57 +08:00
|
|
|
int
|
2000-11-01 00:18:34 +08:00
|
|
|
rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
|
|
|
|
{
|
2008-01-02 20:10:25 +08:00
|
|
|
size_t partlen;
|
2007-11-02 16:02:40 +08:00
|
|
|
const unsigned char *ptr = data;
|
|
|
|
|
2003-04-03 05:16:26 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
return -1;
|
|
|
|
|
2008-01-02 20:10:25 +08:00
|
|
|
DPRINTF((stderr, "*** Update(%p,%p,%zd) hashctx %p \"%s\"\n", ctx, data, len, ctx->hashctx, ((char *)data)));
|
2007-11-02 16:02:40 +08:00
|
|
|
partlen = ~(unsigned int)0xFF;
|
|
|
|
while (len > 0) {
|
|
|
|
if (len < partlen) {
|
2008-01-02 20:10:25 +08:00
|
|
|
partlen = len;
|
2007-11-02 16:02:40 +08:00
|
|
|
}
|
|
|
|
HASH_Update(ctx->hashctx, ptr, partlen);
|
|
|
|
ptr += partlen;
|
|
|
|
len -= partlen;
|
|
|
|
}
|
|
|
|
return 0;
|
2000-11-01 00:18:34 +08:00
|
|
|
}
|
|
|
|
|
2001-10-19 09:35:57 +08:00
|
|
|
int
|
2003-04-03 05:16:26 +08:00
|
|
|
rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
|
2000-11-01 00:18:34 +08:00
|
|
|
{
|
2007-11-02 16:02:40 +08:00
|
|
|
unsigned char * digest;
|
2008-07-12 22:57:51 +08:00
|
|
|
unsigned int digestlen;
|
2000-11-01 00:18:34 +08:00
|
|
|
|
2003-04-03 05:16:26 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
return -1;
|
2007-11-02 16:02:40 +08:00
|
|
|
digestlen = HASH_ResultLenContext(ctx->hashctx);
|
|
|
|
digest = xmalloc(digestlen);
|
2003-04-03 05:16:26 +08:00
|
|
|
|
2008-01-02 20:10:25 +08:00
|
|
|
DPRINTF((stderr, "*** Final(%p,%p,%p,%zd) hashctx %p digest %p\n", ctx, datap, lenp, asAscii, ctx->hashctx, digest));
|
2007-09-11 22:48:54 +08:00
|
|
|
/* FIX: check rc */
|
2008-01-02 20:44:58 +08:00
|
|
|
HASH_End(ctx->hashctx, digest, (unsigned int *) &digestlen, digestlen);
|
2000-11-01 00:18:34 +08:00
|
|
|
|
2001-07-22 03:44:22 +08:00
|
|
|
/* Return final digest. */
|
2000-11-01 00:18:34 +08:00
|
|
|
if (!asAscii) {
|
2007-11-02 16:02:40 +08:00
|
|
|
if (lenp) *lenp = digestlen;
|
2000-11-01 00:18:34 +08:00
|
|
|
if (datap) {
|
2001-09-26 22:45:50 +08:00
|
|
|
*datap = digest;
|
|
|
|
digest = NULL;
|
2000-11-01 00:18:34 +08:00
|
|
|
}
|
|
|
|
} else {
|
2007-11-02 16:02:40 +08:00
|
|
|
if (lenp) *lenp = (2*digestlen) + 1;
|
2000-11-01 00:18:34 +08:00
|
|
|
if (datap) {
|
2007-11-26 17:42:39 +08:00
|
|
|
const uint8_t * s = (const uint8_t *) digest;
|
2008-04-07 19:04:00 +08:00
|
|
|
*datap = pgpHexStr(s, digestlen);
|
2000-11-01 00:18:34 +08:00
|
|
|
}
|
|
|
|
}
|
2001-09-26 22:45:50 +08:00
|
|
|
if (digest) {
|
2007-11-02 16:02:40 +08:00
|
|
|
memset(digest, 0, digestlen); /* In case it's sensitive */
|
2001-09-26 22:45:50 +08:00
|
|
|
free(digest);
|
|
|
|
}
|
2007-11-02 16:02:40 +08:00
|
|
|
HASH_Destroy(ctx->hashctx);
|
2000-11-01 00:18:34 +08:00
|
|
|
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
|
|
|
free(ctx);
|
2001-10-19 09:35:57 +08:00
|
|
|
return 0;
|
2000-11-01 00:18:34 +08:00
|
|
|
}
|
2008-02-27 03:46:38 +08:00
|
|
|
|
|
|
|
void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int flags)
|
|
|
|
{
|
2009-03-12 00:10:19 +08:00
|
|
|
if (fd->ndigests < FDDIGEST_MAX) {
|
|
|
|
fd->digests[fd->ndigests] = rpmDigestInit(hashalgo, flags);
|
2008-02-27 03:46:38 +08:00
|
|
|
fd->ndigests++;
|
|
|
|
fdstat_enter(fd, FDSTAT_DIGEST);
|
|
|
|
fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void fdUpdateDigests(FD_t fd, const unsigned char * buf, size_t buflen)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (buf != NULL && buflen > 0)
|
|
|
|
for (i = fd->ndigests - 1; i >= 0; i--) {
|
2009-03-12 00:10:19 +08:00
|
|
|
DIGEST_CTX ctx = fd->digests[i];
|
|
|
|
if (ctx == NULL)
|
2008-02-27 03:46:38 +08:00
|
|
|
continue;
|
|
|
|
fdstat_enter(fd, FDSTAT_DIGEST);
|
2009-03-12 00:10:19 +08:00
|
|
|
(void) rpmDigestUpdate(ctx, buf, buflen);
|
2008-02-27 03:46:38 +08:00
|
|
|
fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) buflen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo,
|
|
|
|
void ** datap,
|
|
|
|
size_t * lenp,
|
|
|
|
int asAscii)
|
|
|
|
{
|
|
|
|
int imax = -1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = fd->ndigests - 1; i >= 0; i--) {
|
2009-03-12 00:10:19 +08:00
|
|
|
DIGEST_CTX ctx = fd->digests[i];
|
|
|
|
if (ctx == NULL)
|
2008-02-27 03:46:38 +08:00
|
|
|
continue;
|
|
|
|
if (i > imax) imax = i;
|
2009-03-12 00:10:19 +08:00
|
|
|
if (ctx->algo != hashalgo)
|
2008-02-27 03:46:38 +08:00
|
|
|
continue;
|
|
|
|
fdstat_enter(fd, FDSTAT_DIGEST);
|
2009-03-12 00:10:19 +08:00
|
|
|
(void) rpmDigestFinal(ctx, datap, lenp, asAscii);
|
2008-02-27 03:46:38 +08:00
|
|
|
fdstat_exit(fd, FDSTAT_DIGEST, (ssize_t) 0);
|
2009-03-12 00:10:19 +08:00
|
|
|
fd->digests[i] = NULL;
|
2008-02-27 03:46:38 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i < 0) {
|
|
|
|
if (datap) *datap = NULL;
|
|
|
|
if (lenp) *lenp = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd->ndigests = imax;
|
|
|
|
if (i < imax)
|
|
|
|
fd->ndigests++; /* convert index to count */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fdStealDigest(FD_t fd, pgpDig dig)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = fd->ndigests - 1; i >= 0; i--) {
|
2009-03-12 00:10:19 +08:00
|
|
|
DIGEST_CTX ctx = fd->digests[i];
|
|
|
|
if (ctx == NULL)
|
|
|
|
continue;
|
|
|
|
switch (ctx->algo) {
|
2008-02-27 03:46:38 +08:00
|
|
|
case PGPHASHALGO_MD5:
|
|
|
|
assert(dig->md5ctx == NULL);
|
2009-03-12 00:10:19 +08:00
|
|
|
dig->md5ctx = ctx;
|
|
|
|
fd->digests[i] = NULL;
|
2008-02-27 03:46:38 +08:00
|
|
|
break;
|
|
|
|
case PGPHASHALGO_SHA1:
|
|
|
|
case PGPHASHALGO_SHA256:
|
|
|
|
case PGPHASHALGO_SHA384:
|
|
|
|
case PGPHASHALGO_SHA512:
|
|
|
|
assert(dig->sha1ctx == NULL);
|
2009-03-12 00:10:19 +08:00
|
|
|
dig->sha1ctx = ctx;
|
|
|
|
fd->digests[i] = NULL;
|
2008-02-27 03:46:38 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|