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