TestAES.java revision 16658:cb761a779278
1/* 2 * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/* 25 * @test 26 * @bug 7088989 8014374 8167512 8173708 27 * @summary Ensure the AES ciphers of OracleUcrypto provider works correctly 28 * @key randomness 29 * @run main TestAES 30 * @run main/othervm/java.security.policy==empty.policy TestAES 31 */ 32 33import java.io.*; 34import java.security.*; 35import java.security.spec.*; 36import java.util.*; 37import javax.crypto.*; 38import javax.crypto.spec.*; 39 40public class TestAES extends UcryptoTest { 41 42 private static final String[] PADDEDCIPHER_ALGOS = { 43 "AES/ECB/PKCS5Padding", 44 "AES/CBC/PKCS5Padding", 45 "AES/CFB128/PKCS5Padding" 46 }; 47 48 private static final String[] CIPHER_ALGOS = { 49 "AES/ECB/NoPadding", 50 "AES/CBC/NoPadding", 51 "AES/CFB128/NoPadding", 52 "AES/CTR/NoPadding", 53 }; 54 55 private static final SecretKey CIPHER_KEY = 56 new SecretKeySpec(new byte[16], "AES"); 57 58 public static void main(String[] args) throws Exception { 59 main(new TestAES(), null); 60 } 61 62 public void doTest(Provider prov) throws Exception { 63 // Provider for testing Interoperability 64 Provider sunJCEProv = Security.getProvider("SunJCE"); 65 66 testCipherInterop(CIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); 67 testCipherInterop(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); 68 69 testCipherOffset(CIPHER_ALGOS, CIPHER_KEY, prov); 70 testCipherOffset(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov); 71 72 testCipherKeyWrapping(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); 73 testCipherGCM(CIPHER_KEY, prov); 74 } 75 76 private static void testCipherInterop(String[] algos, SecretKey key, 77 Provider p, 78 Provider interopP) { 79 boolean testPassed = true; 80 byte[] in = new byte[32]; 81 (new SecureRandom()).nextBytes(in); 82 83 for (String algo : algos) { 84 try { 85 // check ENC 86 Cipher c; 87 try { 88 c = Cipher.getInstance(algo, p); 89 } catch (NoSuchAlgorithmException nsae) { 90 System.out.println("Skipping Unsupported CIP algo: " + algo); 91 continue; 92 } 93 c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null); 94 byte[] eout = c.doFinal(in, 0, in.length); 95 96 AlgorithmParameters params = c.getParameters(); 97 Cipher c2 = Cipher.getInstance(algo, interopP); 98 c2.init(Cipher.ENCRYPT_MODE, key, params, null); 99 byte[] eout2 = c2.doFinal(in, 0, in.length); 100 101 if (!Arrays.equals(eout, eout2)) { 102 System.out.println(algo + ": DIFF FAILED"); 103 testPassed = false; 104 } else { 105 System.out.println(algo + ": ENC Passed"); 106 } 107 108 // check DEC 109 c.init(Cipher.DECRYPT_MODE, key, params, null); 110 byte[] dout = c.doFinal(eout); 111 c2.init(Cipher.DECRYPT_MODE, key, params, null); 112 byte[] dout2 = c2.doFinal(eout2); 113 114 if (!Arrays.equals(dout, dout2)) { 115 System.out.println(algo + ": DIFF FAILED"); 116 testPassed = false; 117 } else { 118 System.out.println(algo + ": DEC Passed"); 119 } 120 } catch(Exception ex) { 121 System.out.println("Unexpected Exception: " + algo); 122 ex.printStackTrace(); 123 testPassed = false; 124 } 125 } 126 127 if (!testPassed) { 128 throw new RuntimeException("One or more CIPHER test failed!"); 129 } else { 130 System.out.println("CIPHER Interop Tests Passed"); 131 } 132 } 133 134 private static void testCipherOffset(String[] algos, SecretKey key, 135 Provider p) { 136 boolean testPassed = true; 137 byte[] in = new byte[16]; 138 (new SecureRandom()).nextBytes(in); 139 int blockSize = 16; 140 141 for (int j = 1; j < (in.length - 1); j++) { 142 System.out.println("Input offset size: " + j); 143 for (int i = 0; i < algos.length; i++) { 144 try { 145 // check ENC 146 Cipher c; 147 try { 148 c = Cipher.getInstance(algos[i], p); 149 } catch (NoSuchAlgorithmException nsae) { 150 System.out.println("Skip Unsupported CIP algo: " + algos[i]); 151 continue; 152 } 153 c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null); 154 byte[] eout = new byte[c.getOutputSize(in.length)]; 155 int firstPartLen = in.length - j - 1; 156 //System.out.print("1st UPDATE: " + firstPartLen); 157 int k = c.update(in, 0, firstPartLen, eout, 0); 158 k += c.update(in, firstPartLen, 1, eout, k); 159 k += c.doFinal(in, firstPartLen+1, j, eout, k); 160 161 AlgorithmParameters params = c.getParameters(); 162 163 Cipher c2 = Cipher.getInstance(algos[i], p); 164 c2.init(Cipher.ENCRYPT_MODE, key, params, null); 165 byte[] eout2 = new byte[c2.getOutputSize(in.length)]; 166 int k2 = c2.update(in, 0, j, eout2, 0); 167 k2 += c2.update(in, j, 1, eout2, k2); 168 k2 += c2.doFinal(in, j+1, firstPartLen, eout2, k2); 169 170 if (!checkArrays(eout, k, eout2, k2)) testPassed = false; 171 172 // check DEC 173 c.init(Cipher.DECRYPT_MODE, key, params, null); 174 byte[] dout = new byte[c.getOutputSize(eout.length)]; 175 k = c.update(eout, 0, firstPartLen, dout, 0); 176 k += c.update(eout, firstPartLen, 1, dout, k); 177 k += c.doFinal(eout, firstPartLen+1, eout.length - firstPartLen - 1, dout, k); 178 if (!checkArrays(in, in.length, dout, k)) testPassed = false; 179 } catch(Exception ex) { 180 if (ex instanceof BadPaddingException && 181 algos[i].indexOf("CFB128") != -1 && 182 p.getName().equals("OracleUcrypto")) { 183 System.out.println("Ignore due to a pre-S11.3 bug: " + ex); 184 continue; 185 } 186 System.out.println("Unexpected Exception: " + algos[i]); 187 ex.printStackTrace(); 188 testPassed = false; 189 } 190 } 191 } 192 if (!testPassed) { 193 throw new RuntimeException("One or more CIPHER test failed!"); 194 } else { 195 System.out.println("CIPHER Offset Tests Passed"); 196 } 197 } 198 199 private static void testCipherKeyWrapping(String[] algos, SecretKey key, 200 Provider p, Provider interopP) 201 throws NoSuchAlgorithmException { 202 boolean testPassed = true; 203 204 // Test SecretKey, PrivateKey and PublicKey 205 Key[] tbwKeys = new Key[3]; 206 int[] tbwKeyTypes = { Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, Cipher.PUBLIC_KEY }; 207 tbwKeys[0] = new SecretKeySpec(new byte[20], "Blowfish"); 208 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 209 kpg.initialize(1024); 210 KeyPair kp = kpg.generateKeyPair(); 211 tbwKeys[1] = kp.getPrivate(); 212 tbwKeys[2] = kp.getPublic(); 213 214 for (int i = 0; i < algos.length; i++) { 215 try { 216 System.out.println(algos[i] + " - Native WRAP/Java UNWRAP"); 217 218 Cipher c1; 219 try { 220 c1 = Cipher.getInstance(algos[i], p); 221 } catch (NoSuchAlgorithmException nsae) { 222 System.out.println("Skipping Unsupported CIP algo: " + algos[i]); 223 continue; 224 } 225 c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null); 226 AlgorithmParameters params = c1.getParameters(); 227 Cipher c2 = Cipher.getInstance(algos[i], interopP); 228 c2.init(Cipher.UNWRAP_MODE, key, params, null); 229 230 for (int j = 0; j < tbwKeys.length ; j++) { 231 byte[] wrappedKey = c1.wrap(tbwKeys[j]); 232 Key recovered = c2.unwrap(wrappedKey, 233 tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]); 234 if (!checkKeys(tbwKeys[j], recovered)) testPassed = false; 235 } 236 237 System.out.println(algos[i] + " - Java WRAP/Native UNWRAP"); 238 c1 = Cipher.getInstance(algos[i], interopP); 239 c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null); 240 params = c1.getParameters(); 241 c2 = Cipher.getInstance(algos[i], p); 242 c2.init(Cipher.UNWRAP_MODE, key, params, null); 243 244 for (int j = 0; j < tbwKeys.length ; j++) { 245 byte[] wrappedKey = c1.wrap(tbwKeys[j]); 246 Key recovered = c2.unwrap(wrappedKey, 247 tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]); 248 if (!checkKeys(tbwKeys[j], recovered)) testPassed = false; 249 } 250 251 } catch(Exception ex) { 252 System.out.println("Unexpected Exception: " + algos[i]); 253 ex.printStackTrace(); 254 testPassed = false; 255 } 256 } 257 if (!testPassed) { 258 throw new RuntimeException("One or more CIPHER test failed!"); 259 } else { 260 System.out.println("CIPHER KeyWrapping Tests Passed"); 261 } 262 } 263 264 265 private static void testCipherGCM(SecretKey key, 266 Provider p) { 267 boolean testPassed = true; 268 byte[] in = new byte[16]; 269 (new SecureRandom()).nextBytes(in); 270 271 byte[] iv = new byte[16]; 272 (new SecureRandom()).nextBytes(iv); 273 274 275 String algo = "AES/GCM/NoPadding"; 276 int tagLen[] = { 128, 120, 112, 104, 96, 64, 32 }; 277 278 try { 279 Cipher c; 280 try { 281 c = Cipher.getInstance(algo, p); 282 } catch (NoSuchAlgorithmException nsae) { 283 System.out.println("Skipping Unsupported CIP algo: " + algo); 284 return; 285 } 286 for (int i = 0; i < tagLen.length; i++) { 287 // change iv value to pass the key+iv uniqueness cehck for 288 // GCM encryption 289 iv[0] += 1; 290 AlgorithmParameterSpec paramSpec = new GCMParameterSpec(tagLen[i], iv); 291 // check ENC 292 c.init(Cipher.ENCRYPT_MODE, key, paramSpec, null); 293 c.updateAAD(iv); 294 byte[] eout = c.doFinal(in, 0, in.length); 295 296 AlgorithmParameters param = c.getParameters(); 297 // check DEC 298 c.init(Cipher.DECRYPT_MODE, key, param, null); 299 c.updateAAD(iv); 300 byte[] dout = c.doFinal(eout, 0, eout.length); 301 302 if (!Arrays.equals(dout, in)) { 303 System.out.println(algo + ": PT and RT DIFF FAILED"); 304 testPassed = false; 305 } else { 306 System.out.println(algo + ": tagLen " + tagLen[i] + " done"); 307 } 308 } 309 } catch(Exception ex) { 310 System.out.println("Unexpected Exception: " + algo); 311 ex.printStackTrace(); 312 testPassed = false; 313 } 314 if (!testPassed) { 315 throw new RuntimeException("One or more CIPHER test failed!"); 316 } else { 317 System.out.println("CIPHER GCM Tests Passed"); 318 } 319 } 320 321 private static boolean checkArrays(byte[] a1, int a1Len, byte[] a2, int a2Len) { 322 boolean equal = true; 323 if (a1Len != a2Len) { 324 System.out.println("DIFFERENT OUT LENGTH"); 325 equal = false; 326 } else { 327 for (int p = 0; p < a1Len; p++) { 328 if (a1[p] != a2[p]) { 329 System.out.println("DIFF FAILED"); 330 equal = false; 331 break; 332 } 333 } 334 } 335 return equal; 336 } 337 338 private static boolean checkKeys(Key k1, Key k2) { 339 boolean equal = true; 340 if (!k1.getAlgorithm().equalsIgnoreCase(k2.getAlgorithm())) { 341 System.out.println("DIFFERENT Key Algorithm"); 342 equal = false; 343 } else if (!k1.getFormat().equalsIgnoreCase(k2.getFormat())) { 344 System.out.println("DIFFERENT Key Format"); 345 equal = false; 346 } else if (!Arrays.equals(k1.getEncoded(), k2.getEncoded())) { 347 System.out.println("DIFFERENT Key Encoding"); 348 equal = false; 349 } 350 return equal; 351 } 352} 353