Splint fiddles.
[platform/upstream/rpm.git] / rpmio / digest.c
1 /** \ingroup signature
2  * \file rpmio/digest.c
3  */
4
5 #include "system.h"
6 #include "rpmio_internal.h"
7 #include "debug.h"
8
9 #ifdef  SHA_DEBUG
10 #define DPRINTF(_a)     fprintf _a
11 #else
12 #define DPRINTF(_a)
13 #endif
14
15 /*@access DIGEST_CTX@*/
16
17 /**
18  * MD5/SHA1 digest private data.
19  */
20 struct DIGEST_CTX_s {
21     rpmDigestFlags flags;       /*!< Bit(s) to control digest operation. */
22     uint32 datalen;             /*!< No. bytes in block of plaintext data. */
23     uint32 paramlen;            /*!< No. bytes of digest parameters. */
24     uint32 digestlen;           /*!< No. bytes of digest. */
25     void * param;               /*!< Digest parameters. */
26     int (*Reset) (void * param)
27         /*@modifies param @*/;  /*!< Digest initialize. */
28     int (*Update) (void * param, const byte * data, int len)
29         /*@modifies param @*/;  /*!< Digest transform. */
30     int (*Digest) (void * param, /*@out@*/ uint32 * digest)
31         /*@modifies param, digest @*/;  /*!< Digest finish. */
32 };
33
34 /*@-boundsread@*/
35 DIGEST_CTX
36 rpmDigestDup(DIGEST_CTX octx)
37 {
38     DIGEST_CTX nctx;
39     nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
40     nctx->param = memcpy(xcalloc(1, nctx->paramlen), octx->param, nctx->paramlen);
41     return nctx;
42 }
43 /*@=boundsread@*/
44
45 DIGEST_CTX
46 rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
47 {
48     DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
49     int xx;
50
51     ctx->flags = flags;
52
53     switch (hashalgo) {
54     case PGPHASHALGO_MD5:
55         ctx->digestlen = 16;
56         ctx->datalen = 64;
57 /*@-sizeoftype@*/ /* FIX: union, not void pointer */
58         ctx->paramlen = sizeof(md5Param);
59 /*@=sizeoftype@*/
60         ctx->param = xcalloc(1, ctx->paramlen);
61 /*@-type@*/ /* FIX: cast? */
62         ctx->Reset = (void *) md5Reset;
63         ctx->Update = (void *) md5Update;
64         ctx->Digest = (void *) md5Digest;
65 /*@=type@*/
66         break;
67     case PGPHASHALGO_SHA1:
68         ctx->digestlen = 20;
69         ctx->datalen = 64;
70 /*@-sizeoftype@*/ /* FIX: union, not void pointer */
71         ctx->paramlen = sizeof(sha1Param);
72 /*@=sizeoftype@*/
73         ctx->param = xcalloc(1, ctx->paramlen);
74 /*@-type@*/ /* FIX: cast? */
75         ctx->Reset = (void *) sha1Reset;
76         ctx->Update = (void *) sha1Update;
77         ctx->Digest = (void *) sha1Digest;
78 /*@=type@*/
79         break;
80     case PGPHASHALGO_RIPEMD160:
81     case PGPHASHALGO_MD2:
82     case PGPHASHALGO_TIGER192:
83     case PGPHASHALGO_HAVAL_5_160:
84     default:
85         free(ctx);
86         return NULL;
87         /*@notreached@*/ break;
88     }
89
90 /*@-boundsread@*/
91     xx = (*ctx->Reset) (ctx->param);
92 /*@=boundsread@*/
93
94 DPRINTF((stderr, "*** Init(%x) ctx %p param %p\n", flags, ctx, ctx->param));
95     return ctx;
96 }
97
98 /*@-mustmod@*/ /* LCL: ctx->param may be modified, but ctx is abstract @*/
99 int
100 rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
101 {
102     if (ctx == NULL)
103         return -1;
104
105 DPRINTF((stderr, "*** Update(%p,%p,%d) param %p \"%s\"\n", ctx, data, len, ctx->param, ((char *)data)));
106 /*@-boundsread@*/
107     return (*ctx->Update) (ctx->param, data, len);
108 /*@=boundsread@*/
109 }
110 /*@=mustmod@*/
111
112 /*@unchecked@*/
113 static int _ie = 0x44332211;
114
115 /*@-redef@*/
116 /*@unchecked@*/
117 static union _dendian {
118 /*@unused@*/ int i;
119     char b[4];
120 } *_endian = (union _dendian *)&_ie;
121 /*@=redef@*/
122
123 #define        IS_BIG_ENDIAN()         (_endian->b[0] == '\x44')
124 #define        IS_LITTLE_ENDIAN()      (_endian->b[0] == '\x11')
125
126 /*@-boundswrite@*/
127 int
128 rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
129 {
130     uint32 * digest;
131     char * t;
132     int i;
133
134     if (ctx == NULL)
135         return -1;
136     digest = xmalloc(ctx->digestlen);
137
138 DPRINTF((stderr, "*** Final(%p,%p,%p,%d) param %p digest %p\n", ctx, datap, lenp, asAscii, ctx->param, digest));
139 /*@-noeffectuncon@*/ /* FIX: check rc */
140     (void) (*ctx->Digest) (ctx->param, digest);
141 /*@=noeffectuncon@*/
142
143 /*@-sizeoftype@*/
144     if (IS_LITTLE_ENDIAN())
145     for (i = 0; i < (ctx->digestlen/sizeof(uint32)); i++)
146         digest[i] = swapu32(digest[i]);
147 /*@=sizeoftype@*/
148
149     /* Return final digest. */
150 /*@-branchstate@*/
151     if (!asAscii) {
152         if (lenp) *lenp = ctx->digestlen;
153         if (datap) {
154             *datap = digest;
155             digest = NULL;
156         }
157     } else {
158         if (lenp) *lenp = (2*ctx->digestlen) + 1;
159         if (datap) {
160             const byte * s = (const byte *) digest;
161             static const char hex[] = "0123456789abcdef";
162
163             *datap = t = xmalloc((2*ctx->digestlen) + 1);
164             for (i = 0 ; i < ctx->digestlen; i++) {
165                 *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
166                 *t++ = hex[ (unsigned)((*s++   ) & 0x0f) ];
167             }
168             *t = '\0';
169         }
170     }
171 /*@=branchstate@*/
172     if (digest) {
173         memset(digest, 0, ctx->digestlen);      /* In case it's sensitive */
174         free(digest);
175     }
176     memset(ctx->param, 0, ctx->paramlen);       /* In case it's sensitive */
177     free(ctx->param);
178     memset(ctx, 0, sizeof(*ctx));       /* In case it's sensitive */
179     free(ctx);
180     return 0;
181 }
182 /*@=boundswrite@*/