1 /* 2 * Copyright (c) 2004, 2015, 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 4495742 27 * @summary Add non-blocking SSL/TLS functionality, usable with any 28 * I/O abstraction 29 * 30 * This is to test larger buffer arrays, and make sure the maximum 31 * is being passed. 32 * 33 * @run main/othervm -Djsse.enableCBCProtection=false LargeBufs 34 * 35 * @author Brad R. Wetmore 36 * @key randomness 37 */ 38 39 import javax.net.ssl.*; 40 import javax.net.ssl.SSLEngineResult.*; 41 import java.io.*; 42 import java.security.*; 43 import java.nio.*; 44 import java.util.Random; 45 46 public class LargeBufs { 47 48 private static boolean debug = true; 49 50 private SSLContext sslc; 51 static private SSLEngine ssle1; // client 52 static private SSLEngine ssle2; // server 53 54 private static String pathToStores = "../etc"; 55 private static String keyStoreFile = "keystore"; 56 private static String trustStoreFile = "truststore"; 57 private static String passwd = "passphrase"; 58 59 private static String keyFilename = 60 System.getProperty("test.src", "./") + "/" + pathToStores + 61 "/" + keyStoreFile; 62 private static String trustFilename = 63 System.getProperty("test.src", "./") + "/" + pathToStores + 64 "/" + trustStoreFile; 65 66 private ByteBuffer appOut1; // write side of ssle1 67 private ByteBuffer appIn1; // read side of ssle1 68 private ByteBuffer appOut2; // write side of ssle2 69 private ByteBuffer appIn2; // read side of ssle2 70 71 private ByteBuffer oneToTwo; // "reliable" transport ssle1->ssle2 72 private ByteBuffer twoToOne; // "reliable" transport ssle2->ssle1 73 74 private int appBufferMax; 75 private int netBufferMax; 76 private int OFFSET = 37; 77 78 /* 79 * Majority of the test case is here, setup is done below. 80 */ 81 private void createSSLEngines() throws Exception { 82 ssle1 = sslc.createSSLEngine("client", 1); 83 ssle1.setUseClientMode(true); 84 85 ssle2 = sslc.createSSLEngine(); 86 ssle2.setUseClientMode(false); 87 ssle2.setNeedClientAuth(true); 88 } 89 90 private void runTest(String cipher) throws Exception { 91 boolean dataDone = false; 92 93 createSSLEngines(); 94 95 System.out.println("Using " + cipher); 96 ssle1.setEnabledCipherSuites(new String [] { cipher }); 97 ssle2.setEnabledCipherSuites(new String [] { cipher }); 98 99 createBuffers(); 100 101 SSLEngineResult result1; // ssle1's results from last operation 102 SSLEngineResult result2; // ssle2's results from last operation 103 104 while (!isEngineClosed(ssle1) || !isEngineClosed(ssle2)) { 105 106 log("================"); 107 108 result1 = ssle1.wrap(appOut1, oneToTwo); 109 result2 = ssle2.wrap(appOut2, twoToOne); 110 111 if ((result1.bytesConsumed() != 0) && 112 (result1.bytesConsumed() != appBufferMax) && 113 (result1.bytesConsumed() != OFFSET)) { 114 throw new Exception("result1: " + result1); 115 } 116 117 if ((result2.bytesConsumed() != 0) && 118 (result2.bytesConsumed() != appBufferMax) && 119 (result2.bytesConsumed() != 2 * OFFSET)) { 120 throw new Exception("result2: " + result2); 121 } 122 123 log("wrap1: " + result1); 124 log("oneToTwo = " + oneToTwo); 125 log(""); 126 127 log("wrap2: " + result2); 128 log("twoToOne = " + twoToOne); 129 130 runDelegatedTasks(result1, ssle1); 131 runDelegatedTasks(result2, ssle2); 132 133 oneToTwo.flip(); 134 twoToOne.flip(); 135 136 log("----"); 137 138 result1 = ssle1.unwrap(twoToOne, appIn1); 139 result2 = ssle2.unwrap(oneToTwo, appIn2); 140 141 if ((result1.bytesProduced() != 0) && 142 (result1.bytesProduced() != appBufferMax) && 143 (result1.bytesProduced() != 2 * OFFSET)) { 144 throw new Exception("result1: " + result1); 145 } 146 147 if ((result2.bytesProduced() != 0) && 148 (result2.bytesProduced() != appBufferMax) && 149 (result2.bytesProduced() != OFFSET)) { 150 throw new Exception("result1: " + result1); 151 } 152 153 log("unwrap1: " + result1); 154 log("twoToOne = " + twoToOne); 155 log(""); 156 157 log("unwrap2: " + result2); 158 log("oneToTwo = " + oneToTwo); 159 160 runDelegatedTasks(result1, ssle1); 161 runDelegatedTasks(result2, ssle2); 162 163 oneToTwo.compact(); 164 twoToOne.compact(); 165 166 /* 167 * If we've transfered all the data between app1 and app2, 168 * we try to close and see what that gets us. 169 */ 170 if (!dataDone && (appOut1.limit() == appIn2.position()) && 171 (appOut2.limit() == appIn1.position())) { 172 173 checkTransfer(appOut1, appIn2); 174 checkTransfer(appOut2, appIn1); 175 176 log("Closing ssle1's *OUTBOUND*..."); 177 ssle1.closeOutbound(); 178 dataDone = true; 179 } 180 } 181 } 182 183 public static void main(String args[]) throws Exception { 184 // reset the security property to make sure that the algorithms 185 // and keys used in this test are not disabled. 186 Security.setProperty("jdk.tls.disabledAlgorithms", ""); 187 188 LargeBufs test; 189 190 test = new LargeBufs(); 191 test.runTest("SSL_RSA_WITH_RC4_128_MD5"); 192 193 test = new LargeBufs(); 194 test.runTest("SSL_RSA_WITH_3DES_EDE_CBC_SHA"); 195 196 System.out.println("Test Passed."); 197 } 198 199 /* 200 * ********************************************************** 201 * Majority of the test case is above, below is just setup stuff 202 * ********************************************************** 203 */ 204 205 public LargeBufs() throws Exception { 206 sslc = getSSLContext(keyFilename, trustFilename); 207 } 208 209 /* 210 * Create an initialized SSLContext to use for this test. 211 */ 212 private SSLContext getSSLContext(String keyFile, String trustFile) 213 throws Exception { 214 215 KeyStore ks = KeyStore.getInstance("JKS"); 216 KeyStore ts = KeyStore.getInstance("JKS"); 217 218 char[] passphrase = "passphrase".toCharArray(); 219 220 ks.load(new FileInputStream(keyFile), passphrase); 221 ts.load(new FileInputStream(trustFile), passphrase); 222 223 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 224 kmf.init(ks, passphrase); 225 226 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 227 tmf.init(ts); 228 229 SSLContext sslCtx = SSLContext.getInstance("TLS"); 230 231 sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 232 233 return sslCtx; 234 } 235 236 private void createBuffers() { 237 // Size the buffers as appropriate. 238 239 SSLSession session = ssle1.getSession(); 240 241 // The maximum application buffer should calculate like 242 // appBufferMax = session.getApplicationBufferSize(); 243 // however, the getApplicationBufferSize() doesn't guarantee 244 // that the ability to concume or produce applicaton data upto 245 // the size. 16384 is the default JSSE implementation maximum 246 // application size that could be consumed and produced. 247 appBufferMax = 16384; 248 netBufferMax = session.getPacketBufferSize(); 249 250 Random random = new Random(); 251 byte [] one = new byte [appBufferMax * 5 + OFFSET]; 252 byte [] two = new byte [appBufferMax * 5 + 2 * OFFSET]; 253 254 random.nextBytes(one); 255 random.nextBytes(two); 256 257 appOut1 = ByteBuffer.wrap(one); 258 appOut2 = ByteBuffer.wrap(two); 259 260 appIn1 = ByteBuffer.allocate(appBufferMax * 6); 261 appIn2 = ByteBuffer.allocate(appBufferMax * 6); 262 263 oneToTwo = ByteBuffer.allocateDirect(netBufferMax); 264 twoToOne = ByteBuffer.allocateDirect(netBufferMax); 265 266 System.out.println("Testing arrays of: " + one.length + 267 " and " + two.length); 268 269 log("AppOut1 = " + appOut1); 270 log("AppOut2 = " + appOut2); 271 log(""); 272 } 273 274 private static void runDelegatedTasks(SSLEngineResult result, 275 SSLEngine engine) throws Exception { 276 277 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { 278 Runnable runnable; 279 while ((runnable = engine.getDelegatedTask()) != null) { 280 log("running delegated task..."); 281 runnable.run(); 282 } 283 } 284 } 285 286 private static boolean isEngineClosed(SSLEngine engine) { 287 return (engine.isOutboundDone() && engine.isInboundDone()); 288 } 289 290 private static void checkTransfer(ByteBuffer a, ByteBuffer b) 291 throws Exception { 292 a.flip(); 293 b.flip(); 294 295 if (!a.equals(b)) { 296 throw new Exception("Data didn't transfer cleanly"); 297 } else { 298 log("Data transferred cleanly"); 299 } 300 301 a.position(a.limit()); 302 b.position(b.limit()); 303 a.limit(a.capacity()); 304 b.limit(b.capacity()); 305 } 306 307 private static void log(String str) { 308 if (debug) { 309 System.out.println(str); 310 } 311 } 312 }