xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/netpgpverify/digest.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
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 uint64_t	prefix_tiger[] = {
68 	0x0123456789ABCDEFLL,
69 	0xFEDCBA9876543210LL,
70 	0xF096A5B4C3B2E187LL
71 };
72 
73 static uint8_t prefix_rmd160[] = {
74 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24,
75 	0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14
76 };
77 
78 static uint8_t prefix_sha512[] = {
79 	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
80 	0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
81 };
82 
83 #define V4_SIGNATURE		4
84 
85 /*************************************************************************/
86 
87 /* algorithm size (raw) */
88 int
89 digest_alg_size(unsigned alg)
90 {
91 	switch(alg) {
92 	case MD5_HASH_ALG:
93 		return 16;
94 	case SHA1_HASH_ALG:
95 		return 20;
96 	case RIPEMD_HASH_ALG:
97 		return RMD160_DIGEST_LENGTH;
98 	case SHA256_HASH_ALG:
99 		return 32;
100 	case SHA512_HASH_ALG:
101 		return 64;
102 	case TIGER_HASH_ALG:
103 	case TIGER2_HASH_ALG:
104 		return TIGER_DIGEST_LENGTH;
105 	default:
106 		printf("hash_any: bad algorithm\n");
107 		return 0;
108 	}
109 }
110 
111 /* initialise the hash structure */
112 int
113 digest_init(digest_t *hash, const uint32_t hashalg)
114 {
115 	if (hash == NULL) {
116 		return 0;
117 	}
118 	switch(hash->alg = hashalg) {
119 	case MD5_HASH_ALG:
120 		netpgpv_MD5Init(&hash->u.md5ctx);
121 		hash->size = 16;
122 		hash->prefix = prefix_md5;
123 		hash->len = sizeof(prefix_md5);
124 		hash->ctx = &hash->u.md5ctx;
125 		return 1;
126 	case SHA1_HASH_ALG:
127 		netpgpv_SHA1Init(&hash->u.sha1ctx);
128 		hash->size = 20;
129 		hash->prefix = prefix_sha1;
130 		hash->len = sizeof(prefix_sha1);
131 		hash->ctx = &hash->u.sha1ctx;
132 		return 1;
133 	case RIPEMD_HASH_ALG:
134 		netpgpv_RMD160Init(&hash->u.rmd160ctx);
135 		hash->size = 20;
136 		hash->prefix = prefix_rmd160;
137 		hash->len = sizeof(prefix_rmd160);
138 		hash->ctx = &hash->u.rmd160ctx;
139 		return 1;
140 	case SHA256_HASH_ALG:
141 		netpgpv_SHA256_Init(&hash->u.sha256ctx);
142 		hash->size = 32;
143 		hash->prefix = prefix_sha256;
144 		hash->len = sizeof(prefix_sha256);
145 		hash->ctx = &hash->u.sha256ctx;
146 		return 1;
147 	case SHA512_HASH_ALG:
148 		netpgpv_SHA512_Init(&hash->u.sha512ctx);
149 		hash->size = 64;
150 		hash->prefix = prefix_sha512;
151 		hash->len = sizeof(prefix_sha512);
152 		hash->ctx = &hash->u.sha512ctx;
153 		return 1;
154 	case TIGER_HASH_ALG:
155 		netpgpv_TIGER_Init(&hash->u.tigerctx);
156 		hash->size = TIGER_DIGEST_LENGTH;
157 		hash->prefix = prefix_tiger;
158 		hash->len = sizeof(prefix_tiger);
159 		hash->ctx = &hash->u.tigerctx;
160 		return 1;
161 	case TIGER2_HASH_ALG:
162 		netpgpv_TIGER2_Init(&hash->u.tigerctx);
163 		hash->size = TIGER_DIGEST_LENGTH;
164 		hash->prefix = prefix_tiger;
165 		hash->len = sizeof(prefix_tiger);
166 		hash->ctx = &hash->u.tigerctx;
167 		return 1;
168 	default:
169 		printf("hash_any: bad algorithm\n");
170 		return 0;
171 	}
172 }
173 
174 typedef struct rec_t {
175 	const char	*s;
176 	const unsigned	 alg;
177 } rec_t;
178 
179 static rec_t	hashalgs[] = {
180 	{	"md5",		MD5_HASH_ALG	},
181 	{	"sha1",		SHA1_HASH_ALG	},
182 	{	"ripemd",	RIPEMD_HASH_ALG	},
183 	{	"sha256",	SHA256_HASH_ALG	},
184 	{	"sha512",	SHA512_HASH_ALG	},
185 	{	"tiger",	TIGER_HASH_ALG	},
186 	{	"tiger2",	TIGER2_HASH_ALG	},
187 	{	NULL,		0		}
188 };
189 
190 /* initialise by string alg name */
191 unsigned
192 digest_get_alg(const char *hashalg)
193 {
194 	rec_t	*r;
195 
196 	for (r = hashalgs ; hashalg && r->s ; r++) {
197 		if (strcasecmp(r->s, hashalg) == 0) {
198 			return r->alg;
199 		}
200 	}
201 	return 0;
202 }
203 
204 int
205 digest_update(digest_t *hash, const uint8_t *data, size_t length)
206 {
207 	if (hash == NULL || data == NULL) {
208 		return 0;
209 	}
210 	switch(hash->alg) {
211 	case MD5_HASH_ALG:
212 		netpgpv_MD5Update(hash->ctx, data, (unsigned)length);
213 		return 1;
214 	case SHA1_HASH_ALG:
215 		netpgpv_SHA1Update(hash->ctx, data, (unsigned)length);
216 		return 1;
217 	case RIPEMD_HASH_ALG:
218 		netpgpv_RMD160Update(hash->ctx, data, (unsigned)length);
219 		return 1;
220 	case SHA256_HASH_ALG:
221 		netpgpv_SHA256_Update(hash->ctx, data, length);
222 		return 1;
223 	case SHA512_HASH_ALG:
224 		netpgpv_SHA512_Update(hash->ctx, data, length);
225 		return 1;
226 	case TIGER_HASH_ALG:
227 	case TIGER2_HASH_ALG:
228 		netpgpv_TIGER_Update(hash->ctx, data, length);
229 		return 1;
230 	default:
231 		printf("hash_any: bad algorithm\n");
232 		return 0;
233 	}
234 }
235 
236 unsigned
237 digest_final(uint8_t *out, digest_t *hash)
238 {
239 	if (hash == NULL || out == NULL) {
240 		return 0;
241 	}
242 	switch(hash->alg) {
243 	case MD5_HASH_ALG:
244 		netpgpv_MD5Final(out, hash->ctx);
245 		break;
246 	case SHA1_HASH_ALG:
247 		netpgpv_SHA1Final(out, hash->ctx);
248 		break;
249 	case RIPEMD_HASH_ALG:
250 		netpgpv_RMD160Final(out, hash->ctx);
251 		break;
252 	case SHA256_HASH_ALG:
253 		netpgpv_SHA256_Final(out, hash->ctx);
254 		break;
255 	case SHA512_HASH_ALG:
256 		netpgpv_SHA512_Final(out, hash->ctx);
257 		break;
258 	case TIGER_HASH_ALG:
259 		netpgpv_TIGER_Final(out, hash->ctx);
260 		break;
261 	default:
262 		printf("hash_any: bad algorithm\n");
263 		return 0;
264 	}
265 	(void) memset(hash->ctx, 0x0, hash->size);
266 	return (unsigned)hash->size;
267 }
268 
269 int
270 digest_length(digest_t *hash, unsigned hashedlen)
271 {
272 	uint8_t		 trailer[6];
273 
274 	if (hash == NULL) {
275 		return 0;
276 	}
277 	trailer[0] = V4_SIGNATURE;
278 	trailer[1] = 0xFF;
279 	trailer[2] = (uint8_t)((hashedlen >> 24) & 0xff);
280 	trailer[3] = (uint8_t)((hashedlen >> 16) & 0xff);
281 	trailer[4] = (uint8_t)((hashedlen >> 8) & 0xff);
282 	trailer[5] = (uint8_t)(hashedlen & 0xff);
283 	digest_update(hash, trailer, sizeof(trailer));
284 	return 1;
285 }
286 
287 unsigned
288 digest_get_prefix(unsigned hashalg, uint8_t *prefix, size_t size)
289 {
290 	USE_ARG(size);
291 	if (prefix == NULL) {
292 		return 0;
293 	}
294 	switch (hashalg) {
295 	case MD5_HASH_ALG:
296 		memcpy(prefix, prefix_md5, sizeof(prefix_md5));
297 		return sizeof(prefix_md5);
298 	case SHA1_HASH_ALG:
299 		memcpy(prefix, prefix_sha1, sizeof(prefix_sha1));
300 		return sizeof(prefix_sha1);
301 	case SHA256_HASH_ALG:
302 		memcpy(prefix, prefix_sha256, sizeof(prefix_sha256));
303 		return sizeof(prefix_sha256);
304 	case SHA512_HASH_ALG:
305 		memcpy(prefix, prefix_sha512, sizeof(prefix_sha512));
306 		return sizeof(prefix_sha512);
307 	default:
308 		printf("digest_get_prefix: unknown hash algorithm: %d\n", hashalg);
309 		return 0;
310 	}
311 }
312 
313