Main Page   Modules   Compound List   File List   Compound Members   File Members   Related Pages  

rpmio/digest.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include "rpmio_internal.h"
00007 #include "debug.h"
00008 
00009 typedef unsigned int uint32;
00010 typedef unsigned char byte;
00011 
00015 struct DIGEST_CTX_s {
00016     rpmDigestFlags flags;       
00017     uint32 digestlen;           
00018     uint32 datalen;             
00019     void (*transform) (DIGEST_CTX); 
00020     int doByteReverse;          
00021     uint32 bits[2];             
00022     uint32 digest[8];           
00023     byte in[64];                
00024 };
00025 
00026 /*
00027  * This code implements SHA-1 as defined in FIPS publication 180-1.
00028  * Based on SHA code originally posted to sci.crypt by Peter Gutmann
00029  * in message <30ajo5$oe8@ccu2.auckland.ac.nz>.
00030  * Modified to test for endianness on creation of SHA objects by AMK.
00031  * Also, the original specification of SHA was found to have a weakness
00032  * by NSA/NIST.  This code implements the fixed version of SHA.
00033  *
00034  * Here's the first paragraph of Peter Gutmann's original posting:
00035  * - The following is my SHA (FIPS 180) code updated to allow use of the "fixed"
00036  * SHA, thanks to Jim Gillogly and an anonymous contributor for the information
00037  * on what's changed in the new version.  The fix is a simple change which
00038  * involves adding a single rotate in the initial expansion function. It is
00039  * unknown whether this is an optimal solution to the problem which was
00040  * discovered in the SHA or whether it's simply a bandaid which fixes the
00041  * problem with a minimum of effort (for example the reengineering of a great
00042  * many Capstone chips).
00043  *
00044  * Copyright (C) 1995, A.M. Kuchling
00045  *
00046  * Distribute and use freely; there are no restrictions on further 
00047  * dissemination and usage except those imposed by the laws of your 
00048  * country of residence.
00049  *
00050  * Adapted to pike and some cleanup by Niels Möller.
00051  * Adapted for rpm use from mhash-0.8.3.
00052  */
00053 
00059 /*#define f1(x,y,z) ( ( x & y ) | ( ~x & z ) )          // Rounds  0-19 */
00060 #define f1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )           /* Rounds  0-19 */
00061 #define f2(x,y,z)   ( x ^ y ^ z )                       /* Rounds 20-39 */
00062 /*#define f3(x,y,z) ( ( x & y ) | ( x & z ) | ( y & z ) ) // Rounds 40-59 */
00063 #define f3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )   /* Rounds 40-59 */
00064 #define f4(x,y,z)   ( x ^ y ^ z )                       /* Rounds 60-79 */
00065 
00069 #define K1  0x5A827999L                                 /* Rounds  0-19 */
00070 #define K2  0x6ED9EBA1L                                 /* Rounds 20-39 */
00071 #define K3  0x8F1BBCDCL                                 /* Rounds 40-59 */
00072 #define K4  0xCA62C1D6L                                 /* Rounds 60-79 */
00073 
00077 #define ROTL(n,X)  ( ( (X) << (n) ) | ( (X) >> ( 32 - (n) ) ) )
00078 
00096 #define expand(W,i) ( W[ i & 15 ] = \
00097                       ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
00098                                  W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )
00099 
00118 #define subRound(a, b, c, d, e, f, k, data) \
00119     ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
00120 
00136 static void
00137 SHA1Transform(DIGEST_CTX ctx)
00138 {
00139     uint32 * in = (uint32 *) ctx->in;
00140     uint32 A, B, C, D, E;     /* Local vars */
00141 
00142     /* Set up first buffer and local data buffer */
00143     A = ctx->digest[0];
00144     B = ctx->digest[1];
00145     C = ctx->digest[2];
00146     D = ctx->digest[3];
00147     E = ctx->digest[4];
00148 
00149     /* Heavy mangling, in 4 sub-rounds of 20 interations each. */
00150     subRound( A, B, C, D, E, f1, K1, in[ 0] );
00151     subRound( E, A, B, C, D, f1, K1, in[ 1] );
00152     subRound( D, E, A, B, C, f1, K1, in[ 2] );
00153     subRound( C, D, E, A, B, f1, K1, in[ 3] );
00154     subRound( B, C, D, E, A, f1, K1, in[ 4] );
00155     subRound( A, B, C, D, E, f1, K1, in[ 5] );
00156     subRound( E, A, B, C, D, f1, K1, in[ 6] );
00157     subRound( D, E, A, B, C, f1, K1, in[ 7] );
00158     subRound( C, D, E, A, B, f1, K1, in[ 8] );
00159     subRound( B, C, D, E, A, f1, K1, in[ 9] );
00160     subRound( A, B, C, D, E, f1, K1, in[10] );
00161     subRound( E, A, B, C, D, f1, K1, in[11] );
00162     subRound( D, E, A, B, C, f1, K1, in[12] );
00163     subRound( C, D, E, A, B, f1, K1, in[13] );
00164     subRound( B, C, D, E, A, f1, K1, in[14] );
00165     subRound( A, B, C, D, E, f1, K1, in[15] );
00166     subRound( E, A, B, C, D, f1, K1, expand( in, 16 ) );
00167     subRound( D, E, A, B, C, f1, K1, expand( in, 17 ) );
00168     subRound( C, D, E, A, B, f1, K1, expand( in, 18 ) );
00169     subRound( B, C, D, E, A, f1, K1, expand( in, 19 ) );
00170 
00171     subRound( A, B, C, D, E, f2, K2, expand( in, 20 ) );
00172     subRound( E, A, B, C, D, f2, K2, expand( in, 21 ) );
00173     subRound( D, E, A, B, C, f2, K2, expand( in, 22 ) );
00174     subRound( C, D, E, A, B, f2, K2, expand( in, 23 ) );
00175     subRound( B, C, D, E, A, f2, K2, expand( in, 24 ) );
00176     subRound( A, B, C, D, E, f2, K2, expand( in, 25 ) );
00177     subRound( E, A, B, C, D, f2, K2, expand( in, 26 ) );
00178     subRound( D, E, A, B, C, f2, K2, expand( in, 27 ) );
00179     subRound( C, D, E, A, B, f2, K2, expand( in, 28 ) );
00180     subRound( B, C, D, E, A, f2, K2, expand( in, 29 ) );
00181     subRound( A, B, C, D, E, f2, K2, expand( in, 30 ) );
00182     subRound( E, A, B, C, D, f2, K2, expand( in, 31 ) );
00183     subRound( D, E, A, B, C, f2, K2, expand( in, 32 ) );
00184     subRound( C, D, E, A, B, f2, K2, expand( in, 33 ) );
00185     subRound( B, C, D, E, A, f2, K2, expand( in, 34 ) );
00186     subRound( A, B, C, D, E, f2, K2, expand( in, 35 ) );
00187     subRound( E, A, B, C, D, f2, K2, expand( in, 36 ) );
00188     subRound( D, E, A, B, C, f2, K2, expand( in, 37 ) );
00189     subRound( C, D, E, A, B, f2, K2, expand( in, 38 ) );
00190     subRound( B, C, D, E, A, f2, K2, expand( in, 39 ) );
00191 
00192     subRound( A, B, C, D, E, f3, K3, expand( in, 40 ) );
00193     subRound( E, A, B, C, D, f3, K3, expand( in, 41 ) );
00194     subRound( D, E, A, B, C, f3, K3, expand( in, 42 ) );
00195     subRound( C, D, E, A, B, f3, K3, expand( in, 43 ) );
00196     subRound( B, C, D, E, A, f3, K3, expand( in, 44 ) );
00197     subRound( A, B, C, D, E, f3, K3, expand( in, 45 ) );
00198     subRound( E, A, B, C, D, f3, K3, expand( in, 46 ) );
00199     subRound( D, E, A, B, C, f3, K3, expand( in, 47 ) );
00200     subRound( C, D, E, A, B, f3, K3, expand( in, 48 ) );
00201     subRound( B, C, D, E, A, f3, K3, expand( in, 49 ) );
00202     subRound( A, B, C, D, E, f3, K3, expand( in, 50 ) );
00203     subRound( E, A, B, C, D, f3, K3, expand( in, 51 ) );
00204     subRound( D, E, A, B, C, f3, K3, expand( in, 52 ) );
00205     subRound( C, D, E, A, B, f3, K3, expand( in, 53 ) );
00206     subRound( B, C, D, E, A, f3, K3, expand( in, 54 ) );
00207     subRound( A, B, C, D, E, f3, K3, expand( in, 55 ) );
00208     subRound( E, A, B, C, D, f3, K3, expand( in, 56 ) );
00209     subRound( D, E, A, B, C, f3, K3, expand( in, 57 ) );
00210     subRound( C, D, E, A, B, f3, K3, expand( in, 58 ) );
00211     subRound( B, C, D, E, A, f3, K3, expand( in, 59 ) );
00212 
00213     subRound( A, B, C, D, E, f4, K4, expand( in, 60 ) );
00214     subRound( E, A, B, C, D, f4, K4, expand( in, 61 ) );
00215     subRound( D, E, A, B, C, f4, K4, expand( in, 62 ) );
00216     subRound( C, D, E, A, B, f4, K4, expand( in, 63 ) );
00217     subRound( B, C, D, E, A, f4, K4, expand( in, 64 ) );
00218     subRound( A, B, C, D, E, f4, K4, expand( in, 65 ) );
00219     subRound( E, A, B, C, D, f4, K4, expand( in, 66 ) );
00220     subRound( D, E, A, B, C, f4, K4, expand( in, 67 ) );
00221     subRound( C, D, E, A, B, f4, K4, expand( in, 68 ) );
00222     subRound( B, C, D, E, A, f4, K4, expand( in, 69 ) );
00223     subRound( A, B, C, D, E, f4, K4, expand( in, 70 ) );
00224     subRound( E, A, B, C, D, f4, K4, expand( in, 71 ) );
00225     subRound( D, E, A, B, C, f4, K4, expand( in, 72 ) );
00226     subRound( C, D, E, A, B, f4, K4, expand( in, 73 ) );
00227     subRound( B, C, D, E, A, f4, K4, expand( in, 74 ) );
00228     subRound( A, B, C, D, E, f4, K4, expand( in, 75 ) );
00229     subRound( E, A, B, C, D, f4, K4, expand( in, 76 ) );
00230     subRound( D, E, A, B, C, f4, K4, expand( in, 77 ) );
00231     subRound( C, D, E, A, B, f4, K4, expand( in, 78 ) );
00232     subRound( B, C, D, E, A, f4, K4, expand( in, 79 ) );
00233 
00234     /* Build message digest */
00235     ctx->digest[0] += A;
00236     ctx->digest[1] += B;
00237     ctx->digest[2] += C;
00238     ctx->digest[3] += D;
00239     ctx->digest[4] += E;
00240 }
00241 
00242 /*
00243  * This code implements the MD5 message-digest algorithm.
00244  * The algorithm is due to Ron Rivest.  This code was
00245  * written by Colin Plumb in 1993, no copyright is claimed.
00246  * This code is in the public domain; do with it what you wish.
00247  *
00248  * Equivalent code is available from RSA Data Security, Inc.
00249  * This code has been tested against that, and is equivalent,
00250  * except that you don't need to include two pages of legalese
00251  * with every copy.
00252  *
00253  * To compute the message digest of a chunk of bytes, declare an
00254  * MD5Context structure, pass it to MD5Init, call MD5Update as
00255  * needed on buffers full of bytes, and then call MD5Final, which
00256  * will fill a supplied 16-byte array with the digest.
00257  */
00258 
00260 /* #define F1(x, y, z) (x & y | ~x & z) */
00261 #define F1(x, y, z) (z ^ (x & (y ^ z)))
00262 #define F2(x, y, z) F1(z, x, y)
00263 #define F3(x, y, z) (x ^ y ^ z)
00264 #define F4(x, y, z) (y ^ (x | ~z))
00265 
00267 #define MD5STEP(f, w, x, y, z, data, s) \
00268         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
00269 
00275 static void
00276 MD5Transform(DIGEST_CTX ctx)
00277 {
00278     register uint32 * in = (uint32 *)ctx->in;
00279     register uint32 a = ctx->digest[0];
00280     register uint32 b = ctx->digest[1];
00281     register uint32 c = ctx->digest[2];
00282     register uint32 d = ctx->digest[3];
00283 
00284     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
00285     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
00286     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
00287     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
00288     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
00289     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
00290     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
00291     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
00292     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
00293     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
00294     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
00295     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
00296     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
00297     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
00298     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
00299     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
00300 
00301     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
00302     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
00303     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
00304     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
00305     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
00306     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
00307     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
00308     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
00309     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
00310     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
00311     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
00312     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
00313     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
00314     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
00315     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
00316     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
00317 
00318     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
00319     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
00320     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
00321     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
00322     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
00323     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
00324     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
00325     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
00326     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
00327     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
00328     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
00329     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
00330     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
00331     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
00332     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
00333     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
00334 
00335     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
00336     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
00337     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
00338     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
00339     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
00340     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
00341     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
00342     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
00343     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
00344     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
00345     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
00346     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
00347     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
00348     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
00349     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
00350     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
00351 
00352     ctx->digest[0] += a;
00353     ctx->digest[1] += b;
00354     ctx->digest[2] += c;
00355     ctx->digest[3] += d;
00356 }
00357 
00358 static int _ie = 0x44332211;
00359 static union _mendian { int i; char b[4]; } *_endian = (union _mendian *)&_ie;
00360 #define IS_BIG_ENDIAN()         (_endian->b[0] == '\x44')
00361 #define IS_LITTLE_ENDIAN()      (_endian->b[0] == '\x11')
00362 
00363 /*
00364  * Reverse bytes for each integer in buffer.
00365  * @param buf           data buffer (uint32 aligned address)
00366  * @param nbytes        no. bytes of data (multiple of sizeof(uint32))
00367  */
00368 static void
00369 byteReverse(byte *buf, unsigned nbytes)
00370 {
00371     unsigned nlongs = nbytes / sizeof(uint32);
00372     uint32 t;
00373     do {
00374         t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
00375             ((unsigned) buf[1] << 8 | buf[0]);
00376         *(uint32 *) buf = t;
00377         buf += 4;
00378     } while (--nlongs);
00379 }
00380 
00381 DIGEST_CTX
00382 rpmDigestInit(rpmDigestFlags flags)
00383 {
00384     DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
00385 
00386     ctx->flags = flags;
00387 
00388     if (flags & RPMDIGEST_MD5) {
00389         ctx->digestlen = 16;
00390         ctx->datalen = 64;
00391         ctx->transform = MD5Transform;
00392         ctx->digest[0] = 0x67452301;
00393         ctx->digest[1] = 0xefcdab89;
00394         ctx->digest[2] = 0x98badcfe;
00395         ctx->digest[3] = 0x10325476;
00396     }
00397 
00398     if (flags & RPMDIGEST_SHA1) {
00399         ctx->digestlen = 20;
00400         ctx->datalen = 64;
00401         ctx->transform = SHA1Transform;
00402         ctx->digest[ 0 ] = 0x67452301;
00403         ctx->digest[ 1 ] = 0xefcdab89;
00404         ctx->digest[ 2 ] = 0x98badcfe;
00405         ctx->digest[ 3 ] = 0x10325476;
00406         ctx->digest[ 4 ] = 0xc3d2e1f0;
00407     }
00408 
00409     /* md5 sums are little endian (no swap) so big endian needs the swap. */
00410     ctx->doByteReverse = (IS_BIG_ENDIAN()) ? 1 : 0;
00411     if (flags & RPMDIGEST_NATIVE)
00412         ctx->doByteReverse = 0;
00413 
00414     ctx->bits[0] = 0;
00415     ctx->bits[1] = 0;
00416 
00417     return ctx;
00418 }
00419 
00420 void
00421 rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
00422 {
00423     const byte * buf = data;
00424     uint32 t;
00425 
00426     /* Update bitcount */
00427 
00428     t = ctx->bits[0];
00429     if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
00430         ctx->bits[1]++;         /* Carry from low to high */
00431     ctx->bits[1] += len >> 29;
00432 
00433     t = (t >> 3) % ctx->datalen;        /* Bytes already in ctx->in */
00434 
00435     /* Handle any leading odd-sized chunks */
00436     if (t) {
00437         byte *p = (byte *) ctx->in + t;
00438 
00439         t = ctx->datalen - t;   /* Bytes left in ctx->in */
00440         if (len < t) {
00441             memcpy(p, buf, len);
00442             return;
00443         }
00444         memcpy(p, buf, t);
00445         if (ctx->doByteReverse)
00446             byteReverse(ctx->in, ctx->datalen);
00447         ctx->transform(ctx);
00448         buf += t;
00449         len -= t;
00450     }
00451 
00452     /* Process data in ctx->datalen chunks */
00453     for (; len >= ctx->datalen; buf += ctx->datalen, len -= ctx->datalen) {
00454         memcpy(ctx->in, buf, ctx->datalen);
00455         if (ctx->doByteReverse)
00456             byteReverse(ctx->in, ctx->datalen);
00457         ctx->transform(ctx);
00458     }
00459 
00460     /* Handle any remaining bytes of data. */
00461     memcpy(ctx->in, buf, len);
00462 }
00463 
00464 void
00465 rpmDigestFinal(/*@only@*/ DIGEST_CTX ctx, /*@out@*/ void ** datap,
00466         /*@out@*/ size_t *lenp, int asAscii)
00467 {
00468     unsigned count = (ctx->bits[0] >> 3) % ctx->datalen;
00469     byte * p = ctx->in + count;
00470 
00471     /* Set the first char of padding to 0x80.  This is safe since there is
00472        always at least one byte free */
00473     *p++ = 0x80;
00474 
00475     /* No. bytes of padding needed to fill buffer. */
00476     count = ctx->datalen - 1 - count;
00477 
00478     /* Insure that next block has room for no. of plaintext bits. */
00479     if (count < sizeof(ctx->bits)) {
00480         memset(p, 0, count);
00481         if (ctx->doByteReverse)
00482             byteReverse(ctx->in, ctx->datalen);
00483         ctx->transform(ctx);
00484         p = ctx->in;
00485         count = ctx->datalen;
00486     }
00487 
00488     /* Pad next block with zeroes, add no. of plaintext bits. */
00489     memset(p, 0, count - sizeof(ctx->bits));
00490     if (ctx->doByteReverse)
00491         byteReverse(ctx->in, ctx->datalen - sizeof(ctx->bits));
00492     ((uint32 *) ctx->in)[14] = ctx->bits[0];
00493     ((uint32 *) ctx->in)[15] = ctx->bits[1];
00494     ctx->transform(ctx);
00495 
00496     /* Return final digest. */
00497     if (ctx->doByteReverse)
00498         byteReverse((byte *) ctx->digest, ctx->digestlen);
00499 
00500     if (!asAscii) {
00501         if (lenp) *lenp = ctx->digestlen;
00502         if (datap) {
00503             *datap = xmalloc(ctx->digestlen);
00504             memcpy(*datap, ctx->digest, ctx->digestlen);
00505         }
00506     } else {
00507         if (lenp) *lenp = (2*ctx->digestlen) + 1;
00508         if (datap) {
00509             const byte * s = (const byte *) ctx->digest;
00510             static const char hex[] = "0123456789abcdef";
00511             char * t;
00512             int i;
00513 
00514             *datap = t = xmalloc((2*ctx->digestlen) + 1);
00515 
00516             for (i = 0 ; i < ctx->digestlen; i++) {
00517                 *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
00518                 *t++ = hex[ (unsigned)((*s++   ) & 0x0f) ];
00519             }
00520             *t = '\0';
00521         }
00522     }
00523     memset(ctx, 0, sizeof(*ctx));       /* In case it's sensitive */
00524     free(ctx);
00525 }

Generated at Sun Apr 8 18:43:01 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000