1 /* 2 * Copyright (c) 2018, 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 8164879 27 * @library /lib/testlibrary ../../ 28 * @modules java.base/sun.security.util 29 * @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property 30 * @run main SSLSocketKeyLimit 0 server AES/GCM/NoPadding keyupdate 1000000 31 * @run main SSLSocketKeyLimit 0 client AES/GCM/NoPadding keyupdate 1000000 32 * @run main SSLSocketKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^22 33 */ 34 35 /** 36 * Verify AES/GCM's limits set in the jdk.tls.keyLimits property 37 * start a new handshake sequence to renegotiate the symmetric key with an 38 * SSLSocket connection. This test verifies the handshake method was called 39 * via debugging info. It does not verify the renegotiation was successful 40 * as that is very hard. 41 */ 42 43 import javax.net.ssl.KeyManagerFactory; 44 import javax.net.ssl.SSLContext; 45 import javax.net.ssl.SSLServerSocket; 46 import javax.net.ssl.SSLServerSocketFactory; 47 import javax.net.ssl.SSLSocket; 48 import javax.net.ssl.SSLSocketFactory; 49 import javax.net.ssl.TrustManagerFactory; 50 import java.io.ByteArrayInputStream; 51 import java.io.ByteArrayOutputStream; 52 import java.io.File; 53 import java.io.InputStream; 54 import java.io.OutputStream; 55 import java.io.PrintWriter; 56 import java.security.KeyStore; 57 import java.security.SecureRandom; 58 import java.util.Arrays; 59 60 import jdk.testlibrary.ProcessTools; 61 import jdk.testlibrary.Utils; 62 import jdk.testlibrary.OutputAnalyzer; 63 import sun.security.util.HexDumpEncoder; 64 65 public class SSLSocketKeyLimit { 66 SSLSocket socket; 67 private InputStream in; 68 private OutputStream out; 69 70 static boolean serverReady = false; 71 static int serverPort = 0; 72 73 static String pathToStores = "../../../../javax/net/ssl/etc/"; 74 static String keyStoreFile = "keystore"; 75 static String passwd = "passphrase"; 76 static int dataLen = 10240; 77 static byte[] data = new byte[dataLen]; 78 static boolean serverwrite = true; 79 int totalDataLen = 0; 80 static boolean done = false; 81 82 SSLSocketKeyLimit() { 83 } 84 85 SSLContext initContext() throws Exception { 86 SSLContext sc = SSLContext.getInstance("TLSv1.3"); 87 KeyStore ks = KeyStore.getInstance( 88 new File(System.getProperty("javax.net.ssl.keyStore")), 89 passwd.toCharArray()); 90 KeyManagerFactory kmf = 91 KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 92 kmf.init(ks, passwd.toCharArray()); 93 TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 94 tmf.init(ks); 95 sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom()); 96 return sc; 97 } 98 99 /** 100 * args should have two values: server|client, <limit size> 101 * Prepending 'p' is for internal use only. 102 */ 103 public static void main(String args[]) throws Exception { 104 if (args[0].compareTo("p") != 0) { 105 106 boolean expectedFail = (Integer.parseInt(args[0]) == 1); 107 if (expectedFail) { 108 System.out.println("Test expected to not find updated msg"); 109 } 110 //Write security property file to overwrite default 111 File f = new File("keyusage."+ System.nanoTime()); 112 PrintWriter p = new PrintWriter(f); 113 p.write("jdk.tls.keyLimits="); 114 for (int i = 2; i < args.length; i++) { 115 p.write(" "+ args[i]); 116 } 117 p.close(); 118 System.out.println("Keyusage path = " + f.getAbsolutePath()); 119 System.setProperty("test.java.opts", 120 "-Dtest.src=" + System.getProperty("test.src") + 121 " -Dtest.jdk=" + System.getProperty("test.jdk") + 122 " -Djavax.net.debug=ssl,handshake" + 123 " -Djava.security.properties=" + f.getName()); 124 125 System.out.println("test.java.opts: " + 126 System.getProperty("test.java.opts")); 127 128 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, 129 Utils.addTestJavaOpts("SSLSocketKeyLimit", "p", args[1])); 130 131 OutputAnalyzer output = ProcessTools.executeProcess(pb); 132 try { 133 if (expectedFail) { 134 output.shouldNotContain("KeyUpdate: write key updated"); 135 output.shouldNotContain("KeyUpdate: read key updated"); 136 } else { 137 output.shouldContain("trigger key update"); 138 output.shouldContain("KeyUpdate: write key updated"); 139 output.shouldContain("KeyUpdate: read key updated"); 140 } 141 } catch (Exception e) { 142 throw e; 143 } finally { 144 System.out.println("-- BEGIN Stdout:"); 145 System.out.println(output.getStdout()); 146 System.out.println("-- END Stdout"); 147 System.out.println("-- BEGIN Stderr:"); 148 System.out.println(output.getStderr()); 149 System.out.println("-- END Stderr"); 150 } 151 return; 152 } 153 154 if (args.length > 0 && args[0].compareToIgnoreCase("client") == 0) { 155 serverwrite = false; 156 } 157 158 String keyFilename = 159 System.getProperty("test.src", "./") + "/" + pathToStores + 160 "/" + keyStoreFile; 161 162 System.setProperty("javax.net.ssl.keyStore", keyFilename); 163 System.setProperty("javax.net.ssl.keyStorePassword", passwd); 164 165 Arrays.fill(data, (byte)0x0A); 166 Thread ts = new Thread(new Server()); 167 168 ts.start(); 169 while (!serverReady) { 170 Thread.sleep(100); 171 } 172 new Client().run(); 173 ts.join(10000); // 10sec 174 System.exit(0); 175 } 176 177 void write(SSLSocket s) throws Exception { 178 int i = 0; 179 in = s.getInputStream(); 180 out = s.getOutputStream(); 181 while (i++ < 150) { 182 out.write(data, 0, dataLen); 183 System.out.print("W"); 184 in.readNBytes(1); 185 System.out.print("R"); 186 } 187 out.write(0x0D); 188 out.flush(); 189 190 // Let read side all the data 191 while (!done) { 192 Thread.sleep(100); 193 } 194 out.close(); 195 in.close(); 196 } 197 198 199 void read(SSLSocket s) throws Exception { 200 byte[] buf = new byte[dataLen]; 201 int len; 202 byte i = 0; 203 try { 204 System.out.println("Server: connected " + s.getSession().getCipherSuite()); 205 in = s.getInputStream(); 206 out = s.getOutputStream(); 207 while (true) { 208 len = in.read(buf, 0, dataLen); 209 System.out.print("r"); 210 out.write(i++); 211 System.out.print("w"); 212 for (byte b: buf) { 213 if (b == 0x0A || b == 0x0D) { 214 continue; 215 } 216 System.out.println("\nData invalid: " + new HexDumpEncoder().encode(buf)); 217 break; 218 } 219 220 if (len > 0 && buf[len-1] == 0x0D) { 221 System.out.println("got end byte"); 222 break; 223 } 224 totalDataLen += len; 225 } 226 } catch (Exception e) { 227 System.out.println("\n" + e.getMessage()); 228 e.printStackTrace(); 229 } finally { 230 // Tell write side that we are done reading 231 out.close(); 232 in.close(); 233 done = true; 234 } 235 System.out.println("\nTotalDataLen = " + totalDataLen); 236 } 237 238 static class Server extends SSLSocketKeyLimit implements Runnable { 239 private SSLServerSocketFactory ssf; 240 private SSLServerSocket ss; 241 Server() { 242 super(); 243 try { 244 ssf = initContext().getServerSocketFactory(); 245 ss = (SSLServerSocket) ssf.createServerSocket(serverPort); 246 serverPort = ss.getLocalPort(); 247 } catch (Exception e) { 248 System.out.println("server: " + e.getMessage()); 249 e.printStackTrace(); 250 } 251 } 252 253 public void run() { 254 try { 255 serverReady = true; 256 System.out.println("Server waiting... port: " + serverPort); 257 socket = (SSLSocket) ss.accept(); 258 if (serverwrite) { 259 write(socket); 260 } else { 261 read(socket); 262 } 263 264 socket.close(); 265 } catch (Exception e) { 266 System.out.println("server: " + e.getMessage()); 267 e.printStackTrace(); 268 } 269 System.out.println("Server closed"); 270 } 271 } 272 273 274 static class Client extends SSLSocketKeyLimit implements Runnable { 275 private SSLSocketFactory sf; 276 277 Client() { 278 super(); 279 } 280 281 public void run() { 282 try { 283 sf = initContext().getSocketFactory(); 284 System.out.println("Client: connecting... port: " + serverPort); 285 socket = (SSLSocket)sf.createSocket("localhost", serverPort); 286 System.out.println("Client: connected." + socket.getSession().getCipherSuite()); 287 288 // Opposite of what the server does 289 if (!serverwrite) { 290 write(socket); 291 } else { 292 read(socket); 293 } 294 295 } catch (Exception e) { 296 System.err.println("client: " + e.getMessage()); 297 e.printStackTrace(); 298 } 299 } 300 } 301 }