Path: blob/master/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java
41152 views
/*1* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 816487926* @library ../../27* @library /test/lib28* @summary Verify AES/GCM's limits set in the jdk.tls.keyLimits property29* start a new handshake sequence to renegotiate the symmetric key with an30* SSLSocket connection. This test verifies the handshake method was called31* via debugging info. It does not verify the renegotiation was successful32* as that is very hard.33*34* @run main SSLEngineKeyLimit 0 server AES/GCM/NoPadding keyupdate 105000035* @run main SSLEngineKeyLimit 1 client AES/GCM/NoPadding keyupdate 2^2236*/3738/*39* This test runs in another process so we can monitor the debug40* results. The OutputAnalyzer must see correct debug output to return a41* success.42*/4344import javax.net.ssl.KeyManagerFactory;45import javax.net.ssl.SSLContext;46import javax.net.ssl.SSLEngine;47import javax.net.ssl.SSLEngineResult;48import javax.net.ssl.TrustManagerFactory;49import java.io.File;50import java.io.PrintWriter;51import java.nio.ByteBuffer;52import java.security.KeyStore;53import java.security.SecureRandom;54import java.util.Arrays;5556import jdk.test.lib.process.ProcessTools;57import jdk.test.lib.process.OutputAnalyzer;58import jdk.test.lib.Utils;5960public class SSLEngineKeyLimit {6162SSLEngine eng;63static ByteBuffer cTos;64static ByteBuffer sToc;65static ByteBuffer outdata;66ByteBuffer buf;67static boolean ready = false;6869static String pathToStores = "../../../../javax/net/ssl/etc/";70static String keyStoreFile = "keystore";71static String passwd = "passphrase";72static String keyFilename;73static int dataLen = 10240;74static boolean serverwrite = true;75int totalDataLen = 0;76static boolean sc = true;77int delay = 1;78static boolean readdone = false;7980// Turn on debugging81static boolean debug = false;8283SSLEngineKeyLimit() {84buf = ByteBuffer.allocate(dataLen*4);85}8687/**88* args should have two values: server|client, <limit size>89* Prepending 'p' is for internal use only.90*/91public static void main(String args[]) throws Exception {9293for (int i = 0; i < args.length; i++) {94System.out.print(" " + args[i]);95}96System.out.println();97if (args[0].compareTo("p") != 0) {98boolean expectedFail = (Integer.parseInt(args[0]) == 1);99if (expectedFail) {100System.out.println("Test expected to not find updated msg");101}102103// Write security property file to overwrite default104File f = new File("keyusage."+ System.nanoTime());105PrintWriter p = new PrintWriter(f);106p.write("jdk.tls.keyLimits=");107for (int i = 2; i < args.length; i++) {108p.write(" "+ args[i]);109}110p.close();111112System.setProperty("test.java.opts",113"-Dtest.src=" + System.getProperty("test.src") +114" -Dtest.jdk=" + System.getProperty("test.jdk") +115" -Djavax.net.debug=ssl,handshake" +116" -Djava.security.properties=" + f.getName());117118System.out.println("test.java.opts: " +119System.getProperty("test.java.opts"));120121ProcessBuilder pb = ProcessTools.createTestJvm(122Utils.addTestJavaOpts("SSLEngineKeyLimit", "p", args[1]));123124OutputAnalyzer output = ProcessTools.executeProcess(pb);125try {126if (expectedFail) {127output.shouldNotContain("KeyUpdate: write key updated");128output.shouldNotContain("KeyUpdate: read key updated");129} else {130output.shouldContain("trigger key update");131output.shouldContain("KeyUpdate: write key updated");132output.shouldContain("KeyUpdate: read key updated");133}134} catch (Exception e) {135throw e;136} finally {137System.out.println("-- BEGIN Stdout:");138System.out.println(output.getStdout());139System.out.println("-- END Stdout");140System.out.println("-- BEGIN Stderr:");141System.out.println(output.getStderr());142System.out.println("-- END Stderr");143}144return;145}146147if (args[0].compareTo("p") != 0) {148throw new Exception ("Tried to run outside of a spawned process");149}150151if (args[1].compareTo("client") == 0) {152serverwrite = false;153}154155cTos = ByteBuffer.allocateDirect(dataLen*4);156keyFilename =157System.getProperty("test.src", "./") + "/" + pathToStores +158"/" + keyStoreFile;159160System.setProperty("javax.net.ssl.keyStore", keyFilename);161System.setProperty("javax.net.ssl.keyStorePassword", passwd);162163sToc = ByteBuffer.allocateDirect(dataLen*4);164outdata = ByteBuffer.allocateDirect(dataLen);165166byte[] data = new byte[dataLen];167Arrays.fill(data, (byte)0x0A);168outdata.put(data);169outdata.flip();170cTos.clear();171sToc.clear();172173Thread ts = new Thread(serverwrite ? new Client() : new Server());174ts.start();175(serverwrite ? new Server() : new Client()).run();176ts.interrupt();177ts.join();178}179180private static void doTask(SSLEngineResult result,181SSLEngine engine) throws Exception {182183if (result.getHandshakeStatus() ==184SSLEngineResult.HandshakeStatus.NEED_TASK) {185Runnable runnable;186while ((runnable = engine.getDelegatedTask()) != null) {187print("\trunning delegated task...");188runnable.run();189}190SSLEngineResult.HandshakeStatus hsStatus =191engine.getHandshakeStatus();192if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) {193throw new Exception(194"handshake shouldn't need additional tasks");195}196print("\tnew HandshakeStatus: " + hsStatus);197}198}199200static void print(String s) {201if (debug) {202System.out.println(s);203}204}205206static void log(String s, SSLEngineResult r) {207if (!debug) {208return;209}210System.out.println(s + ": " +211r.getStatus() + "/" + r.getHandshakeStatus()+ " " +212r.bytesConsumed() + "/" + r.bytesProduced() + " ");213214}215216void write() throws Exception {217int i = 0;218SSLEngineResult r;219boolean again = true;220221while (!ready) {222Thread.sleep(delay);223}224print("Write-side. ");225226while (i++ < 150) {227while (sc) {228if (readdone) {229return;230}231Thread.sleep(delay);232}233234outdata.rewind();235print("write wrap");236237while (true) {238r = eng.wrap(outdata, getWriteBuf());239log("write wrap", r);240if (debug && r.getStatus() != SSLEngineResult.Status.OK) {241print("outdata pos: " + outdata.position() +242" rem: " + outdata.remaining() +243" lim: " + outdata.limit() +244" cap: " + outdata.capacity());245print("writebuf pos: " + getWriteBuf().position() +246" rem: " + getWriteBuf().remaining() +247" lim: " + getWriteBuf().limit() +248" cap: " + getWriteBuf().capacity());249}250if (again && r.getStatus() == SSLEngineResult.Status.OK &&251r.getHandshakeStatus() ==252SSLEngineResult.HandshakeStatus.NEED_WRAP) {253print("again");254again = false;255continue;256}257break;258}259doTask(r, eng);260getWriteBuf().flip();261sc = true;262while (sc) {263if (readdone) {264return;265}266Thread.sleep(delay);267}268269while (true) {270buf.clear();271r = eng.unwrap(getReadBuf(), buf);272log("write unwrap", r);273if (debug && r.getStatus() != SSLEngineResult.Status.OK) {274print("buf pos: " + buf.position() +275" rem: " + buf.remaining() +276" lim: " + buf.limit() +277" cap: " + buf.capacity());278print("readbuf pos: " + getReadBuf().position() +279" rem: " + getReadBuf().remaining() +280" lim: " + getReadBuf().limit() +281" cap:" + getReadBuf().capacity());282}283break;284}285doTask(r, eng);286getReadBuf().compact();287print("compacted readbuf pos: " + getReadBuf().position() +288" rem: " + getReadBuf().remaining() +289" lim: " + getReadBuf().limit() +290" cap: " + getReadBuf().capacity());291sc = true;292}293}294295void read() throws Exception {296byte b = 0x0B;297ByteBuffer buf2 = ByteBuffer.allocateDirect(dataLen);298SSLEngineResult r = null;299boolean exit, again = true;300301while (eng == null) {302Thread.sleep(delay);303}304305try {306System.out.println("connected");307print("entering read loop");308ready = true;309while (true) {310311while (!sc) {312Thread.sleep(delay);313}314315print("read wrap");316exit = false;317while (!exit) {318buf2.put(b);319buf2.flip();320r = eng.wrap(buf2, getWriteBuf());321log("read wrap", r);322if (debug) {323// && r.getStatus() != SSLEngineResult.Status.OK) {324print("buf2 pos: " + buf2.position() +325" rem: " + buf2.remaining() +326" cap: " + buf2.capacity());327print("writebuf pos: " + getWriteBuf().position() +328" rem: " + getWriteBuf().remaining() +329" cap: " + getWriteBuf().capacity());330}331if (again && r.getStatus() == SSLEngineResult.Status.OK &&332r.getHandshakeStatus() ==333SSLEngineResult.HandshakeStatus.NEED_WRAP) {334buf2.compact();335again = false;336continue;337}338exit = true;339}340doTask(r, eng);341buf2.clear();342getWriteBuf().flip();343344sc = false;345346while (!sc) {347Thread.sleep(delay);348}349350while (true) {351buf.clear();352r = eng.unwrap(getReadBuf(), buf);353log("read unwrap", r);354if (debug &&355r.getStatus() != SSLEngineResult.Status.OK) {356print("buf pos " + buf.position() +357" rem: " + buf.remaining() +358" lim: " + buf.limit() +359" cap: " + buf.capacity());360print("readbuf pos: " + getReadBuf().position() +361" rem: " + getReadBuf().remaining() +362" lim: " + getReadBuf().limit() +363" cap: " + getReadBuf().capacity());364doTask(r, eng);365}366367if (again && r.getStatus() == SSLEngineResult.Status.OK &&368r.getHandshakeStatus() ==369SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {370buf.clear();371print("again");372again = false;373continue;374375}376break;377}378buf.clear();379getReadBuf().compact();380381totalDataLen += r.bytesProduced();382sc = false;383}384} catch (Exception e) {385sc = false;386readdone = true;387System.out.println(e.getMessage());388e.printStackTrace();389System.out.println("Total data read = " + totalDataLen);390}391}392393ByteBuffer getReadBuf() {394return null;395}396397ByteBuffer getWriteBuf() {398return null;399}400401402SSLContext initContext() throws Exception {403SSLContext sc = SSLContext.getInstance("TLSv1.3");404KeyStore ks = KeyStore.getInstance(405new File(System.getProperty("javax.net.ssl.keyStore")),406passwd.toCharArray());407KeyManagerFactory kmf = KeyManagerFactory.getInstance(408KeyManagerFactory.getDefaultAlgorithm());409kmf.init(ks, passwd.toCharArray());410TrustManagerFactory tmf = TrustManagerFactory.getInstance(411TrustManagerFactory.getDefaultAlgorithm());412tmf.init(ks);413sc.init(kmf.getKeyManagers(),414tmf.getTrustManagers(), new SecureRandom());415return sc;416}417418static class Server extends SSLEngineKeyLimit implements Runnable {419Server() throws Exception {420super();421eng = initContext().createSSLEngine();422eng.setUseClientMode(false);423eng.setNeedClientAuth(true);424}425426public void run() {427try {428if (serverwrite) {429write();430} else {431read();432}433434} catch (Exception e) {435System.out.println("server: " + e.getMessage());436e.printStackTrace();437}438System.out.println("Server closed");439}440441@Override442ByteBuffer getWriteBuf() {443return sToc;444}445@Override446ByteBuffer getReadBuf() {447return cTos;448}449}450451452static class Client extends SSLEngineKeyLimit implements Runnable {453Client() throws Exception {454super();455eng = initContext().createSSLEngine();456eng.setUseClientMode(true);457}458459public void run() {460try {461if (!serverwrite) {462write();463} else {464read();465}466} catch (Exception e) {467System.out.println("client: " + e.getMessage());468e.printStackTrace();469}470System.out.println("Client closed");471}472@Override473ByteBuffer getWriteBuf() {474return cTos;475}476@Override477ByteBuffer getReadBuf() {478return sToc;479}480}481}482483484