1 /**
2 * Adler32
3 * 
4 * Copyright:
5 * (C) 1999-2007 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.checksum.adler32;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_ADLER32):
15 
16 import botan.utils.loadstor;
17 import botan.hash.hash;
18 /**
19 * The Adler32 checksum, used in zlib
20 */
21 final class Adler32 : HashFunction
22 {
23 public:
24     override @property string name() const { return "Adler32"; }
25     override @property size_t outputLength() const { return 4; }
26     override @property size_t hashBlockSize() const { return 0; }
27     override HashFunction clone() const { return new Adler32; }
28 
29     override void clear() { m_S1 = 1; m_S2 = 0; }
30 
31     this() { clear(); }
32     ~this() { clear(); }
33 protected:
34     /*
35     * Update an Adler32 Checksum
36     */
37     override void addData(const(ubyte)* input, size_t length)
38     {
39         __gshared immutable size_t PROCESS_AMOUNT = 5552;
40         
41         while (length >= PROCESS_AMOUNT)
42         {
43             adler32Update(input, PROCESS_AMOUNT, m_S1, m_S2);
44             input += PROCESS_AMOUNT;
45             length -= PROCESS_AMOUNT;
46         }
47         
48         adler32Update(input, length, m_S1, m_S2);
49     }
50 
51     /*
52     * Finalize an Adler32 Checksum
53     */
54     override void finalResult(ubyte* output)
55     {
56         storeBigEndian(output, m_S2, m_S1);
57         clear();
58     }
59 
60     ushort m_S1, m_S2;
61 }
62 
63 package:
64 
65 void adler32Update(const(ubyte)* input, size_t length, ref ushort S1, ref ushort S2)
66 {
67     uint S1x = S1;
68     uint S2x = S2;
69     
70     while (length >= 16)
71     {
72         S1x += input[ 0]; S2x += S1x;
73         S1x += input[ 1]; S2x += S1x;
74         S1x += input[ 2]; S2x += S1x;
75         S1x += input[ 3]; S2x += S1x;
76         S1x += input[ 4]; S2x += S1x;
77         S1x += input[ 5]; S2x += S1x;
78         S1x += input[ 6]; S2x += S1x;
79         S1x += input[ 7]; S2x += S1x;
80         S1x += input[ 8]; S2x += S1x;
81         S1x += input[ 9]; S2x += S1x;
82         S1x += input[10]; S2x += S1x;
83         S1x += input[11]; S2x += S1x;
84         S1x += input[12]; S2x += S1x;
85         S1x += input[13]; S2x += S1x;
86         S1x += input[14]; S2x += S1x;
87         S1x += input[15]; S2x += S1x;
88         input += 16;
89         length -= 16;
90     }
91     
92     foreach (size_t j; 0 .. length)
93     {
94         S1x += input[j];
95         S2x += S1x;
96     }
97     
98     S1 = S1x % 65521;
99     S2 = S2x % 65521;
100 }
101