diff options
author | jbj <devnull@localhost> | 2000-10-24 13:46:51 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2000-10-24 13:46:51 +0000 |
commit | 3e1e23bf0630949e1ae6d9c9adb4bc606056c75d (patch) | |
tree | 514b50649ddb3d099e6549a8381ec430b5e92867 /rpmio | |
parent | 5a35ed816dc9ef10c3c0951f676779a9e4381207 (diff) | |
download | librpm-tizen-3e1e23bf0630949e1ae6d9c9adb4bc606056c75d.tar.gz librpm-tizen-3e1e23bf0630949e1ae6d9c9adb4bc606056c75d.tar.bz2 librpm-tizen-3e1e23bf0630949e1ae6d9c9adb4bc606056c75d.zip |
- verify MD5 sums of payload files when unpacking archive.
CVS patchset: 4225
CVS date: 2000/10/24 13:46:51
Diffstat (limited to 'rpmio')
-rw-r--r-- | rpmio/Makefile.am | 2 | ||||
-rw-r--r-- | rpmio/md5.c | 322 | ||||
-rw-r--r-- | rpmio/rpmio.c | 18 | ||||
-rw-r--r-- | rpmio/rpmio_internal.h | 35 |
4 files changed, 376 insertions, 1 deletions
diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am index 3756e1eed..09e361ed5 100644 --- a/rpmio/Makefile.am +++ b/rpmio/Makefile.am @@ -10,7 +10,7 @@ pkginc_HEADERS = rpmio.h rpmurl.h rpmmacro.h rpmlog.h rpmmessages.h rpmerr.h noinst_HEADERS = rpmio_internal.h ugid.h lib_LTLIBRARIES = librpmio.la -librpmio_la_SOURCES = rpmrpc.c rpmio.c rpmio_api.c url.c macro.c \ +librpmio_la_SOURCES = rpmrpc.c rpmio.c rpmio_api.c url.c macro.c md5.c \ ugid.c rpmmalloc.c rpmlog.c # XXX Add internal libtool dependence diff --git a/rpmio/md5.c b/rpmio/md5.c new file mode 100644 index 000000000..9a2ac8c1e --- /dev/null +++ b/rpmio/md5.c @@ -0,0 +1,322 @@ +/** \ingroup signature + * \file rpmio/md5hash.c + * + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#include "system.h" + +#include "rpmio_internal.h" + +typedef unsigned int uint32; + +/** + * MD5 private data. + */ +typedef struct MD5Context_s { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; + int doByteReverse; +} * MD5Context; + +static int _ie = 0x44332211; +static union _mendian { int i; char b[4]; } *_endian = (union _mendian *)&_ie; +#define IS_BIG_ENDIAN() (_endian->b[0] == '\x44') +#define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11') + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) + +/** + * The core of the MD5 algorithm. + * This alters an existing MD5 hash to reflect the addition of 16 longwords + * of new data. + */ +static void +MD5Transform(void * private) +{ + MD5Context ctx = (MD5Context) private; + register uint32 * in = (uint32 *)ctx->in; + register uint32 a = ctx->buf[0]; + register uint32 b = ctx->buf[1]; + register uint32 c = ctx->buf[2]; + register uint32 d = ctx->buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + ctx->buf[0] += a; + ctx->buf[1] += b; + ctx->buf[2] += c; + ctx->buf[3] += d; +} + +/* + * Note: this code is harmless on little-endian machines. + */ +static void +byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} + +/** + * Initialize MD5 hash. + * Set bit count to 0 and buffer to mysterious initialization constants. + * @param brokenEndian calculate broken MD5 sum? + * @return MD5 private data + */ +static void * +MD5Init(int brokenEndian) +{ + MD5Context ctx = xcalloc(1, sizeof(*ctx)); + + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; + + if (IS_BIG_ENDIAN()) + ctx->doByteReverse = (brokenEndian ? 0 : 1); + else + ctx->doByteReverse = 0; + return ctx; +} + +/** + * Update context to reflect the concatenation of another buffer full + * of bytes. + * @param private MD5 private data + * @param data next data buffer + * @param len no. bytes of data + */ +static void +MD5Update(void * private, const void * data, size_t len) +{ + MD5Context ctx = (MD5Context) private; + const unsigned char * buf = data; + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in ctx->in */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + if (ctx->doByteReverse) + byteReverse(ctx->in, 16); + MD5Transform(ctx); + buf += t; + len -= t; + } + + /* Process data in 64-byte chunks */ + + for (; len >= 64; buf += 64, len -= 64) { + memcpy(ctx->in, buf, 64); + if (ctx->doByteReverse) + byteReverse(ctx->in, 16); + MD5Transform(ctx); + } + + /* Handle any remaining bytes of data. */ + memcpy(ctx->in, buf, len); +} + +/** + * Return MD5 sum and destroy context. + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + * + * @param private MD5 private data + * @retval datap address of returned MD5 sum + * @retval lenp address of MD5 sum length + * @param asAscii return md5sum as ascii string? + */ +static void +MD5Final(void * private, void ** datap, size_t *lenp, int asAscii) +{ + MD5Context ctx = (MD5Context) private; + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + if (ctx->doByteReverse) + byteReverse(ctx->in, 16); + MD5Transform(ctx); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + if (ctx->doByteReverse) + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx); + if (ctx->doByteReverse) + byteReverse((unsigned char *) ctx->buf, 4); + + if (!asAscii) { + if (lenp) *lenp = 16; + if (datap) { + *datap = xmalloc(16); + memcpy(*datap, ctx->buf, 16); + } + } else { + if (lenp) *lenp = 32+1; + if (datap) { + const unsigned char * s = (const unsigned char *) ctx->buf; + static const char hex[] = "0123456789abcdef"; + char * t; + int i; + + *datap = t = xmalloc(32+1); + + for (i = 0 ; i < 16; i++) { + *t++ = hex[ ((*s >> 4) & 0x0f) ]; + *t++ = hex[ ((*s++ ) & 0x0f) ]; + } + *t = '\0'; + } + } + memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ + free(ctx); +} + +/** + * MD5 transform vectors. + */ +FDHASH_t rpmio_md5hash = { + NULL, MD5Init, MD5Update, MD5Final, MD5Transform +}; diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c index 01c34a3ec..3bc6c5bbf 100644 --- a/rpmio/rpmio.c +++ b/rpmio/rpmio.c @@ -243,6 +243,10 @@ DBGREFS(fd, (stderr, "--> fd %p -- %d %s at %s:%u %s\n", fd, fd->nrefs, msg, fi if (--fd->nrefs > 0) /*@-refcounttrans@*/ return fd; /*@=refcounttrans@*/ if (fd->stats) free(fd->stats); + if (fd->hash) { + if (fd->hash->private) free(fd->hash->private); + free(fd->hash); + } /*@-refcounttrans@*/ free(fd); /*@=refcounttrans@*/ } return NULL; @@ -271,6 +275,7 @@ static inline /*@null@*/ FD_t XfdNew(const char *msg, const char *file, unsigned fd->syserrno = 0; fd->errcookie = NULL; fd->stats = calloc(1, sizeof(FDSTAT_t)); + fd->hash = NULL; gettimeofday(&fd->stats->create, NULL); fd->stats->begin = fd->stats->create; /* structure assignment */ @@ -292,6 +297,8 @@ ssize_t fdRead(void * cookie, /*@out@*/ char * buf, size_t count) { rc = read(fdFileno(fd), buf, (count > fd->bytesRemain ? fd->bytesRemain : count)); fdstat_exit(fd, FDSTAT_READ, rc); + if (fd->hash) fd->hash->Update(fd->hash->private, buf, count); + DBGIO(fd, (stderr, "==>\tfdRead(%p,%p,%ld) rc %ld %s\n", cookie, buf, (long)count, (long)rc, fdbg(fd))); return rc; @@ -303,6 +310,9 @@ ssize_t fdWrite(void * cookie, const char * buf, size_t count) { ssize_t rc; if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */ + + if (fd->hash) fd->hash->Update(fd->hash->private, buf, count); + if (fd->wr_chunked) { char chunksize[20]; sprintf(chunksize, "%x\r\n", (unsigned)count); @@ -1918,6 +1928,7 @@ DBGIO(fd, (stderr, "==>\tgzdRead(%p,%p,%u) rc %lx %s\n", cookie, buf, (unsigned) } } else if (rc >= 0) { fdstat_exit(fd, FDSTAT_READ, rc); + if (fd->hash) fd->hash->Update(fd->hash->private, buf, count); } return rc; } @@ -1928,6 +1939,9 @@ static ssize_t gzdWrite(void * cookie, const char * buf, size_t count) { ssize_t rc; if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */ + + if (fd->hash) fd->hash->Update(fd->hash->private, buf, count); + gzfile = gzdFileno(fd); fdstat_enter(fd, FDSTAT_WRITE); rc = gzwrite(gzfile, (void *)buf, count); @@ -2099,6 +2113,7 @@ static ssize_t bzdRead(void * cookie, /*@out@*/ char * buf, size_t count) { fd->errcookie = bzerror(bzfile, &zerror); } else if (rc >= 0) { fdstat_exit(fd, FDSTAT_READ, rc); + if (fd->hash) fd->hash->Update(fd->hash->private, buf, count); } return rc; } @@ -2109,6 +2124,9 @@ static ssize_t bzdWrite(void * cookie, const char * buf, size_t count) { ssize_t rc; if (fd->bytesRemain == 0) return 0; /* XXX simulate EOF */ + + if (fd->hash) fd->hash->Update(fd->hash->private, buf, count); + bzfile = bzdFileno(fd); fdstat_enter(fd, FDSTAT_WRITE); rc = bzwrite(bzfile, (void *)buf, count); diff --git a/rpmio/rpmio_internal.h b/rpmio/rpmio_internal.h index d39b6ddc0..d4fae9b58 100644 --- a/rpmio/rpmio_internal.h +++ b/rpmio/rpmio_internal.h @@ -48,6 +48,18 @@ typedef struct { } FDSTAT_t; /** \ingroup rpmio + */ +typedef struct { + void * private; + void * (*Init) (int flags); + void (*Update) (void * private, const void * data, size_t len); + void (*Final) (/*@only@*/ void * private, /*@out@*/ void ** datap, /*@out@*/ size_t *lenp, int asAscii); + void (*Transform) (void * private); +} FDHASH_t; + +extern FDHASH_t rpmio_md5hash; + +/** \ingroup rpmio * The FD_t File Handle data structure. */ struct _FD_s { @@ -72,6 +84,7 @@ struct _FD_s { /*@observer@*/ const void *errcookie; /* gzdio/bzdio/ufdio: */ FDSTAT_t *stats; /* I/O statistics */ + FDHASH_t *hash; /* Hash vectors */ int ftpFileDoneNeeded; /* ufdio: (FTP) */ unsigned int firstFree; /* fadio: */ @@ -299,6 +312,28 @@ int ufdClose( /*@only@*/ void * cookie); /*@-refcounttrans@*/ return fd; /*@=refcounttrans@*/ } +/** \ingroup rpmio + */ +/*@unused@*/ static inline void fdInitMD5(FD_t fd) { + fd->hash = xcalloc(1, sizeof(*fd->hash)); + *fd->hash = rpmio_md5hash; /* structure assignment */ + fd->hash->private = (*fd->hash->Init) (0); +} + +/** \ingroup rpmio + */ +/*@unused@*/ static inline void fdFiniMD5(FD_t fd, void **datap, size_t *lenp, int asAscii) { + if (fd->hash == NULL) { + *datap = NULL; + *lenp = 0; + return; + } + (*fd->hash->Final) (fd->hash->private, datap, lenp, asAscii); + fd->hash->private = NULL; + free(fd->hash); + fd->hash = NULL; +} + /*@-shadow@*/ /** \ingroup rpmio */ |