1 package org.bouncycastle.crypto.digests;
2 
3 
4 import org.bouncycastle.util.Memoable;
5 import org.bouncycastle.util.Pack;
6 
7 
8 /**
9  * SHA-224 as described in RFC 3874
10  * <pre>
11  *         block  word  digest
12  * SHA-1   512    32    160
13  * SHA-224 512    32    224
14  * SHA-256 512    32    256
15  * SHA-384 1024   64    384
16  * SHA-512 1024   64    512
17  * </pre>
18  */
19 public class SHA224Digest
20     extends GeneralDigest
21     implements EncodableDigest
22 {
23     private static final int    DIGEST_LENGTH = 28;
24 
25     private int     H1, H2, H3, H4, H5, H6, H7, H8;
26 
27     private int[]   X = new int[64];
28     private int     xOff;
29 
30     /**
31      * Standard constructor
32      */
SHA224Digest()33     public SHA224Digest()
34     {
35         reset();
36     }
37 
38     /**
39      * Copy constructor.  This will copy the state of the provided
40      * message digest.
41      */
SHA224Digest(SHA224Digest t)42     public SHA224Digest(SHA224Digest t)
43     {
44         super(t);
45 
46         doCopy(t);
47     }
48 
doCopy(SHA224Digest t)49     private void doCopy(SHA224Digest t)
50     {
51         super.copyIn(t);
52 
53         H1 = t.H1;
54         H2 = t.H2;
55         H3 = t.H3;
56         H4 = t.H4;
57         H5 = t.H5;
58         H6 = t.H6;
59         H7 = t.H7;
60         H8 = t.H8;
61 
62         System.arraycopy(t.X, 0, X, 0, t.X.length);
63         xOff = t.xOff;
64     }
65 
SHA224Digest(byte[] encodedState)66     public SHA224Digest(byte[] encodedState)
67     {
68         super(encodedState);
69 
70         H1 = Pack.bigEndianToInt(encodedState, 16);
71         H2 = Pack.bigEndianToInt(encodedState, 20);
72         H3 = Pack.bigEndianToInt(encodedState, 24);
73         H4 = Pack.bigEndianToInt(encodedState, 28);
74         H5 = Pack.bigEndianToInt(encodedState, 32);
75         H6 = Pack.bigEndianToInt(encodedState, 36);
76         H7 = Pack.bigEndianToInt(encodedState, 40);
77         H8 = Pack.bigEndianToInt(encodedState, 44);
78 
79         xOff = Pack.bigEndianToInt(encodedState, 48);
80         for (int i = 0; i != xOff; i++)
81         {
82             X[i] = Pack.bigEndianToInt(encodedState, 52 + (i * 4));
83         }
84     }
85 
getAlgorithmName()86     public String getAlgorithmName()
87     {
88         return "SHA-224";
89     }
90 
getDigestSize()91     public int getDigestSize()
92     {
93         return DIGEST_LENGTH;
94     }
95 
processWord( byte[] in, int inOff)96     protected void processWord(
97         byte[]  in,
98         int     inOff)
99     {
100         // Note: Inlined for performance
101 //        X[xOff] = Pack.bigEndianToInt(in, inOff);
102         int n = in[  inOff] << 24;
103         n |= (in[++inOff] & 0xff) << 16;
104         n |= (in[++inOff] & 0xff) << 8;
105         n |= (in[++inOff] & 0xff);
106         X[xOff] = n;
107 
108         if (++xOff == 16)
109         {
110             processBlock();
111         }
112     }
113 
processLength( long bitLength)114     protected void processLength(
115         long    bitLength)
116     {
117         if (xOff > 14)
118         {
119             processBlock();
120         }
121 
122         X[14] = (int)(bitLength >>> 32);
123         X[15] = (int)(bitLength & 0xffffffff);
124     }
125 
doFinal( byte[] out, int outOff)126     public int doFinal(
127         byte[]  out,
128         int     outOff)
129     {
130         finish();
131 
132         Pack.intToBigEndian(H1, out, outOff);
133         Pack.intToBigEndian(H2, out, outOff + 4);
134         Pack.intToBigEndian(H3, out, outOff + 8);
135         Pack.intToBigEndian(H4, out, outOff + 12);
136         Pack.intToBigEndian(H5, out, outOff + 16);
137         Pack.intToBigEndian(H6, out, outOff + 20);
138         Pack.intToBigEndian(H7, out, outOff + 24);
139 
140         reset();
141 
142         return DIGEST_LENGTH;
143     }
144 
145     /**
146      * reset the chaining variables
147      */
reset()148     public void reset()
149     {
150         super.reset();
151 
152         /* SHA-224 initial hash value
153          */
154 
155         H1 = 0xc1059ed8;
156         H2 = 0x367cd507;
157         H3 = 0x3070dd17;
158         H4 = 0xf70e5939;
159         H5 = 0xffc00b31;
160         H6 = 0x68581511;
161         H7 = 0x64f98fa7;
162         H8 = 0xbefa4fa4;
163 
164         xOff = 0;
165         for (int i = 0; i != X.length; i++)
166         {
167             X[i] = 0;
168         }
169     }
170 
processBlock()171     protected void processBlock()
172     {
173         //
174         // expand 16 word block into 64 word blocks.
175         //
176         for (int t = 16; t <= 63; t++)
177         {
178             X[t] = Theta1(X[t - 2]) + X[t - 7] + Theta0(X[t - 15]) + X[t - 16];
179         }
180 
181         //
182         // set up working variables.
183         //
184         int     a = H1;
185         int     b = H2;
186         int     c = H3;
187         int     d = H4;
188         int     e = H5;
189         int     f = H6;
190         int     g = H7;
191         int     h = H8;
192 
193 
194         int t = 0;
195         for(int i = 0; i < 8; i ++)
196         {
197             // t = 8 * i
198             h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
199             d += h;
200             h += Sum0(a) + Maj(a, b, c);
201             ++t;
202 
203             // t = 8 * i + 1
204             g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
205             c += g;
206             g += Sum0(h) + Maj(h, a, b);
207             ++t;
208 
209             // t = 8 * i + 2
210             f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
211             b += f;
212             f += Sum0(g) + Maj(g, h, a);
213             ++t;
214 
215             // t = 8 * i + 3
216             e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
217             a += e;
218             e += Sum0(f) + Maj(f, g, h);
219             ++t;
220 
221             // t = 8 * i + 4
222             d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
223             h += d;
224             d += Sum0(e) + Maj(e, f, g);
225             ++t;
226 
227             // t = 8 * i + 5
228             c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
229             g += c;
230             c += Sum0(d) + Maj(d, e, f);
231             ++t;
232 
233             // t = 8 * i + 6
234             b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
235             f += b;
236             b += Sum0(c) + Maj(c, d, e);
237             ++t;
238 
239             // t = 8 * i + 7
240             a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
241             e += a;
242             a += Sum0(b) + Maj(b, c, d);
243             ++t;
244         }
245 
246         H1 += a;
247         H2 += b;
248         H3 += c;
249         H4 += d;
250         H5 += e;
251         H6 += f;
252         H7 += g;
253         H8 += h;
254 
255         //
256         // reset the offset and clean out the word buffer.
257         //
258         xOff = 0;
259         for (int i = 0; i < 16; i++)
260         {
261             X[i] = 0;
262         }
263     }
264 
265     /* SHA-224 functions */
Ch( int x, int y, int z)266     private int Ch(
267         int    x,
268         int    y,
269         int    z)
270     {
271         return ((x & y) ^ ((~x) & z));
272     }
273 
Maj( int x, int y, int z)274     private int Maj(
275         int    x,
276         int    y,
277         int    z)
278     {
279         return ((x & y) ^ (x & z) ^ (y & z));
280     }
281 
Sum0( int x)282     private int Sum0(
283         int    x)
284     {
285         return ((x >>> 2) | (x << 30)) ^ ((x >>> 13) | (x << 19)) ^ ((x >>> 22) | (x << 10));
286     }
287 
Sum1( int x)288     private int Sum1(
289         int    x)
290     {
291         return ((x >>> 6) | (x << 26)) ^ ((x >>> 11) | (x << 21)) ^ ((x >>> 25) | (x << 7));
292     }
293 
Theta0( int x)294     private int Theta0(
295         int    x)
296     {
297         return ((x >>> 7) | (x << 25)) ^ ((x >>> 18) | (x << 14)) ^ (x >>> 3);
298     }
299 
Theta1( int x)300     private int Theta1(
301         int    x)
302     {
303         return ((x >>> 17) | (x << 15)) ^ ((x >>> 19) | (x << 13)) ^ (x >>> 10);
304     }
305 
306     /* SHA-224 Constants
307      * (represent the first 32 bits of the fractional parts of the
308      * cube roots of the first sixty-four prime numbers)
309      */
310     static final int K[] = {
311         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
312         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
313         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
314         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
315         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
316         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
317         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
318     };
319 
copy()320     public Memoable copy()
321     {
322         return new SHA224Digest(this);
323     }
324 
reset(Memoable other)325     public void reset(Memoable other)
326     {
327         SHA224Digest d = (SHA224Digest)other;
328 
329         doCopy(d);
330     }
331 
getEncodedState()332     public byte[] getEncodedState()
333     {
334         byte[] state = new byte[52 + xOff * 4];
335 
336         super.populateState(state);
337 
338         Pack.intToBigEndian(H1, state, 16);
339         Pack.intToBigEndian(H2, state, 20);
340         Pack.intToBigEndian(H3, state, 24);
341         Pack.intToBigEndian(H4, state, 28);
342         Pack.intToBigEndian(H5, state, 32);
343         Pack.intToBigEndian(H6, state, 36);
344         Pack.intToBigEndian(H7, state, 40);
345         Pack.intToBigEndian(H8, state, 44);
346         Pack.intToBigEndian(xOff, state, 48);
347 
348         for (int i = 0; i != xOff; i++)
349         {
350             Pack.intToBigEndian(X[i], state, 52 + (i * 4));
351         }
352 
353         return state;
354     }
355 }
356 
357