1 /*-
2 * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25 #include "config.h"
26
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <sys/param.h>
30
31 #include <arpa/inet.h>
32 #include <ctype.h>
33 #include <inttypes.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <unistd.h>
40
41 #include "md5.h"
42 #include "rmd160.h"
43 #include "sha1.h"
44 #include "sha2.h"
45
46 #include "digest.h"
47
48 #ifndef USE_ARG
49 #define USE_ARG(x) /*LINTED*/(void)&(x)
50 #endif
51
52 static uint8_t prefix_md5[] = {
53 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
54 0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
55 };
56
57 static uint8_t prefix_sha1[] = {
58 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
59 0x1A, 0x05, 0x00, 0x04, 0x14
60 };
61
62 static uint8_t prefix_sha256[] = {
63 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
64 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
65 };
66
67 static uint8_t prefix_rmd160[] = {
68 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24,
69 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14
70 };
71
72 static uint8_t prefix_sha512[] = {
73 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
74 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
75 };
76
77 #define V4_SIGNATURE 4
78
79 /*************************************************************************/
80
81 /* algorithm size (raw) */
82 int
digest_alg_size(unsigned alg)83 digest_alg_size(unsigned alg)
84 {
85 switch(alg) {
86 case MD5_HASH_ALG:
87 return 16;
88 case SHA1_HASH_ALG:
89 return 20;
90 case RIPEMD_HASH_ALG:
91 return RMD160_DIGEST_LENGTH;
92 case SHA256_HASH_ALG:
93 return 32;
94 case SHA512_HASH_ALG:
95 return 64;
96 default:
97 printf("hash_any: bad algorithm\n");
98 return 0;
99 }
100 }
101
102 /* initialise the hash structure */
103 int
digest_init(digest_t * hash,const uint32_t hashalg)104 digest_init(digest_t *hash, const uint32_t hashalg)
105 {
106 if (hash == NULL) {
107 return 0;
108 }
109 switch(hash->alg = hashalg) {
110 case MD5_HASH_ALG:
111 netpgpv_MD5Init(&hash->u.md5ctx);
112 hash->size = 16;
113 hash->prefix = prefix_md5;
114 hash->len = sizeof(prefix_md5);
115 hash->ctx = &hash->u.md5ctx;
116 return 1;
117 case SHA1_HASH_ALG:
118 netpgpv_SHA1Init(&hash->u.sha1ctx);
119 hash->size = 20;
120 hash->prefix = prefix_sha1;
121 hash->len = sizeof(prefix_sha1);
122 hash->ctx = &hash->u.sha1ctx;
123 return 1;
124 case RIPEMD_HASH_ALG:
125 netpgpv_RMD160Init(&hash->u.rmd160ctx);
126 hash->size = 20;
127 hash->prefix = prefix_rmd160;
128 hash->len = sizeof(prefix_rmd160);
129 hash->ctx = &hash->u.rmd160ctx;
130 return 1;
131 case SHA256_HASH_ALG:
132 netpgpv_SHA256_Init(&hash->u.sha256ctx);
133 hash->size = 32;
134 hash->prefix = prefix_sha256;
135 hash->len = sizeof(prefix_sha256);
136 hash->ctx = &hash->u.sha256ctx;
137 return 1;
138 case SHA512_HASH_ALG:
139 netpgpv_SHA512_Init(&hash->u.sha512ctx);
140 hash->size = 64;
141 hash->prefix = prefix_sha512;
142 hash->len = sizeof(prefix_sha512);
143 hash->ctx = &hash->u.sha512ctx;
144 return 1;
145 default:
146 printf("hash_any: bad algorithm\n");
147 return 0;
148 }
149 }
150
151 typedef struct rec_t {
152 const char *s;
153 const unsigned alg;
154 } rec_t;
155
156 static rec_t hashalgs[] = {
157 { "md5", MD5_HASH_ALG },
158 { "sha1", SHA1_HASH_ALG },
159 { "ripemd", RIPEMD_HASH_ALG },
160 { "sha256", SHA256_HASH_ALG },
161 { "sha512", SHA512_HASH_ALG },
162 { NULL, 0 }
163 };
164
165 /* initialise by string alg name */
166 unsigned
digest_get_alg(const char * hashalg)167 digest_get_alg(const char *hashalg)
168 {
169 rec_t *r;
170
171 for (r = hashalgs ; hashalg && r->s ; r++) {
172 if (strcasecmp(r->s, hashalg) == 0) {
173 return r->alg;
174 }
175 }
176 return 0;
177 }
178
179 int
digest_update(digest_t * hash,const uint8_t * data,size_t length)180 digest_update(digest_t *hash, const uint8_t *data, size_t length)
181 {
182 if (hash == NULL || data == NULL) {
183 return 0;
184 }
185 switch(hash->alg) {
186 case MD5_HASH_ALG:
187 netpgpv_MD5Update(hash->ctx, data, (unsigned)length);
188 return 1;
189 case SHA1_HASH_ALG:
190 netpgpv_SHA1Update(hash->ctx, data, (unsigned)length);
191 return 1;
192 case RIPEMD_HASH_ALG:
193 netpgpv_RMD160Update(hash->ctx, data, (unsigned)length);
194 return 1;
195 case SHA256_HASH_ALG:
196 netpgpv_SHA256_Update(hash->ctx, data, length);
197 return 1;
198 case SHA512_HASH_ALG:
199 netpgpv_SHA512_Update(hash->ctx, data, length);
200 return 1;
201 default:
202 printf("hash_any: bad algorithm\n");
203 return 0;
204 }
205 }
206
207 unsigned
digest_final(uint8_t * out,digest_t * hash)208 digest_final(uint8_t *out, digest_t *hash)
209 {
210 if (hash == NULL || out == NULL) {
211 return 0;
212 }
213 switch(hash->alg) {
214 case MD5_HASH_ALG:
215 netpgpv_MD5Final(out, hash->ctx);
216 break;
217 case SHA1_HASH_ALG:
218 netpgpv_SHA1Final(out, hash->ctx);
219 break;
220 case RIPEMD_HASH_ALG:
221 netpgpv_RMD160Final(out, hash->ctx);
222 break;
223 case SHA256_HASH_ALG:
224 netpgpv_SHA256_Final(out, hash->ctx);
225 break;
226 case SHA512_HASH_ALG:
227 netpgpv_SHA512_Final(out, hash->ctx);
228 break;
229 default:
230 printf("hash_any: bad algorithm\n");
231 return 0;
232 }
233 (void) memset(hash->ctx, 0x0, hash->size);
234 return (unsigned)hash->size;
235 }
236
237 int
digest_length(digest_t * hash,unsigned hashedlen)238 digest_length(digest_t *hash, unsigned hashedlen)
239 {
240 uint8_t trailer[6];
241
242 if (hash == NULL) {
243 return 0;
244 }
245 trailer[0] = V4_SIGNATURE;
246 trailer[1] = 0xFF;
247 trailer[2] = (uint8_t)((hashedlen >> 24) & 0xff);
248 trailer[3] = (uint8_t)((hashedlen >> 16) & 0xff);
249 trailer[4] = (uint8_t)((hashedlen >> 8) & 0xff);
250 trailer[5] = (uint8_t)(hashedlen & 0xff);
251 digest_update(hash, trailer, sizeof(trailer));
252 return 1;
253 }
254
255 unsigned
digest_get_prefix(unsigned hashalg,uint8_t * prefix,size_t size)256 digest_get_prefix(unsigned hashalg, uint8_t *prefix, size_t size)
257 {
258 USE_ARG(size);
259 if (prefix == NULL) {
260 return 0;
261 }
262 switch (hashalg) {
263 case MD5_HASH_ALG:
264 memcpy(prefix, prefix_md5, sizeof(prefix_md5));
265 return sizeof(prefix_md5);
266 case SHA1_HASH_ALG:
267 memcpy(prefix, prefix_sha1, sizeof(prefix_sha1));
268 return sizeof(prefix_sha1);
269 case SHA256_HASH_ALG:
270 memcpy(prefix, prefix_sha256, sizeof(prefix_sha256));
271 return sizeof(prefix_sha256);
272 case SHA512_HASH_ALG:
273 memcpy(prefix, prefix_sha512, sizeof(prefix_sha512));
274 return sizeof(prefix_sha512);
275 default:
276 printf("digest_get_prefix: unknown hash algorithm: %d\n", hashalg);
277 return 0;
278 }
279 }
280
281