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