1 /* 2 * Copyright (c) 2014, 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 27 * @summary Ensure the AES ciphers of OracleUcrypto provider works correctly 28 */ 29 30 import java.io.*; 31 import java.security.*; 32 import java.security.spec.*; 33 import java.util.*; 34 import javax.crypto.*; 35 import javax.crypto.spec.*; 36 37 public class TestAES extends UcryptoTest { 38 39 private static final String[] PADDEDCIPHER_ALGOS = { 40 "AES/ECB/PKCS5Padding", 41 "AES/CBC/PKCS5Padding", 42 "AES/CFB128/PKCS5Padding" 43 }; 44 45 private static final String[] CIPHER_ALGOS = { 46 "AES/ECB/NoPadding", 47 "AES/CBC/NoPadding", 48 "AES/CFB128/NoPadding", 49 "AES/CTR/NoPadding", 50 }; 51 52 private static final SecretKey CIPHER_KEY = 53 new SecretKeySpec(new byte[16], "AES"); 54 55 public static void main(String[] args) throws Exception { 56 main(new TestAES(), null); 57 } 58 59 public void doTest(Provider prov) throws Exception { 60 // Provider for testing Interoperability 61 Provider sunJCEProv = Security.getProvider("SunJCE"); 62 63 testCipherInterop(CIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); 64 testCipherInterop(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); 65 66 testCipherOffset(CIPHER_ALGOS, CIPHER_KEY, prov); 67 testCipherOffset(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov); 68 69 testCipherKeyWrapping(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv); 70 testCipherGCM(CIPHER_KEY, prov); 71 } 72 73 private static void testCipherInterop(String[] algos, SecretKey key, 74 Provider p, 75 Provider interopP) { 76 boolean testPassed = true; 77 byte[] in = new byte[32]; 78 (new SecureRandom()).nextBytes(in); 79 80 for (String algo : algos) { 81 try { 82 // check ENC 83 Cipher c; 84 try { 85 c = Cipher.getInstance(algo, p); 86 } catch (NoSuchAlgorithmException nsae) { 87 System.out.println("Skipping Unsupported CIP algo: " + algo); 88 continue; 89 } 90 c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null); 91 byte[] eout = c.doFinal(in, 0, in.length); 92 93 AlgorithmParameters params = c.getParameters(); 94 Cipher c2 = Cipher.getInstance(algo, interopP); 95 c2.init(Cipher.ENCRYPT_MODE, key, params, null); 96 byte[] eout2 = c2.doFinal(in, 0, in.length); 97 98 if (!Arrays.equals(eout, eout2)) { 99 System.out.println(algo + ": DIFF FAILED"); 100 testPassed = false; 101 } else { 102 System.out.println(algo + ": ENC Passed"); 103 } 104 105 // check DEC 106 c.init(Cipher.DECRYPT_MODE, key, params, null); 107 byte[] dout = c.doFinal(eout); 108 c2.init(Cipher.DECRYPT_MODE, key, params, null); 109 byte[] dout2 = c2.doFinal(eout2); 110 111 if (!Arrays.equals(dout, dout2)) { 112 System.out.println(algo + ": DIFF FAILED"); 113 testPassed = false; 114 } else { 115 System.out.println(algo + ": DEC Passed"); 116 } 117 } catch(Exception ex) { 118 System.out.println("Unexpected Exception: " + algo); 119 ex.printStackTrace(); 120 testPassed = false; 121 } 122 } 123 124 if (!testPassed) { 125 throw new RuntimeException("One or more CIPHER test failed!"); 126 } else { 127 System.out.println("CIPHER Interop Tests Passed"); 128 } 129 } 130 131 private static void testCipherOffset(String[] algos, SecretKey key, 132 Provider p) { 133 boolean testPassed = true; 134 byte[] in = new byte[16]; 135 (new SecureRandom()).nextBytes(in); 136 int blockSize = 16; 137 138 for (int j = 1; j < (in.length - 1); j++) { 139 System.out.println("Input offset size: " + j); 140 for (int i = 0; i < algos.length; i++) { 141 try { 142 // check ENC 143 Cipher c; 144 try { 145 c = Cipher.getInstance(algos[i], p); 146 } catch (NoSuchAlgorithmException nsae) { 147 System.out.println("Skip Unsupported CIP algo: " + algos[i]); 148 continue; 149 } 150 c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null); 151 byte[] eout = new byte[c.getOutputSize(in.length)]; 152 int firstPartLen = in.length - j - 1; 153 //System.out.print("1st UPDATE: " + firstPartLen); 154 int k = c.update(in, 0, firstPartLen, eout, 0); 155 k += c.update(in, firstPartLen, 1, eout, k); 156 k += c.doFinal(in, firstPartLen+1, j, eout, k); 157 158 AlgorithmParameters params = c.getParameters(); 159 160 Cipher c2 = Cipher.getInstance(algos[i], p); 161 c2.init(Cipher.ENCRYPT_MODE, key, params, null); 162 byte[] eout2 = new byte[c2.getOutputSize(in.length)]; 163 int k2 = c2.update(in, 0, j, eout2, 0); 164 k2 += c2.update(in, j, 1, eout2, k2); 165 k2 += c2.doFinal(in, j+1, firstPartLen, eout2, k2); 166 167 if (!checkArrays(eout, k, eout2, k2)) testPassed = false; 168 169 // check DEC 170 c.init(Cipher.DECRYPT_MODE, key, params, null); 171 byte[] dout = new byte[c.getOutputSize(eout.length)]; 172 k = c.update(eout, 0, firstPartLen, dout, 0); 173 k += c.update(eout, firstPartLen, 1, dout, k); 174 k += c.doFinal(eout, firstPartLen+1, eout.length - firstPartLen - 1, dout, k); 175 if (!checkArrays(in, in.length, dout, k)) testPassed = false; 176 } catch(Exception ex) { 177 System.out.println("Unexpected Exception: " + algos[i]); 178 ex.printStackTrace(); 179 testPassed = false; 180 } 181 } 182 } 183 if (!testPassed) { 184 throw new RuntimeException("One or more CIPHER test failed!"); 185 } else { 186 System.out.println("CIPHER Offset Tests Passed"); 187 } 188 } 189 190 private static void testCipherKeyWrapping(String[] algos, SecretKey key, 191 Provider p, Provider interopP) 192 throws NoSuchAlgorithmException { 193 boolean testPassed = true; 194 195 // Test SecretKey, PrivateKey and PublicKey 196 Key[] tbwKeys = new Key[3]; 197 int[] tbwKeyTypes = { Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, Cipher.PUBLIC_KEY }; 198 tbwKeys[0] = new SecretKeySpec(new byte[20], "Blowfish"); 199 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 200 kpg.initialize(1024); 201 KeyPair kp = kpg.generateKeyPair(); 202 tbwKeys[1] = kp.getPrivate(); 203 tbwKeys[2] = kp.getPublic(); 204 205 for (int i = 0; i < algos.length; i++) { 206 try { 207 System.out.println(algos[i] + " - Native WRAP/Java UNWRAP"); 208 209 Cipher c1; 210 try { 211 c1 = Cipher.getInstance(algos[i], p); 212 } catch (NoSuchAlgorithmException nsae) { 213 System.out.println("Skipping Unsupported CIP algo: " + algos[i]); 214 continue; 215 } 216 c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null); 217 AlgorithmParameters params = c1.getParameters(); 218 Cipher c2 = Cipher.getInstance(algos[i], interopP); 219 c2.init(Cipher.UNWRAP_MODE, key, params, null); 220 221 for (int j = 0; j < tbwKeys.length ; j++) { 222 byte[] wrappedKey = c1.wrap(tbwKeys[j]); 223 Key recovered = c2.unwrap(wrappedKey, 224 tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]); 225 if (!checkKeys(tbwKeys[j], recovered)) testPassed = false; 226 } 227 228 System.out.println(algos[i] + " - Java WRAP/Native UNWRAP"); 229 c1 = Cipher.getInstance(algos[i], interopP); 230 c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null); 231 params = c1.getParameters(); 232 c2 = Cipher.getInstance(algos[i], p); 233 c2.init(Cipher.UNWRAP_MODE, key, params, null); 234 235 for (int j = 0; j < tbwKeys.length ; j++) { 236 byte[] wrappedKey = c1.wrap(tbwKeys[j]); 237 Key recovered = c2.unwrap(wrappedKey, 238 tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]); 239 if (!checkKeys(tbwKeys[j], recovered)) testPassed = false; 240 } 241 242 } catch(Exception ex) { 243 System.out.println("Unexpected Exception: " + algos[i]); 244 ex.printStackTrace(); 245 testPassed = false; 246 } 247 } 248 if (!testPassed) { 249 throw new RuntimeException("One or more CIPHER test failed!"); 250 } else { 251 System.out.println("CIPHER KeyWrapping Tests Passed"); 252 } 253 } 254 255 256 private static void testCipherGCM(SecretKey key, 257 Provider p) { 258 boolean testPassed = true; 259 byte[] in = new byte[16]; 260 (new SecureRandom()).nextBytes(in); 261 262 byte[] iv = new byte[16]; 263 (new SecureRandom()).nextBytes(iv); 264 265 266 String algo = "AES/GCM/NoPadding"; 267 int tagLen[] = { 128, 120, 112, 104, 96, 64, 32 }; 268 269 try { 270 Cipher c; 271 try { 272 c = Cipher.getInstance(algo, p); 273 } catch (NoSuchAlgorithmException nsae) { 274 System.out.println("Skipping Unsupported CIP algo: " + algo); 275 return; 276 } 277 for (int i = 0; i < tagLen.length; i++) { 278 // change iv value to pass the key+iv uniqueness cehck for 279 // GCM encryption 280 iv[0] += 1; 281 AlgorithmParameterSpec paramSpec = new GCMParameterSpec(tagLen[i], iv); 282 // check ENC 283 c.init(Cipher.ENCRYPT_MODE, key, paramSpec, null); 284 c.updateAAD(iv); 285 byte[] eout = c.doFinal(in, 0, in.length); 286 287 AlgorithmParameters param = c.getParameters(); 288 // check DEC 289 c.init(Cipher.DECRYPT_MODE, key, param, null); 290 c.updateAAD(iv); 291 byte[] dout = c.doFinal(eout, 0, eout.length); 292 293 if (!Arrays.equals(dout, in)) { 294 System.out.println(algo + ": PT and RT DIFF FAILED"); 295 testPassed = false; 296 } else { 297 System.out.println(algo + ": tagLen " + tagLen[i] + " done"); 298 } 299 } 300 } catch(Exception ex) { 301 System.out.println("Unexpected Exception: " + algo); 302 ex.printStackTrace(); 303 testPassed = false; 304 } 305 if (!testPassed) { 306 throw new RuntimeException("One or more CIPHER test failed!"); 307 } else { 308 System.out.println("CIPHER GCM Tests Passed"); 309 } 310 } 311 312 private static boolean checkArrays(byte[] a1, int a1Len, byte[] a2, int a2Len) { 313 boolean equal = true; 314 if (a1Len != a2Len) { 315 System.out.println("DIFFERENT OUT LENGTH"); 316 equal = false; 317 } else { 318 for (int p = 0; p < a1Len; p++) { 319 if (a1[p] != a2[p]) { 320 System.out.println("DIFF FAILED"); 321 equal = false; 322 break; 323 } 324 } 325 } 326 return equal; 327 } 328 329 private static boolean checkKeys(Key k1, Key k2) { 330 boolean equal = true; 331 if (!k1.getAlgorithm().equalsIgnoreCase(k2.getAlgorithm())) { 332 System.out.println("DIFFERENT Key Algorithm"); 333 equal = false; 334 } else if (!k1.getFormat().equalsIgnoreCase(k2.getFormat())) { 335 System.out.println("DIFFERENT Key Format"); 336 equal = false; 337 } else if (!Arrays.equals(k1.getEncoded(), k2.getEncoded())) { 338 System.out.println("DIFFERENT Key Encoding"); 339 equal = false; 340 } 341 return equal; 342 } 343 }