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