1 /*-
2  * Copyright (c) 2006, 2007
3  *	Thorsten Glaser <tg@mirbsd.de>
4  * The adler32 algorithm is
5  * Copyright (C) 1995 Mark Adler
6  *
7  * Provided that these terms and disclaimer and all copyright notices
8  * are retained or reproduced in an accompanying document, permission
9  * is granted to deal in this work without restriction, including un-
10  * limited rights to use, publicly perform, distribute, sell, modify,
11  * merge, give away, or sublicence.
12  *
13  * Advertising materials mentioning features or use of this work must
14  * display the following acknowledgement:
15  *	This product includes material provided by Thorsten Glaser.
16  *
17  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
18  * the utmost extent permitted by applicable law, neither express nor
19  * implied; without malicious intent or gross negligence. In no event
20  * may a licensor, author or contributor be held liable for indirect,
21  * direct, other damage, loss, or other issues arising in any way out
22  * of dealing in the work, even if advised of the possibility of such
23  * damage or existence of a defect, except proven that it results out
24  * of said person's immediate fault when using the work as intended.
25  */
26 
27 #include <sys/param.h>
28 #include <adler32.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 __RCSID("$MirOS: src/lib/libc/hash/adh32.c,v 1.2 2007/08/19 12:03:13 tg Exp $");
33 
34 void
ADLER32Init(ADLER32_CTX * ctx)35 ADLER32Init(ADLER32_CTX *ctx)
36 {
37 	if (ctx != NULL)
38 		*ctx = 1;
39 }
40 
41 /*-
42  * See also:
43  *	contrib/hosted/fwcf/adler.h
44  *	src/lib/libc/hash/adh32.c
45  *	src/kern/z/adler32s.c
46  *	src/kern/z/adler32_i386.S
47  */
48 void
ADLER32Update(ADLER32_CTX * ctx,const uint8_t * buf,size_t len)49 ADLER32Update(ADLER32_CTX *ctx, const uint8_t *buf, size_t len)
50 {
51 	uint32_t s1, s2, n;
52 
53 	if (ctx == NULL)
54 		return;
55 
56 	s1 = (s2 = *ctx) & 0xFFFF;;
57 	s2 >>= 16;
58 
59 #define ADLER_BASE 65521 /* largest prime smaller than 65536 */
60 #define ADLER_NMAX 5552	 /* largest n: 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
61 	while (len) {
62 		len -= (n = MIN(len, ADLER_NMAX));
63 		while (n--) {
64 			s1 += *buf++;
65 			s2 += s1;
66 		}
67 		s1 %= ADLER_BASE;
68 		s2 %= ADLER_BASE;
69 	}
70 
71 	*ctx = s1 | (s2 << 16);
72 }
73 
74 void
ADLER32Final(uint8_t * dst,ADLER32_CTX * ctx)75 ADLER32Final(uint8_t *dst, ADLER32_CTX *ctx)
76 {
77 	uint32_t tmp = htobe32(*ctx);
78 
79 	if (dst)
80 		memcpy(dst, &tmp, 4);
81 	*ctx = 0;
82 }
83