xref: /netbsd-src/crypto/external/bsd/netpgp/dist/src/netpgpverify/digest.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
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 #include <sys/syslog.h>
31 
32 #include <arpa/inet.h>
33 #include <ctype.h>
34 #include <inttypes.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <time.h>
40 #include <unistd.h>
41 
42 #include "md5.h"
43 #include "rmd160.h"
44 #include "sha1.h"
45 #include "sha2.h"
46 
47 #include "digest.h"
48 
49 static uint8_t prefix_md5[] = {
50 	0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
51 	0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10
52 };
53 
54 static uint8_t prefix_sha1[] = {
55 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0E, 0x03, 0x02,
56 	0x1A, 0x05, 0x00, 0x04, 0x14
57 };
58 
59 static uint8_t prefix_sha256[] = {
60 	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
61 	0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
62 };
63 
64 static uint64_t	prefix_tiger[] = {
65 	0x0123456789ABCDEFLL,
66 	0xFEDCBA9876543210LL,
67 	0xF096A5B4C3B2E187LL
68 };
69 
70 static uint8_t prefix_rmd160[] = {
71 	0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24,
72 	0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14
73 };
74 
75 static uint8_t prefix_sha512[] = {
76 	0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
77 	0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
78 };
79 
80 #define V4_SIGNATURE		4
81 
82 /*************************************************************************/
83 
84 /* algorithm size (raw) */
85 int
86 digest_alg_size(unsigned alg)
87 {
88 	switch(alg) {
89 	case MD5_HASH_ALG:
90 		return 16;
91 	case SHA1_HASH_ALG:
92 		return 20;
93 	case RIPEMD_HASH_ALG:
94 		return RMD160_DIGEST_LENGTH;
95 	case SHA256_HASH_ALG:
96 		return 32;
97 	case SHA512_HASH_ALG:
98 		return 64;
99 	case TIGER_HASH_ALG:
100 	case TIGER2_HASH_ALG:
101 		return TIGER_DIGEST_LENGTH;
102 	default:
103 		printf("hash_any: bad algorithm\n");
104 		return 0;
105 	}
106 }
107 
108 /* initialise the hash structure */
109 int
110 digest_init(digest_t *hash, const uint32_t hashalg)
111 {
112 	if (hash == NULL) {
113 		return 0;
114 	}
115 	switch(hash->alg = hashalg) {
116 	case MD5_HASH_ALG:
117 		MD5Init(&hash->u.md5ctx);
118 		hash->size = 16;
119 		hash->prefix = prefix_md5;
120 		hash->len = sizeof(prefix_md5);
121 		hash->ctx = &hash->u.md5ctx;
122 		return 1;
123 	case SHA1_HASH_ALG:
124 		SHA1Init(&hash->u.sha1ctx);
125 		hash->size = 20;
126 		hash->prefix = prefix_sha1;
127 		hash->len = sizeof(prefix_sha1);
128 		hash->ctx = &hash->u.sha1ctx;
129 		return 1;
130 	case RIPEMD_HASH_ALG:
131 		RMD160Init(&hash->u.rmd160ctx);
132 		hash->size = 20;
133 		hash->prefix = prefix_rmd160;
134 		hash->len = sizeof(prefix_rmd160);
135 		hash->ctx = &hash->u.rmd160ctx;
136 		return 1;
137 	case SHA256_HASH_ALG:
138 		SHA256_Init(&hash->u.sha256ctx);
139 		hash->size = 32;
140 		hash->prefix = prefix_sha256;
141 		hash->len = sizeof(prefix_sha256);
142 		hash->ctx = &hash->u.sha256ctx;
143 		return 1;
144 	case SHA512_HASH_ALG:
145 		SHA512_Init(&hash->u.sha512ctx);
146 		hash->size = 64;
147 		hash->prefix = prefix_sha512;
148 		hash->len = sizeof(prefix_sha512);
149 		hash->ctx = &hash->u.sha512ctx;
150 		return 1;
151 	case TIGER_HASH_ALG:
152 		TIGER_Init(&hash->u.tigerctx);
153 		hash->size = TIGER_DIGEST_LENGTH;
154 		hash->prefix = prefix_tiger;
155 		hash->len = sizeof(prefix_tiger);
156 		hash->ctx = &hash->u.tigerctx;
157 		return 1;
158 	case TIGER2_HASH_ALG:
159 		TIGER2_Init(&hash->u.tigerctx);
160 		hash->size = TIGER_DIGEST_LENGTH;
161 		hash->prefix = prefix_tiger;
162 		hash->len = sizeof(prefix_tiger);
163 		hash->ctx = &hash->u.tigerctx;
164 		return 1;
165 	default:
166 		printf("hash_any: bad algorithm\n");
167 		return 0;
168 	}
169 }
170 
171 typedef struct rec_t {
172 	const char	*s;
173 	const unsigned	 alg;
174 } rec_t;
175 
176 static rec_t	hashalgs[] = {
177 	{	"md5",		MD5_HASH_ALG	},
178 	{	"sha1",		SHA1_HASH_ALG	},
179 	{	"ripemd",	RIPEMD_HASH_ALG	},
180 	{	"sha256",	SHA256_HASH_ALG	},
181 	{	"sha512",	SHA512_HASH_ALG	},
182 	{	"tiger",	TIGER_HASH_ALG	},
183 	{	"tiger2",	TIGER2_HASH_ALG	},
184 	{	NULL,		0		}
185 };
186 
187 /* initialise by string alg name */
188 unsigned
189 digest_get_alg(const char *hashalg)
190 {
191 	rec_t	*r;
192 
193 	for (r = hashalgs ; hashalg && r->s ; r++) {
194 		if (strcasecmp(r->s, hashalg) == 0) {
195 			return r->alg;
196 		}
197 	}
198 	return 0;
199 }
200 
201 int
202 digest_update(digest_t *hash, const uint8_t *data, size_t length)
203 {
204 	if (hash == NULL || data == NULL) {
205 		return 0;
206 	}
207 	switch(hash->alg) {
208 	case MD5_HASH_ALG:
209 		MD5Update(hash->ctx, data, (unsigned)length);
210 		return 1;
211 	case SHA1_HASH_ALG:
212 		SHA1Update(hash->ctx, data, (unsigned)length);
213 		return 1;
214 	case RIPEMD_HASH_ALG:
215 		RMD160Update(hash->ctx, data, (unsigned)length);
216 		return 1;
217 	case SHA256_HASH_ALG:
218 		SHA256_Update(hash->ctx, data, length);
219 		return 1;
220 	case SHA512_HASH_ALG:
221 		SHA512_Update(hash->ctx, data, length);
222 		return 1;
223 	case TIGER_HASH_ALG:
224 	case TIGER2_HASH_ALG:
225 		TIGER_Update(hash->ctx, data, length);
226 		return 1;
227 	default:
228 		printf("hash_any: bad algorithm\n");
229 		return 0;
230 	}
231 }
232 
233 unsigned
234 digest_final(uint8_t *out, digest_t *hash)
235 {
236 	if (hash == NULL || out == NULL) {
237 		return 0;
238 	}
239 	switch(hash->alg) {
240 	case MD5_HASH_ALG:
241 		MD5Final(out, hash->ctx);
242 		break;
243 	case SHA1_HASH_ALG:
244 		SHA1Final(out, hash->ctx);
245 		break;
246 	case RIPEMD_HASH_ALG:
247 		RMD160Final(out, hash->ctx);
248 		break;
249 	case SHA256_HASH_ALG:
250 		SHA256_Final(out, hash->ctx);
251 		break;
252 	case SHA512_HASH_ALG:
253 		SHA512_Final(out, hash->ctx);
254 		break;
255 	case TIGER_HASH_ALG:
256 		TIGER_Final(out, hash->ctx);
257 		break;
258 	default:
259 		printf("hash_any: bad algorithm\n");
260 		return 0;
261 	}
262 	(void) memset(hash->ctx, 0x0, hash->size);
263 	return (unsigned)hash->size;
264 }
265 
266 int
267 digest_length(digest_t *hash, unsigned hashedlen)
268 {
269 	uint8_t		 trailer[6];
270 
271 	if (hash == NULL) {
272 		return 0;
273 	}
274 	trailer[0] = V4_SIGNATURE;
275 	trailer[1] = 0xFF;
276 	trailer[2] = (uint8_t)((hashedlen >> 24) & 0xff);
277 	trailer[3] = (uint8_t)((hashedlen >> 16) & 0xff);
278 	trailer[4] = (uint8_t)((hashedlen >> 8) & 0xff);
279 	trailer[5] = (uint8_t)(hashedlen & 0xff);
280 	digest_update(hash, trailer, sizeof(trailer));
281 	return 1;
282 }
283 
284 unsigned
285 digest_get_prefix(unsigned hashalg, uint8_t *prefix, size_t size)
286 {
287 	USE_ARG(size);
288 	if (prefix == NULL) {
289 		return 0;
290 	}
291 	switch (hashalg) {
292 	case MD5_HASH_ALG:
293 		memcpy(prefix, prefix_md5, sizeof(prefix_md5));
294 		return sizeof(prefix_md5);
295 	case SHA1_HASH_ALG:
296 		memcpy(prefix, prefix_sha1, sizeof(prefix_sha1));
297 		return sizeof(prefix_sha1);
298 	case SHA256_HASH_ALG:
299 		memcpy(prefix, prefix_sha256, sizeof(prefix_sha256));
300 		return sizeof(prefix_sha256);
301 	default:
302 		printf("digest_get_prefix: unknown hash algorithm: %d\n", hashalg);
303 		return 0;
304 	}
305 }
306 
307