1 package org.bouncycastle.crypto.digests;
2 
3 import org.bouncycastle.crypto.ExtendedDigest;
4 import org.bouncycastle.util.Memoable;
5 import org.bouncycastle.util.Pack;
6 
7 /**
8  * Base class for SHA-384 and SHA-512.
9  */
10 public abstract class LongDigest
11     implements ExtendedDigest, Memoable, EncodableDigest
12 {
13     private static final int BYTE_LENGTH = 128;
14 
15     private byte[] xBuf = new byte[8];
16     private int     xBufOff;
17 
18     private long    byteCount1;
19     private long    byteCount2;
20 
21     protected long    H1, H2, H3, H4, H5, H6, H7, H8;
22 
23     private long[]  W = new long[80];
24     private int     wOff;
25 
26     /**
27      * Constructor for variable length word
28      */
LongDigest()29     protected LongDigest()
30     {
31         xBufOff = 0;
32 
33         reset();
34     }
35 
36     /**
37      * Copy constructor.  We are using copy constructors in place
38      * of the Object.clone() interface as this interface is not
39      * supported by J2ME.
40      */
LongDigest(LongDigest t)41     protected LongDigest(LongDigest t)
42     {
43         copyIn(t);
44     }
45 
copyIn(LongDigest t)46     protected void copyIn(LongDigest t)
47     {
48         System.arraycopy(t.xBuf, 0, xBuf, 0, t.xBuf.length);
49 
50         xBufOff = t.xBufOff;
51         byteCount1 = t.byteCount1;
52         byteCount2 = t.byteCount2;
53 
54         H1 = t.H1;
55         H2 = t.H2;
56         H3 = t.H3;
57         H4 = t.H4;
58         H5 = t.H5;
59         H6 = t.H6;
60         H7 = t.H7;
61         H8 = t.H8;
62 
63         System.arraycopy(t.W, 0, W, 0, t.W.length);
64         wOff = t.wOff;
65     }
66 
populateState(byte[] state)67     protected void populateState(byte[] state)
68     {
69         System.arraycopy(xBuf, 0, state, 0, xBufOff);
70         Pack.intToBigEndian(xBufOff, state, 8);
71         Pack.longToBigEndian(byteCount1, state, 12);
72         Pack.longToBigEndian(byteCount2, state, 20);
73         Pack.longToBigEndian(H1, state, 28);
74         Pack.longToBigEndian(H2, state, 36);
75         Pack.longToBigEndian(H3, state, 44);
76         Pack.longToBigEndian(H4, state, 52);
77         Pack.longToBigEndian(H5, state, 60);
78         Pack.longToBigEndian(H6, state, 68);
79         Pack.longToBigEndian(H7, state, 76);
80         Pack.longToBigEndian(H8, state, 84);
81 
82         Pack.intToBigEndian(wOff, state, 92);
83         for (int i = 0; i < wOff; i++)
84         {
85             Pack.longToBigEndian(W[i], state, 96 + (i * 8));
86         }
87     }
88 
restoreState(byte[] encodedState)89     protected void restoreState(byte[] encodedState)
90     {
91         xBufOff = Pack.bigEndianToInt(encodedState, 8);
92         System.arraycopy(encodedState, 0, xBuf, 0, xBufOff);
93         byteCount1 = Pack.bigEndianToLong(encodedState, 12);
94         byteCount2 = Pack.bigEndianToLong(encodedState, 20);
95 
96         H1 = Pack.bigEndianToLong(encodedState, 28);
97         H2 = Pack.bigEndianToLong(encodedState, 36);
98         H3 = Pack.bigEndianToLong(encodedState, 44);
99         H4 = Pack.bigEndianToLong(encodedState, 52);
100         H5 = Pack.bigEndianToLong(encodedState, 60);
101         H6 = Pack.bigEndianToLong(encodedState, 68);
102         H7 = Pack.bigEndianToLong(encodedState, 76);
103         H8 = Pack.bigEndianToLong(encodedState, 84);
104 
105         wOff = Pack.bigEndianToInt(encodedState, 92);
106         for (int i = 0; i < wOff; i++)
107         {
108             W[i] = Pack.bigEndianToLong(encodedState, 96 + (i * 8));
109         }
110     }
111 
getEncodedStateSize()112     protected int getEncodedStateSize()
113     {
114         return 96 + (wOff * 8);
115     }
116 
update( byte in)117     public void update(
118         byte in)
119     {
120         xBuf[xBufOff++] = in;
121 
122         if (xBufOff == xBuf.length)
123         {
124             processWord(xBuf, 0);
125             xBufOff = 0;
126         }
127 
128         byteCount1++;
129     }
130 
update( byte[] in, int inOff, int len)131     public void update(
132         byte[]  in,
133         int     inOff,
134         int     len)
135     {
136         //
137         // fill the current word
138         //
139         while ((xBufOff != 0) && (len > 0))
140         {
141             update(in[inOff]);
142 
143             inOff++;
144             len--;
145         }
146 
147         //
148         // process whole words.
149         //
150         while (len > xBuf.length)
151         {
152             processWord(in, inOff);
153 
154             inOff += xBuf.length;
155             len -= xBuf.length;
156             byteCount1 += xBuf.length;
157         }
158 
159         //
160         // load in the remainder.
161         //
162         while (len > 0)
163         {
164             update(in[inOff]);
165 
166             inOff++;
167             len--;
168         }
169     }
170 
finish()171     public void finish()
172     {
173         adjustByteCounts();
174 
175         long    lowBitLength = byteCount1 << 3;
176         long    hiBitLength = byteCount2;
177 
178         //
179         // add the pad bytes.
180         //
181         update((byte)128);
182 
183         while (xBufOff != 0)
184         {
185             update((byte)0);
186         }
187 
188         processLength(lowBitLength, hiBitLength);
189 
190         processBlock();
191     }
192 
reset()193     public void reset()
194     {
195         byteCount1 = 0;
196         byteCount2 = 0;
197 
198         xBufOff = 0;
199         for (int i = 0; i < xBuf.length; i++)
200         {
201             xBuf[i] = 0;
202         }
203 
204         wOff = 0;
205         for (int i = 0; i != W.length; i++)
206         {
207             W[i] = 0;
208         }
209     }
210 
getByteLength()211     public int getByteLength()
212     {
213         return BYTE_LENGTH;
214     }
215 
processWord( byte[] in, int inOff)216     protected void processWord(
217         byte[]  in,
218         int     inOff)
219     {
220         W[wOff] = Pack.bigEndianToLong(in, inOff);
221 
222         if (++wOff == 16)
223         {
224             processBlock();
225         }
226     }
227 
228     /**
229      * adjust the byte counts so that byteCount2 represents the
230      * upper long (less 3 bits) word of the byte count.
231      */
adjustByteCounts()232     private void adjustByteCounts()
233     {
234         if (byteCount1 > 0x1fffffffffffffffL)
235         {
236             byteCount2 += (byteCount1 >>> 61);
237             byteCount1 &= 0x1fffffffffffffffL;
238         }
239     }
240 
processLength( long lowW, long hiW)241     protected void processLength(
242         long    lowW,
243         long    hiW)
244     {
245         if (wOff > 14)
246         {
247             processBlock();
248         }
249 
250         W[14] = hiW;
251         W[15] = lowW;
252     }
253 
processBlock()254     protected void processBlock()
255     {
256         adjustByteCounts();
257 
258         //
259         // expand 16 word block into 80 word blocks.
260         //
261         for (int t = 16; t <= 79; t++)
262         {
263             W[t] = Sigma1(W[t - 2]) + W[t - 7] + Sigma0(W[t - 15]) + W[t - 16];
264         }
265 
266         //
267         // set up working variables.
268         //
269         long     a = H1;
270         long     b = H2;
271         long     c = H3;
272         long     d = H4;
273         long     e = H5;
274         long     f = H6;
275         long     g = H7;
276         long     h = H8;
277 
278         int t = 0;
279         for(int i = 0; i < 10; i ++)
280         {
281           // t = 8 * i
282           h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
283           d += h;
284           h += Sum0(a) + Maj(a, b, c);
285 
286           // t = 8 * i + 1
287           g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
288           c += g;
289           g += Sum0(h) + Maj(h, a, b);
290 
291           // t = 8 * i + 2
292           f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
293           b += f;
294           f += Sum0(g) + Maj(g, h, a);
295 
296           // t = 8 * i + 3
297           e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
298           a += e;
299           e += Sum0(f) + Maj(f, g, h);
300 
301           // t = 8 * i + 4
302           d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
303           h += d;
304           d += Sum0(e) + Maj(e, f, g);
305 
306           // t = 8 * i + 5
307           c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
308           g += c;
309           c += Sum0(d) + Maj(d, e, f);
310 
311           // t = 8 * i + 6
312           b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
313           f += b;
314           b += Sum0(c) + Maj(c, d, e);
315 
316           // t = 8 * i + 7
317           a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
318           e += a;
319           a += Sum0(b) + Maj(b, c, d);
320         }
321 
322         H1 += a;
323         H2 += b;
324         H3 += c;
325         H4 += d;
326         H5 += e;
327         H6 += f;
328         H7 += g;
329         H8 += h;
330 
331         //
332         // reset the offset and clean out the word buffer.
333         //
334         wOff = 0;
335         for (int i = 0; i < 16; i++)
336         {
337             W[i] = 0;
338         }
339     }
340 
341     /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
Ch( long x, long y, long z)342     private long Ch(
343         long    x,
344         long    y,
345         long    z)
346     {
347         return ((x & y) ^ ((~x) & z));
348     }
349 
Maj( long x, long y, long z)350     private long Maj(
351         long    x,
352         long    y,
353         long    z)
354     {
355         return ((x & y) ^ (x & z) ^ (y & z));
356     }
357 
Sum0( long x)358     private long Sum0(
359         long    x)
360     {
361         return ((x << 36)|(x >>> 28)) ^ ((x << 30)|(x >>> 34)) ^ ((x << 25)|(x >>> 39));
362     }
363 
Sum1( long x)364     private long Sum1(
365         long    x)
366     {
367         return ((x << 50)|(x >>> 14)) ^ ((x << 46)|(x >>> 18)) ^ ((x << 23)|(x >>> 41));
368     }
369 
Sigma0( long x)370     private long Sigma0(
371         long    x)
372     {
373         return ((x << 63)|(x >>> 1)) ^ ((x << 56)|(x >>> 8)) ^ (x >>> 7);
374     }
375 
Sigma1( long x)376     private long Sigma1(
377         long    x)
378     {
379         return ((x << 45)|(x >>> 19)) ^ ((x << 3)|(x >>> 61)) ^ (x >>> 6);
380     }
381 
382     /* SHA-384 and SHA-512 Constants
383      * (represent the first 64 bits of the fractional parts of the
384      * cube roots of the first sixty-four prime numbers)
385      */
386     static final long K[] = {
387 0x428a2f98d728ae22L, 0x7137449123ef65cdL, 0xb5c0fbcfec4d3b2fL, 0xe9b5dba58189dbbcL,
388 0x3956c25bf348b538L, 0x59f111f1b605d019L, 0x923f82a4af194f9bL, 0xab1c5ed5da6d8118L,
389 0xd807aa98a3030242L, 0x12835b0145706fbeL, 0x243185be4ee4b28cL, 0x550c7dc3d5ffb4e2L,
390 0x72be5d74f27b896fL, 0x80deb1fe3b1696b1L, 0x9bdc06a725c71235L, 0xc19bf174cf692694L,
391 0xe49b69c19ef14ad2L, 0xefbe4786384f25e3L, 0x0fc19dc68b8cd5b5L, 0x240ca1cc77ac9c65L,
392 0x2de92c6f592b0275L, 0x4a7484aa6ea6e483L, 0x5cb0a9dcbd41fbd4L, 0x76f988da831153b5L,
393 0x983e5152ee66dfabL, 0xa831c66d2db43210L, 0xb00327c898fb213fL, 0xbf597fc7beef0ee4L,
394 0xc6e00bf33da88fc2L, 0xd5a79147930aa725L, 0x06ca6351e003826fL, 0x142929670a0e6e70L,
395 0x27b70a8546d22ffcL, 0x2e1b21385c26c926L, 0x4d2c6dfc5ac42aedL, 0x53380d139d95b3dfL,
396 0x650a73548baf63deL, 0x766a0abb3c77b2a8L, 0x81c2c92e47edaee6L, 0x92722c851482353bL,
397 0xa2bfe8a14cf10364L, 0xa81a664bbc423001L, 0xc24b8b70d0f89791L, 0xc76c51a30654be30L,
398 0xd192e819d6ef5218L, 0xd69906245565a910L, 0xf40e35855771202aL, 0x106aa07032bbd1b8L,
399 0x19a4c116b8d2d0c8L, 0x1e376c085141ab53L, 0x2748774cdf8eeb99L, 0x34b0bcb5e19b48a8L,
400 0x391c0cb3c5c95a63L, 0x4ed8aa4ae3418acbL, 0x5b9cca4f7763e373L, 0x682e6ff3d6b2b8a3L,
401 0x748f82ee5defb2fcL, 0x78a5636f43172f60L, 0x84c87814a1f0ab72L, 0x8cc702081a6439ecL,
402 0x90befffa23631e28L, 0xa4506cebde82bde9L, 0xbef9a3f7b2c67915L, 0xc67178f2e372532bL,
403 0xca273eceea26619cL, 0xd186b8c721c0c207L, 0xeada7dd6cde0eb1eL, 0xf57d4f7fee6ed178L,
404 0x06f067aa72176fbaL, 0x0a637dc5a2c898a6L, 0x113f9804bef90daeL, 0x1b710b35131c471bL,
405 0x28db77f523047d84L, 0x32caab7b40c72493L, 0x3c9ebe0a15c9bebcL, 0x431d67c49c100d4cL,
406 0x4cc5d4becb3e42b6L, 0x597f299cfc657e2aL, 0x5fcb6fab3ad6faecL, 0x6c44198c4a475817L
407     };
408 
409 }
410