8044193: Need to add known answer tests for AES cipher
Summary: Added more tests for AES cipher using known test vectors.
Reviewed-by: valeriep
Contributed-by: Zaiyao Liu <zaiyao.liu@oracle.com>
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.PrintStream;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Arrays;
import java.util.Random;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class Dynamic {
static final String ALGORITHM = "AES";
static final String[] MODE = {
"ECb", "CbC", "CTR", "PCBC", "OFB", "OFB150", "cFB", "CFB7",
"cFB8", "cFB16", "cFB24", "cFB32", "Cfb40", "cfB48", "cfB56",
"cfB64", "cfB72", "cfB80", "cfB88", "cfB96", "cfb104", "cfB112",
"cfB120", "cfB128", "OFB8", "OFB16", "OFB24", "OFB32", "OFB40",
"OFB48", "OFB56", "OFB64", "OFB72", "OFB80", "OFB88", "OFB96",
"OFB104", "OFB112", "OFB120", "OFB128", "GCM"
};
static final String[] PADDING = {
"NoPadding", "PKCS5Padding", "ISO10126Padding"
};
static final String SUNJCE = "SunJCE";
Cipher ci = null;
byte[] iv = null;
AlgorithmParameterSpec aps = null;
SecretKey key = null;
int keyStrength;
static int DefaultSize = 128;
public void run(String[] argv) throws Exception {
if (!runAllTest(argv, System.out)) {
throw new Exception("Test Failed");
}
}
protected boolean runAllTest(String argv[], PrintStream out) {
boolean result = true;
StringBuilder failedList = new StringBuilder();
int failedCnt = 0;
int testCount = 0;
int padKinds; // how many kinds of padding mode such as PKCS5padding and
// NoPadding.
try {
for (int i = 0; i < 3; i++) {
keyStrength = DefaultSize + i * 64; // obtain the key size 128,
// 192, 256
for (int j = 0; j < MODE.length; j++) {
if (MODE[j].equalsIgnoreCase("ECB")
|| MODE[j].equalsIgnoreCase("PCBC")
|| MODE[j].equalsIgnoreCase("CBC")) {
padKinds = PADDING.length;
} else {
padKinds = 1;
}
for (int k = 0; k < padKinds; k++) {
testCount++;
try {
if (!runTest(ALGORITHM, MODE[j], PADDING[k])) {
result = false;
failedCnt++;
failedList.append(ALGORITHM + "/" + MODE[j]
+ "/" + PADDING[k] + " ");
}
} catch (Exception e) {
e.printStackTrace();
result = false;
failedCnt++;
failedList.append(ALGORITHM + "/" + MODE[j] + "/"
+ PADDING[k] + " ");
}
}
}
}
if (result) {
out.println("STATUS:Passed. Test " + testCount
+ " cases, All Passed");
return true;
}
out.println("STATUS:Failed. " + failedCnt + " Failed: "
+ failedList);
return false;
} catch (Exception ex) {
ex.printStackTrace();
out.println("STATUS:Failed. Unexpected Exception: " + ex);
return false;
}
}
protected boolean runTest(String algo, String mo, String pad)
throws Exception {
boolean result = true;
try {
byte[] plainText = new byte[160000];
new Random().nextBytes(plainText);
String transformation = algo + "/" + mo + "/" + pad;
ci = Cipher.getInstance(transformation, SUNJCE);
KeyGenerator kg = KeyGenerator.getInstance(algo, SUNJCE);
if (keyStrength > Cipher.getMaxAllowedKeyLength(transformation)) {
// skip if this key length is larger than what's
// configured in the jce jurisdiction policy files
System.out.println(keyStrength
+ " is larger than what's configured "
+ "in the jce jurisdiction policy files");
return result;
}
kg.init(keyStrength);
key = kg.generateKey();
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.ENCRYPT_MODE, key, aps);
} else {
ci.init(Cipher.ENCRYPT_MODE, key);
}
byte[] cipherText = new byte[ci.getOutputSize(plainText.length)];
int offset = ci.update(plainText, 0, plainText.length, cipherText,
0);
ci.doFinal(cipherText, offset);
if (!mo.equalsIgnoreCase("ECB")) {
iv = ci.getIV();
aps = new IvParameterSpec(iv);
} else {
aps = null;
}
if (!mo.equalsIgnoreCase("GCM")) {
ci.init(Cipher.DECRYPT_MODE, key, aps);
} else {
ci.init(Cipher.DECRYPT_MODE, key, ci.getParameters());
}
byte[] recoveredText = new byte[ci.getOutputSize(cipherText.length)];
int len = ci.doFinal(cipherText, 0, cipherText.length,
recoveredText);
byte[] tmp = new byte[len];
for (int i = 0; i < len; i++) {
tmp[i] = recoveredText[i];
}
result = Arrays.equals(plainText, tmp);
} catch (NoSuchAlgorithmException nsaEx) {
nsaEx.printStackTrace();
// CFB7 and OFB150 are negative test,SunJCE not support this
// algorithm
result = mo.equalsIgnoreCase("CFB7")
|| mo.equalsIgnoreCase("OFB150");
}
return result;
}
}