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