# rpmio/digest.c

Go to the documentation of this file.

    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 /*@access DIGEST_CTX@*/
    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         /*@modifies param @*/;
    00032     int (*Update) (void * param, const byte * data, int len)
    00033         /*@modifies param @*/;
    00034     int (*Digest) (void * param, /*@out@*/ uint32 * digest)
    00035         /*@modifies param, digest @*/;
    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         /*@-sizeoftype@*/ /* FIX: union, not void pointer */
    00059         ctx->paramlen = sizeof(md5Param);
    00060         /*@=sizeoftype@*/
    00061         ctx->param = xcalloc(1, ctx->paramlen);
    00062         /*@-type@*/ /* FIX: cast? */
    00063         ctx->Reset = (void *) md5Reset;
    00064         ctx->Update = (void *) md5Update;
    00065         ctx->Digest = (void *) md5Digest;
    00066         /*@=type@*/
    00067         break;
    00068     case PGPHASHALGO_SHA1:
    00069         ctx->digestlen = 20;
    00070         ctx->datalen = 64;
    00071         /*@-sizeoftype@*/ /* FIX: union, not void pointer */
    00072         ctx->paramlen = sizeof(sha1Param);
    00073         /*@=sizeoftype@*/
    00074         ctx->param = xcalloc(1, ctx->paramlen);
    00075         /*@-type@*/ /* FIX: cast? */
    00076         ctx->Reset = (void *) sha1Reset;
    00077         ctx->Update = (void *) sha1Update;
    00078         ctx->Digest = (void *) sha1Digest;
    00079         /*@=type@*/
    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         /*@notreached@*/ 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 /*@-mustmod@*/ /* LCL: ctx->param may be modified, but ctx is abstract @*/
    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 /*@=mustmod@*/
    00105
    00106 /*@unchecked@*/
    00107 static int _ie = 0x44332211;
    00108 /*@-redef@*/
    00109 /*@unchecked@*/
    00110 static union _dendian {
    00111 /*@unused@*/ int i;
    00112     char b[4];
    00113 } *_endian = (union _dendian *)&_ie;
    00114 /*@=redef@*/
    00115 #define        IS_BIG_ENDIAN()         (_endian->b[0] == '\x44')
    00116 #define        IS_LITTLE_ENDIAN()      (_endian->b[0] == '\x11')
    00117
    00118 int
    00119 rpmDigestFinal(/*@only@*/ DIGEST_CTX ctx, /*@out@*/ void ** datap,
    00120         /*@out@*/ 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     /*@-noeffectuncon@*/ /* FIX: check rc */
    00128     (void) (*ctx->Digest) (ctx->param, digest);
    00129     /*@=noeffectuncon@*/
    00130
    00131     /*@-sizeoftype@*/
    00132     if (IS_LITTLE_ENDIAN())
    00133     for (i = 0; i < (ctx->digestlen/sizeof(uint32)); i++)
    00134         digest[i] = swapu32(digest[i]);
    00135     /*@=sizeoftype@*/
    00136
    00137     /* Return final digest. */
    00138     /*@-branchstate@*/
    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     /*@=branchstate@*/
    00160     if (digest) {
    00161         memset(digest, 0, ctx->digestlen);      /* In case it's sensitive */
    00162         free(digest);
    00163     }
    00164     memset(ctx->param, 0, ctx->paramlen);       /* In case it's sensitive */
    00165     free(ctx->param);
    00166     memset(ctx, 0, sizeof(*ctx));       /* In case it's sensitive */
    00167     free(ctx);
    00168     return 0;
    00169 }