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