Path: blob/master/test/jdk/javax/net/ssl/SSLEngine/SSLEngineService.java
41152 views
/*1* Copyright (c) 2006, 2012, 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* @bug 638845625* @summary Need adjustable TLS max record size for interoperability26* with non-compliant stacks27*28* Helper class of SSL/TLS client/server communication.29*30* @author Xuelei Fan31*/3233import javax.net.ssl.*;3435import java.io.*;36import java.security.*;37import java.nio.*;38import java.nio.channels.*;3940public class SSLEngineService {4142private static String keyStoreFile = "keystore";43private static String trustStoreFile = "truststore";44private static char[] passphrase = "passphrase".toCharArray();4546private String pathToStores;47private String keyFilename;48private String trustFilename;4950protected SSLEngineService() {51init("../etc");52}5354protected SSLEngineService(String pathToStores) {55init(pathToStores);56}5758private void init(String pathToStores) {59this.pathToStores = pathToStores;60this.keyFilename =61System.getProperty("test.src", "./") + "/" + pathToStores +62"/" + keyStoreFile;63this.trustFilename =64System.getProperty("test.src", "./") + "/" + pathToStores +65"/" + trustStoreFile;66}6768// deliver local application data.69protected static void deliver(SSLEngine ssle, SocketChannel sc)70throws Exception {7172// create buufer.73int appBufferMax = ssle.getSession().getApplicationBufferSize();74int netBufferMax = ssle.getSession().getPacketBufferSize();75int length = appBufferMax * (Integer.SIZE / 8);7677// allocate more in order to check large packet78ByteBuffer localAppData = ByteBuffer.allocate(length);7980// allocate less in order to check BUFFER_OVERFLOW/BUFFER_UNDERFLOW81ByteBuffer localNetData = ByteBuffer.allocate(netBufferMax/2);8283// prepare local application data84localAppData.putInt(length);85for (int i = 1; i < appBufferMax; i++) {86localAppData.putInt(i);87}88localAppData.flip();899091while (localAppData.hasRemaining()) {92// empty the local network packet buffer.93localNetData.clear();9495// generated local network packet.96SSLEngineResult res = ssle.wrap(localAppData, localNetData);9798// checking status99switch (res.getStatus()) {100101case OK :102localNetData.flip();103104// send the network packet105while (localNetData.hasRemaining()) {106if (sc.write(localNetData) < 0) {107throw new IOException("Unable write to socket channel");108}109}110111if (res.getHandshakeStatus() ==112SSLEngineResult.HandshakeStatus.NEED_TASK) {113Runnable runnable;114while ((runnable = ssle.getDelegatedTask()) != null) {115runnable.run();116}117}118119// detect large buffer120if (res.bytesProduced() >= Short.MAX_VALUE) {121System.out.println("Generate a " +122res.bytesProduced() + " bytes large packet ");123}124break;125126case BUFFER_OVERFLOW :127// maybe need to enlarge the local network packet buffer.128int size = ssle.getSession().getPacketBufferSize();129if (size > localNetData.capacity()) {130System.out.println("resize destination buffer upto " +131size + " bytes for BUFFER_OVERFLOW");132localNetData = enlargeBuffer(localNetData, size);133}134break;135136default : // BUFFER_UNDERFLOW or CLOSED :137throw new IOException("Received invalid" + res.getStatus() +138"during transfer application data");139}140}141}142143144// receive peer application data.145protected static void receive(SSLEngine ssle, SocketChannel sc)146throws Exception {147148// create buufers.149int appBufferMax = ssle.getSession().getApplicationBufferSize();150int netBufferMax = ssle.getSession().getPacketBufferSize();151152// allocate less in order to check BUFFER_OVERFLOW/BUFFER_UNDERFLOW153ByteBuffer peerAppData = ByteBuffer.allocate(appBufferMax/2);154ByteBuffer peerNetData = ByteBuffer.allocate(netBufferMax/2);155int received = -1;156157boolean needToReadMore = true;158while (received != 0) {159if (needToReadMore) {160if (ssle.isInboundDone() || sc.read(peerNetData) < 0) {161break;162}163}164165peerNetData.flip();166SSLEngineResult res = ssle.unwrap(peerNetData, peerAppData);167peerNetData.compact();168169// checking status170switch (res.getStatus()) {171172case OK :173if (res.getHandshakeStatus() ==174SSLEngineResult.HandshakeStatus.NEED_TASK) {175Runnable runnable;176while ((runnable = ssle.getDelegatedTask()) != null) {177runnable.run();178}179}180181if (received < 0 && res.bytesProduced() < 4 ) {182break;183}184185if (received < 0) {186received = peerAppData.getInt(0);187}188189System.out.println("received " + peerAppData.position() +190" bytes client application data");191System.out.println("\tcomsumed " + res.bytesConsumed() +192" byes network data");193peerAppData.clear();194195received -= res.bytesProduced();196197// detect large buffer198if (res.bytesConsumed() >= Short.MAX_VALUE) {199System.out.println("Consumes a " + res.bytesConsumed() +200" bytes large packet ");201}202203needToReadMore = (peerNetData.position() > 0) ? false : true;204205break;206207case BUFFER_OVERFLOW :208// maybe need to enlarge the peer application data buffer.209int size = ssle.getSession().getApplicationBufferSize();210if (size > peerAppData.capacity()) {211System.out.println("resize destination buffer upto " +212size + " bytes for BUFFER_OVERFLOW");213peerAppData = enlargeBuffer(peerAppData, size);214}215break;216217case BUFFER_UNDERFLOW :218// maybe need to enlarge the peer network packet data buffer.219size = ssle.getSession().getPacketBufferSize();220if (size > peerNetData.capacity()) {221System.out.println("resize source buffer upto " + size +222" bytes for BUFFER_UNDERFLOW");223peerNetData = enlargeBuffer(peerNetData, size);224}225226needToReadMore = true;227break;228229default : // CLOSED :230throw new IOException("Received invalid" + res.getStatus() +231"during transfer application data");232}233}234}235236protected static void handshaking(SSLEngine ssle, SocketChannel sc,237ByteBuffer additional) throws Exception {238239int appBufferMax = ssle.getSession().getApplicationBufferSize();240int netBufferMax = ssle.getSession().getPacketBufferSize();241242// allocate less in order to check BUFFER_OVERFLOW/BUFFER_UNDERFLOW243ByteBuffer localAppData = ByteBuffer.allocate(appBufferMax/10);244ByteBuffer peerAppData = ByteBuffer.allocate(appBufferMax/10);245ByteBuffer localNetData = ByteBuffer.allocate(netBufferMax/10);246ByteBuffer peerNetData = ByteBuffer.allocate(netBufferMax/10);247248// begin handshake249ssle.beginHandshake();250SSLEngineResult.HandshakeStatus hs = ssle.getHandshakeStatus();251252// start handshaking from unwrap253byte[] buffer = new byte[0xFF];254boolean underflow = false;255do {256switch (hs) {257258case NEED_UNWRAP :259if (peerNetData.position() == 0) {260if (additional != null && additional.hasRemaining()) {261do {262int len = Math.min(buffer.length,263peerNetData.remaining());264len = Math.min(len, additional.remaining());265if (len != 0) {266additional.get(buffer, 0, len);267peerNetData.put(buffer, 0, len);268}269} while (peerNetData.remaining() > 0 &&270additional.hasRemaining());271} else {272if (sc.read(peerNetData) < 0) {273ssle.closeInbound();274return;275}276}277}278279if (underflow) {280if (sc.read(peerNetData) < 0) {281ssle.closeInbound();282return;283}284285underflow = false;286}287288peerNetData.flip();289SSLEngineResult res = ssle.unwrap(peerNetData, peerAppData);290peerNetData.compact();291hs = res.getHandshakeStatus();292293switch (res.getStatus()) {294case OK :295break;296case BUFFER_UNDERFLOW :297// maybe need to enlarge the peer network packet buffer.298int size = ssle.getSession().getPacketBufferSize();299if (size > peerNetData.capacity()) {300System.out.println("resize source buffer upto " +301size + " bytes for BUFFER_UNDERFLOW");302peerNetData = enlargeBuffer(peerNetData, size);303}304305underflow = true;306break;307case BUFFER_OVERFLOW :308// maybe need to enlarge the peer application data buffer.309size = ssle.getSession().getApplicationBufferSize();310if (size > peerAppData.capacity()) {311System.out.println("resize destination buffer upto " +312size + " bytes for BUFFER_OVERFLOW");313peerAppData = enlargeBuffer(peerAppData, size);314}315break;316default : //CLOSED317throw new IOException("Received invalid" + res.getStatus() +318"during initial handshaking");319}320break;321322case NEED_WRAP :323// empty the local network packet buffer.324localNetData.clear();325326// generated local network packet.327res = ssle.wrap(localAppData, localNetData);328hs = res.getHandshakeStatus();329330// checking status331switch (res.getStatus()) {332case OK :333localNetData.flip();334335// send the network packet336while (localNetData.hasRemaining()) {337if (sc.write(localNetData) < 0) {338throw new IOException(339"Unable write to socket channel");340}341}342break;343344case BUFFER_OVERFLOW :345// maybe need to enlarge the local network packet buffer.346int size = ssle.getSession().getPacketBufferSize();347if (size > localNetData.capacity()) {348System.out.println("resize destination buffer upto " +349size + " bytes for BUFFER_OVERFLOW");350localNetData = enlargeBuffer(localNetData, size);351}352break;353354default : // BUFFER_UNDERFLOW or CLOSED :355throw new IOException("Received invalid" + res.getStatus() +356"during initial handshaking");357}358break;359360case NEED_TASK :361Runnable runnable;362while ((runnable = ssle.getDelegatedTask()) != null) {363runnable.run();364}365hs = ssle.getHandshakeStatus();366break;367368default : // FINISHED or NOT_HANDSHAKING369// do nothing370}371} while (hs != SSLEngineResult.HandshakeStatus.FINISHED &&372hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING);373}374375private static ByteBuffer enlargeBuffer(ByteBuffer buffer, int size) {376ByteBuffer bb = ByteBuffer.allocate(size);377buffer.flip();378bb.put(buffer);379380return bb;381}382383/*384* Create an initialized SSLContext to use for this test.385*/386protected SSLEngine createSSLEngine(boolean mode) throws Exception {387388SSLEngine ssle;389390KeyStore ks = KeyStore.getInstance("JKS");391KeyStore ts = KeyStore.getInstance("JKS");392393ks.load(new FileInputStream(keyFilename), passphrase);394ts.load(new FileInputStream(trustFilename), passphrase);395396KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");397kmf.init(ks, passphrase);398399TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");400tmf.init(ts);401402SSLContext sslCtx = SSLContext.getInstance("TLS");403sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);404405ssle = sslCtx.createSSLEngine();406ssle.setUseClientMode(mode);407408return ssle;409}410}411412413