10c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom/* 20c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * Copyright (C) 2010 The Android Open Source Project 30c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * 40c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 50c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * you may not use this file except in compliance with the License. 60c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * You may obtain a copy of the License at 70c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * 80c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 90c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * 100c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * Unless required by applicable law or agreed to in writing, software 110c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 120c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * See the License for the specific language governing permissions and 140c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * limitations under the License. 150c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom */ 160c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.javax.net.ssl; 180c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 190c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstromimport java.io.IOException; 200c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstromimport java.nio.ByteBuffer; 214557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLEngine; 224557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLEngineResult; 230c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstromimport javax.net.ssl.SSLEngineResult.HandshakeStatus; 247c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giroimport javax.net.ssl.SSLException; 254557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLSession; 260c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstromimport junit.framework.Assert; 270c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 280c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom/** 290c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * TestSSLEnginePair is a convenience class for other tests that want 300c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * a pair of connected and handshaked client and server SSLEngines for 310c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * testing. 320c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom */ 3358af60a00935641f4669afc358593456944644ecKenny Rootpublic final class TestSSLEnginePair extends Assert implements AutoCloseable { 340c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom public final TestSSLContext c; 350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom public final SSLEngine server; 360c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom public final SSLEngine client; 370c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 380c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom private TestSSLEnginePair(TestSSLContext c, 390c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom SSLEngine server, 400c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom SSLEngine client) { 410c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom this.c = c; 420c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom this.server = server; 430c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom this.client = client; 440c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 450c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 4658af60a00935641f4669afc358593456944644ecKenny Root public static TestSSLEnginePair create() throws IOException { 4758af60a00935641f4669afc358593456944644ecKenny Root return create(null); 4858af60a00935641f4669afc358593456944644ecKenny Root } 4958af60a00935641f4669afc358593456944644ecKenny Root 500c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom public static TestSSLEnginePair create(Hooks hooks) throws IOException { 51059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom return create(TestSSLContext.create(), hooks); 52059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 53059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 54059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public static TestSSLEnginePair create(TestSSLContext c, Hooks hooks) throws IOException { 55727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root return create(c, hooks, null); 56727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 57727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root 58727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root public static TestSSLEnginePair create(TestSSLContext c, Hooks hooks, boolean[] finished) 59727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root throws IOException { 60727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root SSLEngine[] engines = connect(c, hooks, finished); 610c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return new TestSSLEnginePair(c, engines[0], engines[1]); 620c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 630c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 64727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root public static SSLEngine[] connect(TestSSLContext c, Hooks hooks) throws IOException { 65727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root return connect(c, hooks, null); 66727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 67727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root 680c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom /** 690c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * Create a new connected server/client engine pair within a 700c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * existing SSLContext. Optionally specify clientCipherSuites to 710c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * allow forcing new SSLSession to test SSLSessionContext 720c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * caching. Optionally specify serverCipherSuites for testing 730c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom * cipher suite negotiation. 740c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom */ 75059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public static SSLEngine[] connect(final TestSSLContext c, 76727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root Hooks hooks, 77727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root boolean finished[]) throws IOException { 780c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (hooks == null) { 790c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom hooks = new Hooks(); 800c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 810c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 82727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root // FINISHED state should be returned only once. 83727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root boolean[] clientFinished = new boolean[1]; 84727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root boolean[] serverFinished = new boolean[1]; 85727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root 86059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom SSLSession session = c.clientContext.createSSLEngine().getSession(); 870c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 880c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom int packetBufferSize = session.getPacketBufferSize(); 890c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom ByteBuffer clientToServer = ByteBuffer.allocate(packetBufferSize); 900c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom ByteBuffer serverToClient = ByteBuffer.allocate(packetBufferSize); 910c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 920c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom int applicationBufferSize = session.getApplicationBufferSize(); 930c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom ByteBuffer scratch = ByteBuffer.allocate(applicationBufferSize); 940c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 953ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root SSLEngine client = c.clientContext.createSSLEngine(c.host.getHostName(), c.port); 96059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom SSLEngine server = c.serverContext.createSSLEngine(); 970c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom client.setUseClientMode(true); 980c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom server.setUseClientMode(false); 990c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom hooks.beforeBeginHandshake(client, server); 1000c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom client.beginHandshake(); 1010c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom server.beginHandshake(); 1020c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 1030c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom while (true) { 1040c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom boolean clientDone = client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING; 1050c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom boolean serverDone = server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING; 1060c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (clientDone && serverDone) { 1070c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom break; 1080c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1090c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 1100c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom boolean progress = false; 1110c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (!clientDone) { 1120c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom progress |= handshakeCompleted(client, 1130c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom clientToServer, 1140c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom serverToClient, 115727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root scratch, 116727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root clientFinished); 1170c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1180c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (!serverDone) { 1190c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom progress |= handshakeCompleted(server, 1200c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom serverToClient, 1210c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom clientToServer, 122727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root scratch, 123727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root serverFinished); 1240c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1250c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (!progress) { 1260c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom break; 1270c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1280c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1290c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 130727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root if (finished != null) { 131727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root assertEquals(2, finished.length); 132727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root finished[0] = clientFinished[0]; 133a368cef707903c2adc7868ba48a95ccdac5f7625Kenny Root finished[1] = serverFinished[0]; 134727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 1350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return new SSLEngine[] { server, client }; 1360c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1370c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 1380c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom public static class Hooks { 1390c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom void beforeBeginHandshake(SSLEngine client, SSLEngine server) {} 1400c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1410c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 1427c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro public void close() throws SSLException { 1437c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro close(new SSLEngine[] { client, server }); 1447c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro } 1457c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro 1467c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro public static void close(SSLEngine[] engines) { 1477c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro try { 1487c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro for (SSLEngine engine : engines) { 1497c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro if (engine != null) { 1507c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro engine.closeInbound(); 1517c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro engine.closeOutbound(); 1527c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro } 1537c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro } 1547c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro } catch (Exception e) { 1557c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro throw new RuntimeException(e); 1567c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro } 1577c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro } 1587c4f30cf50079df52bc4572688c7c9eed129a4bbSergio Giro 1590c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom private static boolean handshakeCompleted(SSLEngine engine, 1600c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom ByteBuffer output, 1610c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom ByteBuffer input, 162727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root ByteBuffer scratch, 163727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root boolean[] finished) throws IOException { 1640c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom try { 1650c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // make the other side's output into our input 1660c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom input.flip(); 1670c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 1680c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom HandshakeStatus status = engine.getHandshakeStatus(); 1690c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom switch (status) { 1700c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 171727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root case NEED_TASK: { 1720c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom boolean progress = false; 1730c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom while (true) { 1740c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom Runnable runnable = engine.getDelegatedTask(); 1750c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (runnable == null) { 1760c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return progress; 1770c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 1780c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom runnable.run(); 1790c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom progress = true; 1800c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 181727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 1820c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 183727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root case NEED_UNWRAP: { 1840c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // avoid underflow 1850c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (input.remaining() == 0) { 1860c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return false; 1870c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 188946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root int inputPositionBefore = input.position(); 1890c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom SSLEngineResult unwrapResult = engine.unwrap(input, scratch); 1900c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom assertEquals(SSLEngineResult.Status.OK, unwrapResult.getStatus()); 1910c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom assertEquals(0, scratch.position()); 192946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root assertEquals(0, unwrapResult.bytesProduced()); 193946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root assertEquals(input.position() - inputPositionBefore, unwrapResult.bytesConsumed()); 194727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root assertFinishedOnce(finished, unwrapResult); 1950c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return true; 196727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 1970c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 198727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root case NEED_WRAP: { 1990c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // avoid possible overflow 2000c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom if (output.remaining() != output.capacity()) { 2010c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return false; 2020c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 203946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root ByteBuffer emptyByteBuffer = ByteBuffer.allocate(0); 204946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root int inputPositionBefore = emptyByteBuffer.position(); 205946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root int outputPositionBefore = output.position(); 206946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root SSLEngineResult wrapResult = engine.wrap(emptyByteBuffer, output); 2070c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom assertEquals(SSLEngineResult.Status.OK, wrapResult.getStatus()); 208946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root assertEquals(0, wrapResult.bytesConsumed()); 209946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root assertEquals(inputPositionBefore, emptyByteBuffer.position()); 210946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root assertEquals(output.position() - outputPositionBefore, 211946d9a0b59d1a615278ad52518fa588407dfebd2Kenny Root wrapResult.bytesProduced()); 212727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root assertFinishedOnce(finished, wrapResult); 2130c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom return true; 214727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 2150c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom 2160c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom case NOT_HANDSHAKING: 2170c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // should have been checked by caller before calling 2180c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom case FINISHED: 2190c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // only returned by wrap/unrap status, not getHandshakeStatus 2200c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom throw new IllegalStateException("Unexpected HandshakeStatus = " + status); 2210c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom default: 2220c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom throw new IllegalStateException("Unknown HandshakeStatus = " + status); 2230c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 2240c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } finally { 2250c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom // shift consumed input, restore to output mode 2260c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom input.compact(); 2270c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 2280c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom } 229727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root 230727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root private static void assertFinishedOnce(boolean[] finishedOut, SSLEngineResult result) { 231727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root if (result.getHandshakeStatus() == HandshakeStatus.FINISHED) { 232727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root assertFalse("should only return FINISHED once", finishedOut[0]); 233727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root finishedOut[0] = true; 234727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 235727df1258e3b8386afea4778626c9ab16ef467d6Kenny Root } 2360c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom} 237