00001
00005 #include "system.h"
00006 #include "rpmio_internal.h"
00007 #include "beecrypt.h"
00008 #include "md5.h"
00009 #include "endianness.h"
00010 #include "fips180.h"
00011 #include "debug.h"
00012
00013 #ifdef SHA_DEBUG
00014 #define DPRINTF(_a) fprintf _a
00015 #else
00016 #define DPRINTF(_a)
00017 #endif
00018
00019
00020
00024 struct DIGEST_CTX_s {
00025 rpmDigestFlags flags;
00026 uint32 datalen;
00027 uint32 paramlen;
00028 uint32 digestlen;
00029 void * param;
00030 int (*Reset) (void * param)
00031 ;
00032 int (*Update) (void * param, const byte * data, int len)
00033 ;
00034 int (*Digest) (void * param, uint32 * digest)
00035 ;
00036 };
00037
00038 DIGEST_CTX
00039 rpmDigestDup(DIGEST_CTX octx)
00040 {
00041 DIGEST_CTX nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
00042 nctx->param = memcpy(xcalloc(1, nctx->paramlen), octx->param, nctx->paramlen);
00043 return nctx;
00044 }
00045
00046 DIGEST_CTX
00047 rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
00048 {
00049 DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
00050 int xx;
00051
00052 ctx->flags = flags;
00053
00054 switch (hashalgo) {
00055 case PGPHASHALGO_MD5:
00056 ctx->digestlen = 16;
00057 ctx->datalen = 64;
00058
00059 ctx->paramlen = sizeof(md5Param);
00060
00061 ctx->param = xcalloc(1, ctx->paramlen);
00062
00063 ctx->Reset = (void *) md5Reset;
00064 ctx->Update = (void *) md5Update;
00065 ctx->Digest = (void *) md5Digest;
00066
00067 break;
00068 case PGPHASHALGO_SHA1:
00069 ctx->digestlen = 20;
00070 ctx->datalen = 64;
00071
00072 ctx->paramlen = sizeof(sha1Param);
00073
00074 ctx->param = xcalloc(1, ctx->paramlen);
00075
00076 ctx->Reset = (void *) sha1Reset;
00077 ctx->Update = (void *) sha1Update;
00078 ctx->Digest = (void *) sha1Digest;
00079
00080 break;
00081 case PGPHASHALGO_RIPEMD160:
00082 case PGPHASHALGO_MD2:
00083 case PGPHASHALGO_TIGER192:
00084 case PGPHASHALGO_HAVAL_5_160:
00085 default:
00086 free(ctx);
00087 return NULL;
00088 break;
00089 }
00090
00091 xx = (*ctx->Reset) (ctx->param);
00092
00093 DPRINTF((stderr, "*** Init(%x) ctx %p param %p\n", flags, ctx, ctx->param));
00094 return ctx;
00095 }
00096
00097
00098 int
00099 rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
00100 {
00101 DPRINTF((stderr, "*** Update(%p,%p,%d) param %p \"%s\"\n", ctx, data, len, ctx->param, ((char *)data)));
00102 return (*ctx->Update) (ctx->param, data, len);
00103 }
00104
00105
00106
00107 static int _ie = 0x44332211;
00108
00109
00110 static union _dendian {
00111 int i;
00112 char b[4];
00113 } *_endian = (union _dendian *)&_ie;
00114
00115 #define IS_BIG_ENDIAN() (_endian->b[0] == '\x44')
00116 #define IS_LITTLE_ENDIAN() (_endian->b[0] == '\x11')
00117
00118 int
00119 rpmDigestFinal( DIGEST_CTX ctx, void ** datap,
00120 size_t *lenp, int asAscii)
00121 {
00122 uint32 * digest = xmalloc(ctx->digestlen);
00123 char * t;
00124 int i;
00125
00126 DPRINTF((stderr, "*** Final(%p,%p,%p,%d) param %p digest %p\n", ctx, datap, lenp, asAscii, ctx->param, digest));
00127
00128 (void) (*ctx->Digest) (ctx->param, digest);
00129
00130
00131
00132 if (IS_LITTLE_ENDIAN())
00133 for (i = 0; i < (ctx->digestlen/sizeof(uint32)); i++)
00134 digest[i] = swapu32(digest[i]);
00135
00136
00137
00138
00139 if (!asAscii) {
00140 if (lenp) *lenp = ctx->digestlen;
00141 if (datap) {
00142 *datap = digest;
00143 digest = NULL;
00144 }
00145 } else {
00146 if (lenp) *lenp = (2*ctx->digestlen) + 1;
00147 if (datap) {
00148 const byte * s = (const byte *) digest;
00149 static const char hex[] = "0123456789abcdef";
00150
00151 *datap = t = xmalloc((2*ctx->digestlen) + 1);
00152 for (i = 0 ; i < ctx->digestlen; i++) {
00153 *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
00154 *t++ = hex[ (unsigned)((*s++ ) & 0x0f) ];
00155 }
00156 *t = '\0';
00157 }
00158 }
00159
00160 if (digest) {
00161 memset(digest, 0, ctx->digestlen);
00162 free(digest);
00163 }
00164 memset(ctx->param, 0, ctx->paramlen);
00165 free(ctx->param);
00166 memset(ctx, 0, sizeof(*ctx));
00167 free(ctx);
00168 return 0;
00169 }