1 /**
2 * SHA-{224,256}
3 * 
4 * Copyright:
5 * (C) 1999-2011 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *      2007 FlexSecure GmbH
8 *
9 * License:
10 * Botan is released under the Simplified BSD License (see LICENSE.md)
11 */
12 module botan.hash.sha2_32;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_SHA2_32):
16 
17 import botan.hash.mdx_hash;
18 import botan.hash.sha2_32;
19 import botan.utils.loadstor;
20 import botan.utils.rotate;
21 import botan.hash.hash;
22 import botan.utils.types;
23 import std.format : format;
24 
25 /**
26 * SHA-224
27 */
28 final class SHA224 : MDxHashFunction, HashFunction
29 {
30 public:
31     
32     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
33     override @property string name() const { return "SHA-224"; }
34     override @property size_t outputLength() const { return 28; }
35     override HashFunction clone() const { return new SHA224; }
36 
37     /*
38     * Clear memory of sensitive data
39     */
40     override void clear()
41     {
42         super.clear();
43         m_digest[0] = 0xC1059ED8;
44         m_digest[1] = 0x367CD507;
45         m_digest[2] = 0x3070DD17;
46         m_digest[3] = 0xF70E5939;
47         m_digest[4] = 0xFFC00B31;
48         m_digest[5] = 0x68581511;
49         m_digest[6] = 0x64F98FA7;
50         m_digest[7] = 0xBEFA4FA4;
51     }
52 
53 
54     this()
55     { 
56         super(64, true, true);
57         m_digest.length = 8;
58         clear(); 
59     }
60 
61 protected:
62     /*
63     * SHA-224 compression function
64     */
65     override void compressN(const(ubyte)* input, size_t blocks)
66     {
67 		assert(m_digest.length == 8);
68 		uint[8] digest = m_digest.ptr[0 .. 8];
69 		compress(digest, input, blocks);
70 		m_digest[] = digest.ptr[0 .. 8];
71     }
72 
73     /*
74     * Copy out the digest
75     */
76     override void copyOut(ubyte* output)
77     {
78         for (size_t i = 0; i != outputLength(); i += 4)
79             storeBigEndian(m_digest[i/4], output + i);
80     }
81 
82     SecureVector!uint m_digest;
83 }
84 
85 
86 /**
87 * SHA-256
88 */
89 class SHA256 : MDxHashFunction, HashFunction
90 {
91 public:
92     
93     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
94     override @property string name() const { return "SHA-256"; }
95     override @property size_t outputLength() const { return 32; }
96     override HashFunction clone() const { return new SHA256; }
97 
98     /*
99     * Clear memory of sensitive data
100     */
101     override void clear()
102     {
103         super.clear();
104         m_digest[0] = 0x6A09E667;
105         m_digest[1] = 0xBB67AE85;
106         m_digest[2] = 0x3C6EF372;
107         m_digest[3] = 0xA54FF53A;
108         m_digest[4] = 0x510E527F;
109         m_digest[5] = 0x9B05688C;
110         m_digest[6] = 0x1F83D9AB;
111         m_digest[7] = 0x5BE0CD19;
112     }
113 
114     this()
115     { 
116         super(64, true, true);
117         m_digest.length = 8;
118         clear();
119     }
120 protected:
121     /*
122     * SHA-256 compression function
123     */
124     override void compressN(const(ubyte)* input, size_t blocks)
125     {
126 		assert(m_digest.length == 8);
127 		uint[8] digest = m_digest.ptr[0 .. 8];
128 		compress(digest, input, blocks);
129 		m_digest[] = digest.ptr[0 .. 8];
130     }
131 
132     /*
133     * Copy out the digest
134     */
135     override void copyOut(ubyte* output)
136     {
137         for (size_t i = 0; i != outputLength(); i += 4)
138             storeBigEndian(m_digest[i/4], output + i);
139     }
140 
141 
142     SecureVector!uint m_digest;
143 }
144 
145 private:
146 pure:
147 
148 /*
149 * SHA-256 Rho Function
150 */
151 uint rho(uint X, uint rot1, uint rot2, uint rot3)
152 {
153     return (rotateRight(X, rot1) ^ rotateRight(X, rot2) ^ rotateRight(X, rot3));
154 }
155 
156 /*
157 * SHA-256 Sigma Function
158 */
159 uint sigma(uint X, uint rot1, uint rot2, uint shift)
160 {
161     return (rotateRight(X, rot1) ^ rotateRight(X, rot2) ^ (X >> shift));
162 }
163 
164 /*
165 * SHA-256 F1 Function
166 *
167 * Use a macro as many compilers won't  a function this big,
168 * even though it is much faster if d.
169 */
170 enum string SHA2_32_F(alias _A, alias _B, alias _C, alias _D, alias _E, alias _F, alias _G, alias _H, alias _M1, alias _M2, alias _M3, alias _M4, uint magic) = q{
171     %9$s += %1$s + rho(%6$s, 6, 11, 25) + ((%6$s & %7$s) ^ (~%6$s & %8$s)) + %10$s;
172     %5$s += %9$s;
173     %9$s += rho(%2$s, 2, 13, 22) + ((%2$s & %3$s) | ((%2$s | %3$s) & %4$s));
174     %10$s += sigma(%11$s, 17, 19, 10) + %12$s + sigma(%13$s, 7, 18, 3);
175 }.format(magic,
176     __traits(identifier, _A), __traits(identifier, _B), __traits(identifier, _C), __traits(identifier, _D),
177     __traits(identifier, _E), __traits(identifier, _F), __traits(identifier, _G), __traits(identifier, _H),
178     __traits(identifier, _M1), __traits(identifier, _M2), __traits(identifier, _M3), __traits(identifier, _M4));
179 
180 /*
181 * SHA-224 / SHA-256 compression function
182 */
183 void compress(ref uint[8] digest,
184               const(ubyte)* input, size_t blocks) pure
185 {
186     uint A = digest[0], B = digest[1], C = digest[2],
187         D = digest[3], E = digest[4], F = digest[5],
188         G = digest[6], H = digest[7];
189     
190     foreach (size_t i; 0 .. blocks)
191     {
192         uint W00 = loadBigEndian!uint(input,  0);
193         uint W01 = loadBigEndian!uint(input,  1);
194         uint W02 = loadBigEndian!uint(input,  2);
195         uint W03 = loadBigEndian!uint(input,  3);
196         uint W04 = loadBigEndian!uint(input,  4);
197         uint W05 = loadBigEndian!uint(input,  5);
198         uint W06 = loadBigEndian!uint(input,  6);
199         uint W07 = loadBigEndian!uint(input,  7);
200         uint W08 = loadBigEndian!uint(input,  8);
201         uint W09 = loadBigEndian!uint(input,  9);
202         uint W10 = loadBigEndian!uint(input, 10);
203         uint W11 = loadBigEndian!uint(input, 11);
204         uint W12 = loadBigEndian!uint(input, 12);
205         uint W13 = loadBigEndian!uint(input, 13);
206         uint W14 = loadBigEndian!uint(input, 14);
207         uint W15 = loadBigEndian!uint(input, 15);
208         
209         mixin(
210             SHA2_32_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x428A2F98) ~ 
211             SHA2_32_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x71374491) ~ 
212             SHA2_32_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xB5C0FBCF) ~ 
213             SHA2_32_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xE9B5DBA5) ~ 
214             SHA2_32_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x3956C25B) ~ 
215             SHA2_32_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x59F111F1) ~ 
216             SHA2_32_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x923F82A4) ~ 
217             SHA2_32_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0xAB1C5ED5) ~ 
218             SHA2_32_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xD807AA98) ~ 
219             SHA2_32_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x12835B01) ~ 
220             SHA2_32_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x243185BE) ~ 
221             SHA2_32_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x550C7DC3) ~ 
222             SHA2_32_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x72BE5D74) ~ 
223             SHA2_32_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x80DEB1FE) ~ 
224             SHA2_32_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x9BDC06A7) ~ 
225             SHA2_32_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC19BF174) ~ 
226             SHA2_32_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xE49B69C1) ~ 
227             SHA2_32_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xEFBE4786) ~ 
228             SHA2_32_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x0FC19DC6) ~ 
229             SHA2_32_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x240CA1CC) ~ 
230             SHA2_32_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x2DE92C6F) ~ 
231             SHA2_32_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4A7484AA) ~ 
232             SHA2_32_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5CB0A9DC) ~ 
233             SHA2_32_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x76F988DA) ~ 
234             SHA2_32_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x983E5152) ~ 
235             SHA2_32_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA831C66D) ~ 
236             SHA2_32_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xB00327C8) ~ 
237             SHA2_32_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xBF597FC7) ~ 
238             SHA2_32_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xC6E00BF3) ~ 
239             SHA2_32_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD5A79147) ~ 
240             SHA2_32_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x06CA6351) ~ 
241             SHA2_32_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x14292967) ~ 
242             SHA2_32_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x27B70A85) ~ 
243             SHA2_32_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x2E1B2138) ~ 
244             SHA2_32_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x4D2C6DFC) ~ 
245             SHA2_32_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x53380D13) ~ 
246             SHA2_32_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x650A7354) ~ 
247             SHA2_32_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x766A0ABB) ~ 
248             SHA2_32_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x81C2C92E) ~ 
249             SHA2_32_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x92722C85) ~ 
250             SHA2_32_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xA2BFE8A1) ~ 
251             SHA2_32_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA81A664B) ~ 
252             SHA2_32_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xC24B8B70) ~ 
253             SHA2_32_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xC76C51A3) ~ 
254             SHA2_32_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xD192E819) ~ 
255             SHA2_32_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD6990624) ~ 
256             SHA2_32_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xF40E3585) ~ 
257             SHA2_32_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x106AA070) ~ 
258             SHA2_32_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x19A4C116) ~ 
259             SHA2_32_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x1E376C08) ~ 
260             SHA2_32_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x2748774C) ~ 
261             SHA2_32_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x34B0BCB5) ~ 
262             SHA2_32_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x391C0CB3) ~ 
263             SHA2_32_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4ED8AA4A) ~ 
264             SHA2_32_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5B9CCA4F) ~ 
265             SHA2_32_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x682E6FF3) ~ 
266             SHA2_32_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x748F82EE) ~ 
267             SHA2_32_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x78A5636F) ~ 
268             SHA2_32_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x84C87814) ~ 
269             SHA2_32_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x8CC70208) ~ 
270             SHA2_32_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x90BEFFFA) ~ 
271             SHA2_32_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xA4506CEB) ~ 
272             SHA2_32_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xBEF9A3F7) ~ 
273             SHA2_32_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC67178F2)
274             );
275         
276         A = (digest[0] += A);
277         B = (digest[1] += B);
278         C = (digest[2] += C);
279         D = (digest[3] += D);
280         E = (digest[4] += E);
281         F = (digest[5] += F);
282         G = (digest[6] += G);
283         H = (digest[7] += H);
284         
285         input += 64;
286     }
287 }