Imported Upstream version 0.7.17
[platform/upstream/libsolv.git] / src / chksum.c
1 /*
2  * Copyright (c) 2008-2012, Novell Inc.
3  *
4  * This program is licensed under the BSD license, read LICENSE.BSD
5  * for further information
6  */
7
8 #include <sys/types.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13
14 #include "pool.h"
15 #include "util.h"
16 #include "chksum.h"
17
18 #include "md5.h"
19 #include "sha1.h"
20 #include "sha2.h"
21
22 #ifdef _WIN32
23   #include "strfncs.h"
24 #endif
25
26 struct s_Chksum {
27   Id type;
28   int done;
29   unsigned char result[64];
30   union {
31     MD5_CTX md5;
32     SHA1_CTX sha1;
33     SHA224_CTX sha224;
34     SHA256_CTX sha256;
35     SHA384_CTX sha384;
36     SHA512_CTX sha512;
37   } c;
38 };
39
40 Chksum *
41 solv_chksum_create(Id type)
42 {
43   Chksum *chk;
44   chk = solv_calloc(1, sizeof(*chk));
45   chk->type = type;
46   switch(type)
47     {
48     case REPOKEY_TYPE_MD5:
49       solv_MD5_Init(&chk->c.md5);
50       return chk;
51     case REPOKEY_TYPE_SHA1:
52       solv_SHA1_Init(&chk->c.sha1);
53       return chk;
54     case REPOKEY_TYPE_SHA224:
55       solv_SHA224_Init(&chk->c.sha224);
56       return chk;
57     case REPOKEY_TYPE_SHA256:
58       solv_SHA256_Init(&chk->c.sha256);
59       return chk;
60     case REPOKEY_TYPE_SHA384:
61       solv_SHA384_Init(&chk->c.sha384);
62       return chk;
63     case REPOKEY_TYPE_SHA512:
64       solv_SHA512_Init(&chk->c.sha512);
65       return chk;
66     default:
67       break;
68     }
69   free(chk);
70   return 0;
71 }
72
73 Chksum *
74 solv_chksum_create_clone(Chksum *chk)
75 {
76   return solv_memdup(chk, sizeof(*chk));
77 }
78
79 int
80 solv_chksum_len(Id type)
81 {
82   switch (type)
83     {
84     case REPOKEY_TYPE_MD5:
85       return 16;
86     case REPOKEY_TYPE_SHA1:
87       return 20;
88     case REPOKEY_TYPE_SHA224:
89       return 28;
90     case REPOKEY_TYPE_SHA256:
91       return 32;
92     case REPOKEY_TYPE_SHA384:
93       return 48;
94     case REPOKEY_TYPE_SHA512:
95       return 64;
96     default:
97       return 0;
98     }
99 }
100
101 Chksum *
102 solv_chksum_create_from_bin(Id type, const unsigned char *buf)
103 {
104   Chksum *chk;
105   int l = solv_chksum_len(type);
106   if (buf == 0 || l == 0)
107     return 0;
108   chk = solv_calloc(1, sizeof(*chk));
109   chk->type = type;
110   chk->done = 1;
111   memcpy(chk->result, buf, l);
112   return chk;
113 }
114
115 void
116 solv_chksum_add(Chksum *chk, const void *data, int len)
117 {
118   if (chk->done)
119     return;
120   switch(chk->type)
121     {
122     case REPOKEY_TYPE_MD5:
123       solv_MD5_Update(&chk->c.md5, (void *)data, len);
124       return;
125     case REPOKEY_TYPE_SHA1:
126       solv_SHA1_Update(&chk->c.sha1, data, len);
127       return;
128     case REPOKEY_TYPE_SHA224:
129       solv_SHA224_Update(&chk->c.sha224, data, len);
130       return;
131     case REPOKEY_TYPE_SHA256:
132       solv_SHA256_Update(&chk->c.sha256, data, len);
133       return;
134     case REPOKEY_TYPE_SHA384:
135       solv_SHA384_Update(&chk->c.sha384, data, len);
136       return;
137     case REPOKEY_TYPE_SHA512:
138       solv_SHA512_Update(&chk->c.sha512, data, len);
139       return;
140     default:
141       return;
142     }
143 }
144
145 const unsigned char *
146 solv_chksum_get(Chksum *chk, int *lenp)
147 {
148   if (chk->done)
149     {
150       if (lenp)
151         *lenp = solv_chksum_len(chk->type);
152       return chk->result;
153     }
154   switch(chk->type)
155     {
156     case REPOKEY_TYPE_MD5:
157       solv_MD5_Final(chk->result, &chk->c.md5);
158       chk->done = 1;
159       if (lenp)
160         *lenp = 16;
161       return chk->result;
162     case REPOKEY_TYPE_SHA1:
163       solv_SHA1_Final(&chk->c.sha1, chk->result);
164       chk->done = 1;
165       if (lenp)
166         *lenp = 20;
167       return chk->result;
168     case REPOKEY_TYPE_SHA224:
169       solv_SHA224_Final(chk->result, &chk->c.sha224);
170       chk->done = 1;
171       if (lenp)
172         *lenp = 28;
173       return chk->result;
174     case REPOKEY_TYPE_SHA256:
175       solv_SHA256_Final(chk->result, &chk->c.sha256);
176       chk->done = 1;
177       if (lenp)
178         *lenp = 32;
179       return chk->result;
180     case REPOKEY_TYPE_SHA384:
181       solv_SHA384_Final(chk->result, &chk->c.sha384);
182       chk->done = 1;
183       if (lenp)
184         *lenp = 48;
185       return chk->result;
186     case REPOKEY_TYPE_SHA512:
187       solv_SHA512_Final(chk->result, &chk->c.sha512);
188       chk->done = 1;
189       if (lenp)
190         *lenp = 64;
191       return chk->result;
192     default:
193       if (lenp)
194         *lenp = 0;
195       return 0;
196     }
197 }
198
199 Id
200 solv_chksum_get_type(Chksum *chk)
201 {
202   return chk->type;
203 }
204
205 int
206 solv_chksum_isfinished(Chksum *chk)
207 {
208   return chk->done != 0;
209 }
210
211 const char *
212 solv_chksum_type2str(Id type)
213 {
214   switch(type)
215     {
216     case REPOKEY_TYPE_MD5:
217       return "md5";
218     case REPOKEY_TYPE_SHA1:
219       return "sha1";
220     case REPOKEY_TYPE_SHA224:
221       return "sha224";
222     case REPOKEY_TYPE_SHA256:
223       return "sha256";
224     case REPOKEY_TYPE_SHA384:
225       return "sha384";
226     case REPOKEY_TYPE_SHA512:
227       return "sha512";
228     default:
229       return 0;
230     }
231 }
232
233 Id
234 solv_chksum_str2type(const char *str)
235 {
236   if (!strcasecmp(str, "md5"))
237     return REPOKEY_TYPE_MD5;
238   if (!strcasecmp(str, "sha") || !strcasecmp(str, "sha1"))
239     return REPOKEY_TYPE_SHA1;
240   if (!strcasecmp(str, "sha224"))
241     return REPOKEY_TYPE_SHA224;
242   if (!strcasecmp(str, "sha256"))
243     return REPOKEY_TYPE_SHA256;
244   if (!strcasecmp(str, "sha384"))
245     return REPOKEY_TYPE_SHA384;
246   if (!strcasecmp(str, "sha512"))
247     return REPOKEY_TYPE_SHA512;
248   return 0;
249 }
250
251 void *
252 solv_chksum_free(Chksum *chk, unsigned char *cp)
253 {
254   if (cp)
255     {
256       const unsigned char *res;
257       int l;
258       res = solv_chksum_get(chk, &l);
259       if (l && res)
260         memcpy(cp, res, l);
261     }
262   solv_free(chk);
263   return 0;
264 }
265
266 int
267 solv_chksum_cmp(Chksum *chk, Chksum *chk2)
268 {
269   int len;
270   const unsigned char *res1, *res2;
271   if (chk == chk2)
272     return 1;
273   if (!chk || !chk2 || chk->type != chk2->type)
274     return 0;
275   res1 = solv_chksum_get(chk, &len);
276   res2 = solv_chksum_get(chk2, 0);
277   return memcmp(res1, res2, len) == 0 ? 1 : 0;
278 }