1 /**
2 * SHA-{384,512}
3 * 
4 * Copyright:
5 * (C) 1999-2010 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.hash.sha2_64;
12 
13 import botan.constants;
14 static if (BOTAN_HAS_SHA2_64):
15 
16 import botan.hash.mdx_hash;
17 import botan.utils.loadstor;
18 import botan.utils.rotate;
19 import botan.utils.types;
20 import std.format : format;
21 
22 /**
23 * SHA-384
24 */
25 final class SHA384 : MDxHashFunction, HashFunction
26 {
27 public:
28     
29     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
30     override @property string name() const { return "SHA-384"; }
31     override @property size_t outputLength() const { return 48; }
32     override HashFunction clone() const { return new SHA384; }
33 
34     /*
35     * Clear memory of sensitive data
36     */
37     override void clear()
38     {
39         super.clear();
40         m_digest[0] = 0xCBBB9D5DC1059ED8;
41         m_digest[1] = 0x629A292A367CD507;
42         m_digest[2] = 0x9159015A3070DD17;
43         m_digest[3] = 0x152FECD8F70E5939;
44         m_digest[4] = 0x67332667FFC00B31;
45         m_digest[5] = 0x8EB44A8768581511;
46         m_digest[6] = 0xDB0C2E0D64F98FA7;
47         m_digest[7] = 0x47B5481DBEFA4FA4;
48     }
49 
50     this()
51     {  
52         super(128, true, true, 16);
53         m_digest.length = 8;
54         clear();
55     }
56 
57 protected:
58     /*
59     * SHA-384 compression function
60     */
61     override void compressN(const(ubyte)* input, size_t blocks)
62     {
63         compress(m_digest, input, blocks);
64     }
65 
66     /*
67     * Copy out the digest
68     */
69     override void copyOut(ubyte* output)
70     {
71         for (size_t i = 0; i != outputLength(); i += 8)
72             storeBigEndian(m_digest[i/8], output + i);
73     }
74 
75     SecureVector!ulong m_digest;
76 }
77 
78 /**
79 * SHA-512
80 */
81 final class SHA512 : MDxHashFunction, HashFunction
82 {
83 public:
84     
85     override @property size_t hashBlockSize() const { return super.hashBlockSize(); }
86     override @property string name() const { return "SHA-512"; }
87     override @property size_t outputLength() const { return 64; }
88     override HashFunction clone() const { return new SHA512; }
89 
90     /*
91     * Clear memory of sensitive data
92     */
93     override void clear()
94     {
95         super.clear();
96         m_digest[0] = 0x6A09E667F3BCC908;
97         m_digest[1] = 0xBB67AE8584CAA73B;
98         m_digest[2] = 0x3C6EF372FE94F82B;
99         m_digest[3] = 0xA54FF53A5F1D36F1;
100         m_digest[4] = 0x510E527FADE682D1;
101         m_digest[5] = 0x9B05688C2B3E6C1F;
102         m_digest[6] = 0x1F83D9ABFB41BD6B;
103         m_digest[7] = 0x5BE0CD19137E2179;
104     }
105 
106     this() 
107     { 
108         super(128, true, true, 16);
109         m_digest.length = 8;
110         clear(); 
111     }
112 
113 protected:
114     /*
115     * SHA-512 compression function
116     */
117     override void compressN(const(ubyte)* input, size_t blocks)
118     {
119         compress(m_digest, input, blocks);
120     }
121 
122     /*
123     * Copy out the digest
124     */
125     override void copyOut(ubyte* output)
126     {
127         for (size_t i = 0; i != outputLength(); i += 8)
128             storeBigEndian(m_digest[i/8], output + i);
129     }
130 
131     SecureVector!ulong m_digest;
132 }
133 
134 private:
135 pure:
136 
137 /*
138 * SHA-{384,512} Rho Function
139 */
140 ulong rho(ulong X, uint rot1, uint rot2, uint rot3)
141 {
142     return (rotateRight(X, rot1) ^ rotateRight(X, rot2) ^
143             rotateRight(X, rot3));
144 }
145 
146 /*
147 * SHA-{384,512} Sigma Function
148 */
149 ulong sigma(ulong X, uint rot1, uint rot2, uint shift)
150 {
151     return (rotateRight(X, rot1) ^ rotateRight(X, rot2) ^ (X >> shift));
152 }
153 
154 /*
155 * SHA-512 F1 Function
156 *
157 * Use a macro as many compilers won't  a function this big,
158 * even though it is much faster if d.
159 */
160 enum string SHA2_64_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, ulong magic) = q{
161     %9$s += %1$sUL + rho(%6$s, 14, 18, 41) + ((%6$s & %7$s) ^ (~%6$s & %8$s)) + %10$s;
162     %5$s += %9$s;
163     %9$s += rho(%2$s, 28, 34, 39) + ((%2$s & %3$s) | ((%2$s | %3$s) & %4$s));
164     %10$s += sigma(%11$s, 19, 61, 6) + %12$s + sigma(%13$s, 1, 8, 7);
165 }.format(magic,
166     __traits(identifier, _A), __traits(identifier, _B), __traits(identifier, _C), __traits(identifier, _D),
167     __traits(identifier, _E), __traits(identifier, _F), __traits(identifier, _G), __traits(identifier, _H),
168     __traits(identifier, _M1), __traits(identifier, _M2), __traits(identifier, _M3), __traits(identifier, _M4));
169 
170 /*
171 * SHA-{384,512} Compression Function
172 */
173 void compress(ref SecureVector!ulong digest,
174               const(ubyte)* input, size_t blocks) pure
175 {
176     ulong A = digest[0], B = digest[1], C = digest[2],
177         D = digest[3], E = digest[4], F = digest[5],
178         G = digest[6], H = digest[7];
179     
180     foreach (size_t i; 0 .. blocks)
181     {
182         ulong W00 = loadBigEndian!ulong(input,  0);
183         ulong W01 = loadBigEndian!ulong(input,  1);
184         ulong W02 = loadBigEndian!ulong(input,  2);
185         ulong W03 = loadBigEndian!ulong(input,  3);
186         ulong W04 = loadBigEndian!ulong(input,  4);
187         ulong W05 = loadBigEndian!ulong(input,  5);
188         ulong W06 = loadBigEndian!ulong(input,  6);
189         ulong W07 = loadBigEndian!ulong(input,  7);
190         ulong W08 = loadBigEndian!ulong(input,  8);
191         ulong W09 = loadBigEndian!ulong(input,  9);
192         ulong W10 = loadBigEndian!ulong(input, 10);
193         ulong W11 = loadBigEndian!ulong(input, 11);
194         ulong W12 = loadBigEndian!ulong(input, 12);
195         ulong W13 = loadBigEndian!ulong(input, 13);
196         ulong W14 = loadBigEndian!ulong(input, 14);
197         ulong W15 = loadBigEndian!ulong(input, 15);
198         
199         mixin(
200             SHA2_64_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x428A2F98D728AE22) ~
201             SHA2_64_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x7137449123EF65CD) ~
202             SHA2_64_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xB5C0FBCFEC4D3B2F) ~
203             SHA2_64_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xE9B5DBA58189DBBC) ~
204             SHA2_64_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x3956C25BF348B538) ~
205             SHA2_64_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x59F111F1B605D019) ~
206             SHA2_64_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x923F82A4AF194F9B) ~
207             SHA2_64_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0xAB1C5ED5DA6D8118) ~
208             SHA2_64_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xD807AA98A3030242) ~
209             SHA2_64_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x12835B0145706FBE) ~
210             SHA2_64_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x243185BE4EE4B28C) ~
211             SHA2_64_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x550C7DC3D5FFB4E2) ~
212             SHA2_64_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x72BE5D74F27B896F) ~
213             SHA2_64_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x80DEB1FE3B1696B1) ~
214             SHA2_64_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x9BDC06A725C71235) ~
215             SHA2_64_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC19BF174CF692694) ~
216             SHA2_64_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xE49B69C19EF14AD2) ~
217             SHA2_64_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xEFBE4786384F25E3) ~
218             SHA2_64_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x0FC19DC68B8CD5B5) ~
219             SHA2_64_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x240CA1CC77AC9C65) ~
220             SHA2_64_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x2DE92C6F592B0275) ~
221             SHA2_64_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4A7484AA6EA6E483) ~
222             SHA2_64_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5CB0A9DCBD41FBD4) ~
223             SHA2_64_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x76F988DA831153B5) ~
224             SHA2_64_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x983E5152EE66DFAB) ~
225             SHA2_64_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA831C66D2DB43210) ~
226             SHA2_64_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xB00327C898FB213F) ~
227             SHA2_64_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xBF597FC7BEEF0EE4) ~
228             SHA2_64_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xC6E00BF33DA88FC2) ~
229             SHA2_64_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD5A79147930AA725) ~
230             SHA2_64_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x06CA6351E003826F) ~
231             SHA2_64_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x142929670A0E6E70) ~
232             SHA2_64_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x27B70A8546D22FFC) ~
233             SHA2_64_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x2E1B21385C26C926) ~
234             SHA2_64_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x4D2C6DFC5AC42AED) ~
235             SHA2_64_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x53380D139D95B3DF) ~
236             SHA2_64_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x650A73548BAF63DE) ~
237             SHA2_64_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x766A0ABB3C77B2A8) ~
238             SHA2_64_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x81C2C92E47EDAEE6) ~
239             SHA2_64_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x92722C851482353B) ~
240             SHA2_64_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0xA2BFE8A14CF10364) ~
241             SHA2_64_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0xA81A664BBC423001) ~
242             SHA2_64_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0xC24B8B70D0F89791) ~
243             SHA2_64_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0xC76C51A30654BE30) ~
244             SHA2_64_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0xD192E819D6EF5218) ~
245             SHA2_64_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xD69906245565A910) ~
246             SHA2_64_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xF40E35855771202A) ~
247             SHA2_64_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x106AA07032BBD1B8) ~
248             SHA2_64_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0x19A4C116B8D2D0C8) ~
249             SHA2_64_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0x1E376C085141AB53) ~
250             SHA2_64_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0x2748774CDF8EEB99) ~
251             SHA2_64_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0x34B0BCB5E19B48A8) ~
252             SHA2_64_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x391C0CB3C5C95A63) ~
253             SHA2_64_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x4ED8AA4AE3418ACB) ~
254             SHA2_64_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x5B9CCA4F7763E373) ~
255             SHA2_64_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x682E6FF3D6B2B8A3) ~
256             SHA2_64_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x748F82EE5DEFB2FC) ~
257             SHA2_64_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x78A5636F43172F60) ~
258             SHA2_64_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x84C87814A1F0AB72) ~
259             SHA2_64_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x8CC702081A6439EC) ~
260             SHA2_64_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x90BEFFFA23631E28) ~
261             SHA2_64_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0xA4506CEBDE82BDE9) ~
262             SHA2_64_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0xBEF9A3F7B2C67915) ~
263             SHA2_64_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0xC67178F2E372532B) ~
264             SHA2_64_F!(A, B, C, D, E, F, G, H, W00, W14, W09, W01, 0xCA273ECEEA26619C) ~
265             SHA2_64_F!(H, A, B, C, D, E, F, G, W01, W15, W10, W02, 0xD186B8C721C0C207) ~
266             SHA2_64_F!(G, H, A, B, C, D, E, F, W02, W00, W11, W03, 0xEADA7DD6CDE0EB1E) ~
267             SHA2_64_F!(F, G, H, A, B, C, D, E, W03, W01, W12, W04, 0xF57D4F7FEE6ED178) ~
268             SHA2_64_F!(E, F, G, H, A, B, C, D, W04, W02, W13, W05, 0x06F067AA72176FBA) ~
269             SHA2_64_F!(D, E, F, G, H, A, B, C, W05, W03, W14, W06, 0x0A637DC5A2C898A6) ~
270             SHA2_64_F!(C, D, E, F, G, H, A, B, W06, W04, W15, W07, 0x113F9804BEF90DAE) ~
271             SHA2_64_F!(B, C, D, E, F, G, H, A, W07, W05, W00, W08, 0x1B710B35131C471B) ~
272             SHA2_64_F!(A, B, C, D, E, F, G, H, W08, W06, W01, W09, 0x28DB77F523047D84) ~
273             SHA2_64_F!(H, A, B, C, D, E, F, G, W09, W07, W02, W10, 0x32CAAB7B40C72493) ~
274             SHA2_64_F!(G, H, A, B, C, D, E, F, W10, W08, W03, W11, 0x3C9EBE0A15C9BEBC) ~
275             SHA2_64_F!(F, G, H, A, B, C, D, E, W11, W09, W04, W12, 0x431D67C49C100D4C) ~
276             SHA2_64_F!(E, F, G, H, A, B, C, D, W12, W10, W05, W13, 0x4CC5D4BECB3E42B6) ~
277             SHA2_64_F!(D, E, F, G, H, A, B, C, W13, W11, W06, W14, 0x597F299CFC657E2A) ~
278             SHA2_64_F!(C, D, E, F, G, H, A, B, W14, W12, W07, W15, 0x5FCB6FAB3AD6FAEC) ~
279             SHA2_64_F!(B, C, D, E, F, G, H, A, W15, W13, W08, W00, 0x6C44198C4A475817)
280             );
281         
282         A = (digest[0] += A);
283         B = (digest[1] += B);
284         C = (digest[2] += C);
285         D = (digest[3] += D);
286         E = (digest[4] += E);
287         F = (digest[5] += F);
288         G = (digest[6] += G);
289         H = (digest[7] += H);
290         
291         input += 128;
292     }
293 }