Remove splint tags.
[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
16 /**
17  * MD5/SHA1 digest private data.
18  */
19 struct DIGEST_CTX_s {
20     rpmDigestFlags flags;       /*!< Bit(s) to control digest operation. */
21     uint32_t datalen;           /*!< No. bytes in block of plaintext data. */
22     uint32_t paramlen;          /*!< No. bytes of digest parameters. */
23     uint32_t digestlen;         /*!< No. bytes of digest. */
24     void * param;               /*!< Digest parameters. */
25     int (*Reset) (void * param);        /*!< Digest initialize. */
26     int (*Update) (void * param, const byte * data, size_t size);       /*!< Digest transform. */
27     int (*Digest) (void * param, byte * digest);        /*!< Digest finish. */
28 };
29
30 DIGEST_CTX
31 rpmDigestDup(DIGEST_CTX octx)
32 {
33     DIGEST_CTX nctx;
34     nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
35     nctx->param = memcpy(xcalloc(1, nctx->paramlen), octx->param, nctx->paramlen);
36     return nctx;
37 }
38
39 DIGEST_CTX
40 rpmDigestInit(pgpHashAlgo hashalgo, rpmDigestFlags flags)
41 {
42     DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
43     int xx;
44
45     ctx->flags = flags;
46
47     switch (hashalgo) {
48     case PGPHASHALGO_MD5:
49         ctx->digestlen = 16;
50         ctx->datalen = 64;
51 /* FIX: union, not void pointer */
52         ctx->paramlen = sizeof(md5Param);
53         ctx->param = xcalloc(1, ctx->paramlen);
54 /* FIX: cast? */
55         ctx->Reset = (void *) md5Reset;
56         ctx->Update = (void *) md5Update;
57         ctx->Digest = (void *) md5Digest;
58         break;
59     case PGPHASHALGO_SHA1:
60         ctx->digestlen = 20;
61         ctx->datalen = 64;
62 /* FIX: union, not void pointer */
63         ctx->paramlen = sizeof(sha1Param);
64         ctx->param = xcalloc(1, ctx->paramlen);
65 /* FIX: cast? */
66         ctx->Reset = (void *) sha1Reset;
67         ctx->Update = (void *) sha1Update;
68         ctx->Digest = (void *) sha1Digest;
69         break;
70 #if HAVE_BEECRYPT_API_H
71     case PGPHASHALGO_SHA256:
72         ctx->digestlen = 32;
73         ctx->datalen = 64;
74 /* FIX: union, not void pointer */
75         ctx->paramlen = sizeof(sha256Param);
76         ctx->param = xcalloc(1, ctx->paramlen);
77 /* FIX: cast? */
78         ctx->Reset = (void *) sha256Reset;
79         ctx->Update = (void *) sha256Update;
80         ctx->Digest = (void *) sha256Digest;
81         break;
82     case PGPHASHALGO_SHA384:
83         ctx->digestlen = 48;
84         ctx->datalen = 128;
85 /* FIX: union, not void pointer */
86         ctx->paramlen = sizeof(sha384Param);
87         ctx->param = xcalloc(1, ctx->paramlen);
88 /* FIX: cast? */
89         ctx->Reset = (void *) sha384Reset;
90         ctx->Update = (void *) sha384Update;
91         ctx->Digest = (void *) sha384Digest;
92         break;
93     case PGPHASHALGO_SHA512:
94         ctx->digestlen = 64;
95         ctx->datalen = 128;
96 /* FIX: union, not void pointer */
97         ctx->paramlen = sizeof(sha512Param);
98         ctx->param = xcalloc(1, ctx->paramlen);
99 /* FIX: cast? */
100         ctx->Reset = (void *) sha512Reset;
101         ctx->Update = (void *) sha512Update;
102         ctx->Digest = (void *) sha512Digest;
103         break;
104 #endif
105     case PGPHASHALGO_RIPEMD160:
106     case PGPHASHALGO_MD2:
107     case PGPHASHALGO_TIGER192:
108     case PGPHASHALGO_HAVAL_5_160:
109     default:
110         free(ctx);
111         return NULL;
112         break;
113     }
114
115     xx = (*ctx->Reset) (ctx->param);
116
117 DPRINTF((stderr, "*** Init(%x) ctx %p param %p\n", flags, ctx, ctx->param));
118     return ctx;
119 }
120
121 /* LCL: ctx->param may be modified, but ctx is abstract @*/
122 int
123 rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
124 {
125     if (ctx == NULL)
126         return -1;
127
128 DPRINTF((stderr, "*** Update(%p,%p,%d) param %p \"%s\"\n", ctx, data, len, ctx->param, ((char *)data)));
129     return (*ctx->Update) (ctx->param, data, len);
130 }
131
132 int
133 rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
134 {
135     byte * digest;
136     char * t;
137     int i;
138
139     if (ctx == NULL)
140         return -1;
141     digest = xmalloc(ctx->digestlen);
142
143 DPRINTF((stderr, "*** Final(%p,%p,%p,%d) param %p digest %p\n", ctx, datap, lenp, asAscii, ctx->param, digest));
144 /* FIX: check rc */
145     (void) (*ctx->Digest) (ctx->param, digest);
146
147     /* Return final digest. */
148     if (!asAscii) {
149         if (lenp) *lenp = ctx->digestlen;
150         if (datap) {
151             *datap = digest;
152             digest = NULL;
153         }
154     } else {
155         if (lenp) *lenp = (2*ctx->digestlen) + 1;
156         if (datap) {
157             const byte * s = (const byte *) digest;
158             static const char hex[] = "0123456789abcdef";
159
160             *datap = t = xmalloc((2*ctx->digestlen) + 1);
161             for (i = 0 ; i < ctx->digestlen; i++) {
162                 *t++ = hex[ (unsigned)((*s >> 4) & 0x0f) ];
163                 *t++ = hex[ (unsigned)((*s++   ) & 0x0f) ];
164             }
165             *t = '\0';
166         }
167     }
168     if (digest) {
169         memset(digest, 0, ctx->digestlen);      /* In case it's sensitive */
170         free(digest);
171     }
172     memset(ctx->param, 0, ctx->paramlen);       /* In case it's sensitive */
173     free(ctx->param);
174     memset(ctx, 0, sizeof(*ctx));       /* In case it's sensitive */
175     free(ctx);
176     return 0;
177 }