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