diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java | 167 |
1 files changed, 124 insertions, 43 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java index a0fd0840..924dff35 100644 --- a/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java @@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.Pack; /** * an implementation of the AES (Rijndael), from FIPS-197. @@ -230,12 +231,22 @@ private static final int[] Tinv0 = private static final int m1 = 0x80808080; private static final int m2 = 0x7f7f7f7f; private static final int m3 = 0x0000001b; + private static final int m4 = 0xC0C0C0C0; + private static final int m5 = 0x3f3f3f3f; private static int FFmulX(int x) { return (((x & m2) << 1) ^ (((x & m1) >>> 7) * m3)); } + private static int FFmulX2(int x) + { + int t0 = (x & m5) << 2; + int t1 = (x & m4); + t1 ^= (t1 >>> 1); + return t0 ^ (t1 >>> 2) ^ (t1 >>> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -248,12 +259,13 @@ private static final int[] Tinv0 = private static int inv_mcol(int x) { - int f2 = FFmulX(x); - int f4 = FFmulX(f2); - int f8 = FFmulX(f4); - int f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ shift(f2 ^ f9, 8) ^ shift(f4 ^ f9, 16) ^ shift(f9, 24); + int t0, t1; + t0 = x; + t1 = t0 ^ shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ shift(t1, 16); + return t0; } private static int subWord(int x) @@ -267,59 +279,128 @@ private static final int[] Tinv0 = * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits * This code is written assuming those are the only possible values */ - private int[][] generateWorkingKey( - byte[] key, - boolean forEncryption) + private int[][] generateWorkingKey(byte[] key, boolean forEncryption) { - int KC = key.length / 4; // key length in words - int t; - - if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.length)) + int keyLen = key.length; + if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0) { throw new IllegalArgumentException("Key length not 128/192/256 bits."); } + int KC = keyLen >>> 2; ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes int[][] W = new int[ROUNDS+1][4]; // 4 words in a block - - // - // copy the key into the round key array - // - - t = 0; - int i = 0; - while (i < key.length) + + switch (KC) + { + case 4: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + + for (int i = 1; i <= 10; ++i) { - W[t >> 2][t & 3] = (key[i]&0xff) | ((key[i+1]&0xff) << 8) | ((key[i+2]&0xff) << 16) | (key[i+3] << 24); - i+=4; - t++; + int u = subWord(shift(t3, 8)) ^ rcon[i - 1]; + t0 ^= u; W[i][0] = t0; + t1 ^= t0; W[i][1] = t1; + t2 ^= t1; W[i][2] = t2; + t3 ^= t2; W[i][3] = t3; } - - // - // while not enough round key material calculated - // calculate new values - // - int k = (ROUNDS + 1) << 2; - for (i = KC; (i < k); i++) + + break; + } + case 6: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4; + int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5; + + int rcon = 1; + int u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[1][2] = t0; + t1 ^= t0; W[1][3] = t1; + t2 ^= t1; W[2][0] = t2; + t3 ^= t2; W[2][1] = t3; + t4 ^= t3; W[2][2] = t4; + t5 ^= t4; W[2][3] = t5; + + for (int i = 3; i < 12; i += 3) { - int temp = W[(i-1)>>2][(i-1)&3]; - if ((i % KC) == 0) - { - temp = subWord(shift(temp, 8)) ^ rcon[(i / KC)-1]; - } - else if ((KC > 6) && ((i % KC) == 4)) - { - temp = subWord(temp); - } - - W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp; + u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + t4 ^= t3; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + u = subWord(shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i + 1][2] = t0; + t1 ^= t0; W[i + 1][3] = t1; + t2 ^= t1; W[i + 2][0] = t2; + t3 ^= t2; W[i + 2][1] = t3; + t4 ^= t3; W[i + 2][2] = t4; + t5 ^= t4; W[i + 2][3] = t5; } + u = subWord(shift(t5, 8)) ^ rcon; + t0 ^= u; W[12][0] = t0; + t1 ^= t0; W[12][1] = t1; + t2 ^= t1; W[12][2] = t2; + t3 ^= t2; W[12][3] = t3; + + break; + } + case 8: + { + int t0 = Pack.littleEndianToInt(key, 0); W[0][0] = t0; + int t1 = Pack.littleEndianToInt(key, 4); W[0][1] = t1; + int t2 = Pack.littleEndianToInt(key, 8); W[0][2] = t2; + int t3 = Pack.littleEndianToInt(key, 12); W[0][3] = t3; + int t4 = Pack.littleEndianToInt(key, 16); W[1][0] = t4; + int t5 = Pack.littleEndianToInt(key, 20); W[1][1] = t5; + int t6 = Pack.littleEndianToInt(key, 24); W[1][2] = t6; + int t7 = Pack.littleEndianToInt(key, 28); W[1][3] = t7; + + int u, rcon = 1; + + for (int i = 2; i < 14; i += 2) + { + u = subWord(shift(t7, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + u = subWord(t3); + t4 ^= u; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + t6 ^= t5; W[i + 1][2] = t6; + t7 ^= t6; W[i + 1][3] = t7; + } + + u = subWord(shift(t7, 8)) ^ rcon; + t0 ^= u; W[14][0] = t0; + t1 ^= t0; W[14][1] = t1; + t2 ^= t1; W[14][2] = t2; + t3 ^= t2; W[14][3] = t3; + + break; + } + default: + { + throw new IllegalStateException("Should never get here"); + } + } + if (!forEncryption) { for (int j = 1; j < ROUNDS; j++) { - for (i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { W[j][i] = inv_mcol(W[j][i]); } |