7185471: Avoid key expansion when AES cipher is re-init w/ the same key

Saved the last cipher key value and skip key expansion if key value is the same.

Reviewed-by: weijun, xuelei
This commit is contained in:
Valerie Peng 2012-08-10 13:10:35 -07:00
parent 919dca6024
commit a44a57d7b6

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -37,6 +37,7 @@
package com.sun.crypto.provider; package com.sun.crypto.provider;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.util.Arrays;
/** /**
* Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit
@ -54,7 +55,12 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
private Object[] sessionK = null; private Object[] sessionK = null;
private int[] K = null; private int[] K = null;
/** (ROUNDS-1) * 4 */ /** Cipher encryption/decryption key */
// skip re-generating Session and Sub keys if the cipher key is
// the same
private byte[] lastKey = null;
/** ROUNDS * 4 */
private int limit = 0; private int limit = 0;
AESCrypt() { AESCrypt() {
@ -82,41 +88,45 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
key.length + " bytes"); key.length + " bytes");
} }
// generate session key and reset sub key. if (!Arrays.equals(key, lastKey)) {
sessionK = makeKey(key); // re-generate session key 'sessionK' when cipher key changes
setSubKey(decrypting); makeSessionKey(key);
lastKey = key.clone(); // save cipher key
} }
private void setSubKey(boolean decrypting) { // set sub key to the corresponding session Key
int[][] Kd = (int[][]) sessionK[decrypting ? 1 : 0]; this.K = (int[]) sessionK[(decrypting? 1:0)];
int rounds = Kd.length;
this.K = new int[rounds*4];
for(int i=0; i<rounds; i++) {
for(int j=0; j<4; j++) {
K[i*4 + j] = Kd[i][j];
}
} }
/**
* Expand an int[(ROUNDS+1)][4] into int[(ROUNDS+1)*4].
* For decryption round keys, need to rotate right by 4 ints.
* @param kr The round keys for encryption or decryption.
* @param decrypting True if 'kr' is for decryption and false otherwise.
*/
private static final int[] expandToSubKey(int[][] kr, boolean decrypting) {
int total = kr.length;
int[] expK = new int[total*4];
if (decrypting) { if (decrypting) {
int j0 = K[K.length-4]; // decrypting, rotate right by 4 ints
int j1 = K[K.length-3]; // i.e. i==0
int j2 = K[K.length-2]; for(int j=0; j<4; j++) {
int j3 = K[K.length-1]; expK[j] = kr[total-1][j];
for (int i=this.K.length-1; i>3; i--) {
this.K[i] = this.K[i-4];
} }
K[0] = j0; for(int i=1; i<total; i++) {
K[1] = j1; for(int j=0; j<4; j++) {
K[2] = j2; expK[i*4 + j] = kr[i-1][j];
K[3] = j3;
} }
}
ROUNDS_12 = (rounds>=13); } else {
ROUNDS_14 = (rounds==15); // encrypting, straight expansion
for(int i=0; i<total; i++) {
rounds--; for(int j=0; j<4; j++) {
limit=rounds*4; expK[i*4 + j] = kr[i][j];
}
}
}
return expK;
} }
private static int[] private static int[]
@ -566,10 +576,10 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
/** /**
* Expand a user-supplied key material into a session key. * Expand a user-supplied key material into a session key.
* *
* @param key The 128/192/256-bit user-key to use. * @param k The 128/192/256-bit cipher key to use.
* @exception InvalidKeyException If the key is invalid. * @exception InvalidKeyException If the key is invalid.
*/ */
private static Object[] makeKey(byte[] k) throws InvalidKeyException { private void makeSessionKey(byte[] k) throws InvalidKeyException {
if (k == null) { if (k == null) {
throw new InvalidKeyException("Empty key"); throw new InvalidKeyException("Empty key");
} }
@ -639,10 +649,18 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
U4[ tt & 0xFF]; U4[ tt & 0xFF];
} }
} }
// assemble the encryption (Ke) and decryption (Kd) round keys into
// one sessionKey object // assemble the encryption (Ke) and decryption (Kd) round keys
Object[] result = new Object[] {Ke, Kd}; // and expand them into arrays of ints.
return result; int[] expandedKe = expandToSubKey(Ke, false); // decrypting==false
int[] expandedKd = expandToSubKey(Kd, true); // decrypting==true
ROUNDS_12 = (ROUNDS>=12);
ROUNDS_14 = (ROUNDS==14);
limit = ROUNDS*4;
// store the expanded sub keys into 'sessionK'
sessionK = new Object[] { expandedKe, expandedKd };
} }