summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/crypto/engines/AESEngine.java
diff options
context:
space:
mode:
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.java167
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]);
}