# HG changeset patch # User ascarpino # Date 1529448815 25200 # Node ID 6210466cf1ac78c389f3c3ac5890a8530a4b4ee4 # Parent b472b5917a1b069129663ee03613c68ca01ecb78 read side key limits diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/InputRecord.java --- a/src/java.base/share/classes/sun/security/ssl/InputRecord.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/InputRecord.java Tue Jun 19 15:53:35 2018 -0700 @@ -42,6 +42,8 @@ */ abstract class InputRecord implements Record, Closeable { SSLReadCipher readCipher; + // Needed for KeyUpdate, used after Handshake.Finished + TransportContext tc; final HandshakeHash handshakeHash; boolean isClosed; diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/KeyUpdate.java --- a/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/KeyUpdate.java Tue Jun 19 15:53:35 2018 -0700 @@ -238,6 +238,7 @@ // Update the write key and IV. handshakeProducer.produce(hc, new KeyUpdateMessage(hc, KeyUpdateRequest.NOTREQUESTED)); + return; } // clean handshake context diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/OutputRecord.java --- a/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Tue Jun 19 15:53:35 2018 -0700 @@ -42,7 +42,7 @@ abstract class OutputRecord extends ByteArrayOutputStream implements Record, Closeable { SSLWriteCipher writeCipher; - // Needed for KeyUpdate + // Needed for KeyUpdate, used after Handshake.Finished TransportContext tc; final HandshakeHash handshakeHash; diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/SSLCipher.java --- a/src/java.base/share/classes/sun/security/ssl/SSLCipher.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/SSLCipher.java Tue Jun 19 15:53:35 2018 -0700 @@ -564,6 +564,8 @@ abstract static class SSLReadCipher { final Authenticator authenticator; final ProtocolVersion protocolVersion; + boolean keyLimitEnabled = false; + long keyLimitCountdown = 0; SecretKey baseSecret; SSLReadCipher(Authenticator authenticator, @@ -606,6 +608,20 @@ boolean isNullCipher() { return false; } + + /** + * Check if processed bytes have reached the key usage limit. + * If key usage limit is not be monitored, return false. + */ + public boolean atKeyLimit() { + if (keyLimitCountdown >= 0) { + return false; + } + + // Turn off limit checking as KeyUpdate will be occurring + keyLimitEnabled = false; + return true; + } } interface WriteCipherGenerator { @@ -1801,6 +1817,16 @@ this.iv = ((IvParameterSpec)params).getIV(); this.random = random; + keyLimitCountdown = cipherLimits.getOrDefault( + algorithm.toUpperCase() + ":" + tag[0], 0L); + if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.fine("KeyLimit read side: algorithm = " + + algorithm.toUpperCase() + ":" + tag[0] + + "\ncountdown value = " + keyLimitCountdown); + } + if (keyLimitCountdown > 0) { + keyLimitEnabled = true; + } // DON'T initialize the cipher for AEAD! } @@ -1888,6 +1914,9 @@ SSLLogger.fine( "Plaintext after DECRYPTION", bb.duplicate()); } + if (keyLimitEnabled) { + keyLimitCountdown -= len; + } return new Plaintext(contentType, ProtocolVersion.NONE.major, ProtocolVersion.NONE.minor, @@ -1945,9 +1974,9 @@ keyLimitCountdown = cipherLimits.getOrDefault( algorithm.toUpperCase() + ":" + tag[0], 0L); if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.fine("algorithm = " + algorithm.toUpperCase() + - ":" + tag[0] + "\ncountdown value = " + - keyLimitCountdown); + SSLLogger.fine("KeyLimit write side: algorithm = " + + algorithm.toUpperCase() + ":" + tag[0] + + "\ncountdown value = " + keyLimitCountdown); } if (keyLimitCountdown > 0) { keyLimitEnabled = true; diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Tue Jun 19 15:53:35 2018 -0700 @@ -34,6 +34,8 @@ import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLProtocolException; import sun.security.ssl.SSLCipher.SSLReadCipher; +import sun.security.ssl.KeyUpdate.KeyUpdateMessage; +import sun.security.ssl.KeyUpdate.KeyUpdateRequest; /** * {@code InputRecord} implementation for {@code SSLEngine}. @@ -331,6 +333,20 @@ return plaintexts.toArray(new Plaintext[0]); } + // KeyLimit check during application data. + // atKeyLimit() inactive when limits not checked, tc set when limits + // are active. + + if (readCipher.atKeyLimit()) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.fine("KeyUpdate: triggered, read side."); + } + + PostHandshakeContext p = new PostHandshakeContext(tc); + KeyUpdate.handshakeProducer.produce(p, + new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED)); + } + return new Plaintext[] { new Plaintext(contentType, majorVersion, minorVersion, -1, -1L, fragment) diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java --- a/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Tue Jun 19 15:53:35 2018 -0700 @@ -249,9 +249,11 @@ isFirstAppOutputRecord = false; } + // atKeyLimit() inactive when limits not checked, tc set when limits + // are active. if (writeCipher.atKeyLimit()) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.fine("KeyUpdate: triggered"); + SSLLogger.fine("KeyUpdate: triggered, write side."); } PostHandshakeContext p = new PostHandshakeContext(tc); diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Tue Jun 19 15:53:35 2018 -0700 @@ -38,6 +38,8 @@ import javax.net.ssl.SSLProtocolException; import sun.security.ssl.SSLCipher.SSLReadCipher; +import sun.security.ssl.KeyUpdate.KeyUpdateMessage; +import sun.security.ssl.KeyUpdate.KeyUpdateRequest; /** * {@code InputRecord} implementation for {@code SSLSocket}. @@ -346,10 +348,23 @@ return plaintexts.toArray(new Plaintext[0]); } + // KeyLimit check during application data. + // atKeyLimit() inactive when limits not checked, tc set when limits + // are active. + + if (readCipher.atKeyLimit()) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.fine("KeyUpdate: triggered, read side."); + } + + PostHandshakeContext p = new PostHandshakeContext(tc); + KeyUpdate.handshakeProducer.produce(p, + new KeyUpdateMessage(p, KeyUpdateRequest.REQUESTED)); + } + return new Plaintext[] { new Plaintext(contentType, majorVersion, minorVersion, -1, -1L, fragment) - // recordEpoch, recordSeq, plaintext); }; } diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Tue Jun 19 15:53:35 2018 -0700 @@ -305,9 +305,11 @@ offset += fragLen; + // atKeyLimit() inactive when limits not checked, tc set when limits + // are active. if (writeCipher.atKeyLimit()) { if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.fine("KeyUpdate: triggered"); + SSLLogger.fine("KeyUpdate: triggered, write side."); } PostHandshakeContext p = new PostHandshakeContext(tc); diff -r b472b5917a1b -r 6210466cf1ac src/java.base/share/classes/sun/security/ssl/TransportContext.java --- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java Tue Jun 19 09:05:57 2018 -0700 +++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java Tue Jun 19 15:53:35 2018 -0700 @@ -605,6 +605,7 @@ HandshakeStatus finishHandshake() { if (protocolVersion.useTLS13PlusSpec()) { outputRecord.tc = this; + inputRecord.tc = this; cipherSuite = handshakeContext.negotiatedCipherSuite; inputRecord.readCipher.baseSecret = handshakeContext.baseReadSecret; outputRecord.writeCipher.baseSecret = handshakeContext.baseWriteSecret; diff -r b472b5917a1b -r 6210466cf1ac test/jdk/java/net/httpclient/MockServer.java --- a/test/jdk/java/net/httpclient/MockServer.java Tue Jun 19 09:05:57 2018 -0700 +++ b/test/jdk/java/net/httpclient/MockServer.java Tue Jun 19 15:53:35 2018 -0700 @@ -183,7 +183,8 @@ } catch (IOException |InterruptedException e1) { cleanup(); } catch (Throwable t) { - System.out.println("X: " + t); + System.out.println("Exception: " + t); + t.printStackTrace(); cleanup(); } } diff -r b472b5917a1b -r 6210466cf1ac test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java --- a/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java Tue Jun 19 09:05:57 2018 -0700 +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/SSLEngineKeyLimit.java Tue Jun 19 15:53:35 2018 -0700 @@ -112,7 +112,7 @@ System.setProperty("test.java.opts", "-Dtest.src=" + System.getProperty("test.src") + " -Dtest.jdk=" + System.getProperty("test.jdk") + - " -Djavax.net.debug=ssl" + + " -Djavax.net.debug=ssl,handshake" + " -Djava.security.properties=" + f.getName()); System.out.println("test.java.opts: " + @@ -127,6 +127,8 @@ output.shouldNotContain("KeyUpdate: write key updated"); output.shouldNotContain("KeyUpdate: read key updated"); } else { + output.shouldContain("KeyUpdate: triggered, read side"); + output.shouldContain("KeyUpdate: triggered, write side"); output.shouldContain("KeyUpdate: write key updated"); output.shouldContain("KeyUpdate: read key updated"); } @@ -220,7 +222,7 @@ } print("Write-side. "); - while (i++ < 120) { + while (i++ < 150) { while (sc) { if (readdone) { return; @@ -378,7 +380,7 @@ readdone = true; System.out.println(e.getMessage()); e.printStackTrace(); - print("Total data read = " + totalDataLen); + System.out.println("Total data read = " + totalDataLen); } } @@ -442,7 +444,7 @@ static class Client extends SSLEngineKeyLimit implements Runnable { Client() throws Exception { super(); - eng = initContext().createSSLEngine("client", 80); + eng = initContext().createSSLEngine(); eng.setUseClientMode(true); } diff -r b472b5917a1b -r 6210466cf1ac test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java --- a/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java Tue Jun 19 09:05:57 2018 -0700 +++ b/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketKeyLimit.java Tue Jun 19 15:53:35 2018 -0700 @@ -63,16 +63,12 @@ import sun.security.util.HexDumpEncoder; public class SSLSocketKeyLimit { - - SSLSocket svr, c; - SSLServerSocketFactory ssf; - SSLServerSocket ss; - SSLSocketFactory sf; - InputStream in; - OutputStream out; + SSLSocket socket; + private InputStream in; + private OutputStream out; static boolean serverReady = false; - static int serverPort = 12345; + static int serverPort = 0; static String pathToStores = "../../../../javax/net/ssl/etc/"; static String keyStoreFile = "keystore"; @@ -83,9 +79,7 @@ int totalDataLen = 0; static boolean done = false; - SSLSocketKeyLimit() { - in = new ByteArrayInputStream(new byte[dataLen]); - out = new ByteArrayOutputStream(); + SSLSocketKeyLimit() { } SSLContext initContext() throws Exception { @@ -125,7 +119,7 @@ System.setProperty("test.java.opts", "-Dtest.src=" + System.getProperty("test.src") + " -Dtest.jdk=" + System.getProperty("test.jdk") + - " -Djavax.net.debug=ssl " + + " -Djavax.net.debug=ssl,handshake " + " -Djava.security.properties=" + f.getName()); System.out.println("test.java.opts: " + @@ -140,6 +134,8 @@ output.shouldNotContain("KeyUpdate: write key updated"); output.shouldNotContain("KeyUpdate: read key updated"); } else { + output.shouldContain("KeyUpdate: triggered, read side"); + output.shouldContain("KeyUpdate: triggered, write side"); output.shouldContain("KeyUpdate: write key updated"); output.shouldContain("KeyUpdate: read key updated"); } @@ -175,7 +171,6 @@ Thread.sleep(100); } new Client().run(); - ts.interrupt(); ts.join(10000); // 10sec System.exit(0); } @@ -184,11 +179,12 @@ int i = 0; in = s.getInputStream(); out = s.getOutputStream(); - System.out.print("Write-side writing... "); while (i++ < 150) { out.write(data, 0, dataLen); + System.out.print("W"); + in.readNBytes(1); + System.out.print("R"); } - out.flush(); out.write(0x0D); out.flush(); @@ -196,20 +192,24 @@ while (!done) { Thread.sleep(100); } + out.close(); + in.close(); } void read(SSLSocket s) throws Exception { byte[] buf = new byte[dataLen]; int len; - int i = 0; + byte i = 0; try { - System.out.println("connected " + s.getSession().getCipherSuite()); + System.out.println("Server: connected " + s.getSession().getCipherSuite()); in = s.getInputStream(); out = s.getOutputStream(); while (true) { len = in.read(buf, 0, dataLen); - System.out.print("."); + System.out.print("r"); + out.write(i++); + System.out.print("w"); for (byte b: buf) { if (b == 0x0A || b == 0x0D) { continue; @@ -219,10 +219,9 @@ } if (len > 0 && buf[len-1] == 0x0D) { - System.out.print("got end byte"); + System.out.println("got end byte"); break; } - out.write(i++); totalDataLen += len; } } catch (Exception e) { @@ -230,12 +229,16 @@ e.printStackTrace(); } finally { // Tell write side that we are done reading + out.close(); + in.close(); done = true; } System.out.println("\nTotalDataLen = " + totalDataLen); } static class Server extends SSLSocketKeyLimit implements Runnable { + private SSLServerSocketFactory ssf; + private SSLServerSocket ss; Server() { super(); try { @@ -249,18 +252,17 @@ } public void run() { - try { serverReady = true; - System.out.println("Server waiting... "); - svr = (SSLSocket) ss.accept(); + System.out.println("Server waiting... port: " + serverPort); + socket = (SSLSocket) ss.accept(); if (serverwrite) { - write(svr); + write(socket); } else { - read(svr); + read(socket); } - svr.close(); + socket.close(); } catch (Exception e) { System.out.println("server: " + e.getMessage()); e.printStackTrace(); @@ -271,6 +273,8 @@ static class Client extends SSLSocketKeyLimit implements Runnable { + private SSLSocketFactory sf; + Client() { super(); } @@ -278,15 +282,15 @@ public void run() { try { sf = initContext().getSocketFactory(); - System.out.print("Client connecting... "); - c = (SSLSocket)sf.createSocket("localhost", serverPort); - System.out.println("connected. " + c.getSession().getCipherSuite()); + System.out.println("Client: connecting... port: " + serverPort); + socket = (SSLSocket)sf.createSocket("localhost", serverPort); + System.out.println("Client: connected." + socket.getSession().getCipherSuite()); // Opposite of what the server does if (!serverwrite) { - write(c); + write(socket); } else { - read(c); + read(socket); } } catch (Exception e) {