Main Page Modules Data Structures File List Data Fields Globals 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 #ifdef  SHA_DEBUG
    00010 #define DPRINTF(_a)     fprintf _a
    00011 #else
    00012 #define DPRINTF(_a)
    00013 #endif
    00014
    00015 /*@access DIGEST_CTX@*/
    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         /*@modifies param @*/;
    00028     int (*Update) (void * param, const byte * data, int len)
    00029         /*@modifies param @*/;
    00030     int (*Digest) (void * param, /*@out@*/ uint32 * digest)
    00031         /*@modifies param, digest @*/;
    00032 };
    00033
    00034 /*@-boundsread@*/
    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 /*@=boundsread@*/
    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         /*@-sizeoftype@*/ /* FIX: union, not void pointer */
    00057         ctx->paramlen = sizeof(md5Param);
    00058         /*@=sizeoftype@*/
    00059         ctx->param = xcalloc(1, ctx->paramlen);
    00060         /*@-type@*/ /* FIX: cast? */
    00061         ctx->Reset = (void *) md5Reset;
    00062         ctx->Update = (void *) md5Update;
    00063         ctx->Digest = (void *) md5Digest;
    00064         /*@=type@*/
    00065         break;
    00066     case PGPHASHALGO_SHA1:
    00067         ctx->digestlen = 20;
    00068         ctx->datalen = 64;
    00069         /*@-sizeoftype@*/ /* FIX: union, not void pointer */
    00070         ctx->paramlen = sizeof(sha1Param);
    00071         /*@=sizeoftype@*/
    00072         ctx->param = xcalloc(1, ctx->paramlen);
    00073         /*@-type@*/ /* FIX: cast? */
    00074         ctx->Reset = (void *) sha1Reset;
    00075         ctx->Update = (void *) sha1Update;
    00076         ctx->Digest = (void *) sha1Digest;
    00077         /*@=type@*/
    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         /*@notreached@*/ break;
    00087     }
    00088
    00089 /*@-boundsread@*/
    00090     xx = (*ctx->Reset) (ctx->param);
    00091 /*@=boundsread@*/
    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 /*@-boundsread@*/
    00103     return (*ctx->Update) (ctx->param, data, len);
    00104 /*@=boundsread@*/
    00105 }
    00106 /*@=mustmod@*/
    00107
    00108 /*@unchecked@*/
    00109 static int _ie = 0x44332211;
    00110 /*@-redef@*/
    00111 /*@unchecked@*/
    00112 static union _dendian {
    00113 /*@unused@*/ int i;
    00114     char b[4];
    00115 } *_endian = (union _dendian *)&_ie;
    00116 /*@=redef@*/
    00117 #define        IS_BIG_ENDIAN()         (_endian->b[0] == '\x44')
    00118 #define        IS_LITTLE_ENDIAN()      (_endian->b[0] == '\x11')
    00119
    00120 /*@-boundswrite@*/
    00121 int
    00122 rpmDigestFinal(/*@only@*/ DIGEST_CTX ctx, /*@out@*/ void ** datap,
    00123         /*@out@*/ 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     /*@-noeffectuncon@*/ /* FIX: check rc */
    00131     (void) (*ctx->Digest) (ctx->param, digest);
    00132     /*@=noeffectuncon@*/
    00133
    00134     /*@-sizeoftype@*/
    00135     if (IS_LITTLE_ENDIAN())
    00136     for (i = 0; i < (ctx->digestlen/sizeof(uint32)); i++)
    00137         digest[i] = swapu32(digest[i]);
    00138     /*@=sizeoftype@*/
    00139
    00140     /* Return final digest. */
    00141     /*@-branchstate@*/
    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     /*@=branchstate@*/
    00163     if (digest) {
    00164         memset(digest, 0, ctx->digestlen);      /* In case it's sensitive */
    00165         free(digest);
    00166     }
    00167     memset(ctx->param, 0, ctx->paramlen);       /* In case it's sensitive */
    00168     free(ctx->param);
    00169     memset(ctx, 0, sizeof(*ctx));       /* In case it's sensitive */
    00170     free(ctx);
    00171     return 0;
    00172 }
    00173 /*@=boundswrite@*/