1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file adler32.c
7 Adler-32 checksum algorithm
8 Written and placed in the public domain by Wei Dai
9 Adapted for libtomcrypt by Steffen Jaeckel
10 */
11 #ifdef LTC_ADLER32
12
13 static const unsigned long s_adler32_base = 65521;
14
adler32_init(adler32_state * ctx)15 void adler32_init(adler32_state *ctx)
16 {
17 LTC_ARGCHKVD(ctx != NULL);
18 ctx->s[0] = 1;
19 ctx->s[1] = 0;
20 }
21
adler32_update(adler32_state * ctx,const unsigned char * input,unsigned long length)22 void adler32_update(adler32_state *ctx, const unsigned char *input, unsigned long length)
23 {
24 unsigned long s1, s2;
25
26 LTC_ARGCHKVD(ctx != NULL);
27 LTC_ARGCHKVD(input != NULL);
28 s1 = ctx->s[0];
29 s2 = ctx->s[1];
30
31 if (length % 8 != 0) {
32 do {
33 s1 += *input++;
34 s2 += s1;
35 length--;
36 } while (length % 8 != 0);
37
38 if (s1 >= s_adler32_base) {
39 s1 -= s_adler32_base;
40 }
41 s2 %= s_adler32_base;
42 }
43
44 while (length > 0) {
45 s1 += input[0];
46 s2 += s1;
47 s1 += input[1];
48 s2 += s1;
49 s1 += input[2];
50 s2 += s1;
51 s1 += input[3];
52 s2 += s1;
53 s1 += input[4];
54 s2 += s1;
55 s1 += input[5];
56 s2 += s1;
57 s1 += input[6];
58 s2 += s1;
59 s1 += input[7];
60 s2 += s1;
61
62 length -= 8;
63 input += 8;
64
65 if (s1 >= s_adler32_base) {
66 s1 -= s_adler32_base;
67 }
68 s2 %= s_adler32_base;
69 }
70
71 LTC_ARGCHKVD(s1 < s_adler32_base);
72 LTC_ARGCHKVD(s2 < s_adler32_base);
73
74 ctx->s[0] = (unsigned short)s1;
75 ctx->s[1] = (unsigned short)s2;
76 }
77
adler32_finish(const adler32_state * ctx,void * hash,unsigned long size)78 void adler32_finish(const adler32_state *ctx, void *hash, unsigned long size)
79 {
80 unsigned char* h;
81
82 LTC_ARGCHKVD(ctx != NULL);
83 LTC_ARGCHKVD(hash != NULL);
84
85 h = hash;
86
87 switch (size) {
88 default:
89 h[3] = ctx->s[0] & 0x0ff;
90 /* FALLTHROUGH */
91 case 3:
92 h[2] = (ctx->s[0] >> 8) & 0x0ff;
93 /* FALLTHROUGH */
94 case 2:
95 h[1] = ctx->s[1] & 0x0ff;
96 /* FALLTHROUGH */
97 case 1:
98 h[0] = (ctx->s[1] >> 8) & 0x0ff;
99 /* FALLTHROUGH */
100 case 0:
101 ;
102 }
103 }
104
adler32_test(void)105 int adler32_test(void)
106 {
107 #ifndef LTC_TEST
108 return CRYPT_NOP;
109 #else
110 const void* in = "libtomcrypt";
111 const unsigned char adler32[] = { 0x1b, 0xe8, 0x04, 0xba };
112 unsigned char out[4];
113 adler32_state ctx;
114 adler32_init(&ctx);
115 adler32_update(&ctx, in, XSTRLEN(in));
116 adler32_finish(&ctx, out, 4);
117 if (compare_testvector(adler32, 4, out, 4, "adler32", 0)) {
118 return CRYPT_FAIL_TESTVECTOR;
119 }
120 return CRYPT_OK;
121 #endif
122 }
123 #endif
124