Home | History | Annotate | Download | only in jsse
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package org.apache.harmony.xnet.provider.jsse;
     19 
     20 import java.nio.ByteBuffer;
     21 import java.util.Arrays;
     22 import javax.net.ssl.SSLEngine;
     23 import javax.net.ssl.SSLEngineResult;
     24 import javax.net.ssl.SSLException;
     25 import javax.net.ssl.SSLSession;
     26 
     27 import junit.framework.Test;
     28 import junit.framework.TestCase;
     29 import junit.framework.TestSuite;
     30 
     31 /**
     32  * SSLEngine implementation test.
     33  */
     34 public class SSLEngineImplTest extends TestCase {
     35 
     36     /**
     37      * The cipher suites used for functionality testing.
     38      */
     39     private static final String[] cipher_suites = {
     40         "RSA_WITH_RC4_128_MD5",
     41         "RSA_WITH_DES_CBC_SHA",
     42         "DH_anon_EXPORT_WITH_DES40_CBC_SHA"
     43     };
     44 
     45     /**
     46      * Test logging switch.
     47      */
     48     private static boolean doLog = false;
     49 
     50     /**
     51      * Sets up the test case.
     52      */
     53     @Override
     54     public void setUp() throws Exception {
     55         if (doLog) {
     56             System.out.println("");
     57             System.out.println("========================");
     58             System.out.println("====== Running the test: " + getName());
     59             System.out.println("========================");
     60         }
     61     }
     62 
     63     /**
     64      * Tests the interaction between the engines.
     65      */
     66     public void testSelfInteraction() throws Exception {
     67         String[] protocols = {"SSLv3", "TLSv1"};
     68         for (int i=0; i<cipher_suites.length; i++) {
     69             for (int j=0; j<2; j++) {
     70                 if (doLog) {
     71                     System.out.println("\n===== Interact over suite: "
     72                             + cipher_suites[i]);
     73                 }
     74                 SSLEngine client = getEngine();
     75                 SSLEngine server = getEngine();
     76                 initEngines(client, server);
     77 
     78                 doHandshake(client, server);
     79                 doDataExchange(client, server);
     80                 doClose(client, server);
     81             }
     82         }
     83     }
     84 
     85     /**
     86      * Tests the session negotiation process.
     87      */
     88     public void testHandshake() throws Exception {
     89         SSLEngine client = getEngine();
     90         SSLEngine server = getEngine();
     91 
     92         initEngines(client, server);
     93 
     94         // checks the impossibility of initial handshake
     95         // with the server not allowed to session creation
     96         doNoRenegotiationTest(client, server, true);
     97 
     98         client = getEngine();
     99         server = getEngine();
    100         initEngines(client, server);
    101 
    102         client.setUseClientMode(true);
    103         server.setUseClientMode(false);
    104 
    105         // do initial handshake
    106         doHandshake(client, server);
    107 
    108         // client initiates rehandshake
    109         client.beginHandshake();
    110         doHandshakeImpl(client, server);
    111 
    112         // server initiates rehandshake
    113         server.beginHandshake();
    114         doHandshakeImpl(client, server);
    115 
    116         // client initiates rehandshake while server invalidates
    117         // used session
    118         server.getSession().invalidate();
    119         client.beginHandshake();
    120         doHandshakeImpl(client, server);
    121 
    122         // server initiates rehandshake while client invalidates
    123         // used session
    124         client.getSession().invalidate();
    125         server.beginHandshake();
    126         doHandshakeImpl(client, server);
    127 
    128         client.getSession().invalidate();
    129         server.getSession().invalidate();
    130         doHandshake(client, server);
    131 
    132         doNoRenegotiationTest(client, server, false);
    133 
    134         doNoRenegotiationTest(server, client, false);
    135 
    136         doClose(client, server);
    137     }
    138 
    139     /**
    140      * setNeedClientAuth(boolean need) method testing.
    141      * getNeedClientAuth() method testing.
    142      */
    143     public void testSetGetNeedClientAuth() throws Exception {
    144         SSLEngine engine = getEngine();
    145 
    146         engine.setWantClientAuth(true);
    147         engine.setNeedClientAuth(false);
    148         assertFalse("Result differs from expected",
    149                 engine.getNeedClientAuth());
    150         assertFalse("Socket did not reset its want client auth state",
    151                 engine.getWantClientAuth());
    152         engine.setWantClientAuth(true);
    153         engine.setNeedClientAuth(true);
    154         assertTrue("Result differs from expected",
    155                 engine.getNeedClientAuth());
    156         assertFalse("Socket did not reset its want client auth state",
    157                 engine.getWantClientAuth());
    158     }
    159 
    160     /**
    161      * setWantClientAuth(boolean want) method testing.
    162      * getWantClientAuth() method testing.
    163      */
    164     public void testSetGetWantClientAuth() throws Exception {
    165         SSLEngine engine = getEngine();
    166 
    167         engine.setNeedClientAuth(true);
    168         engine.setWantClientAuth(false);
    169         assertFalse("Result differs from expected",
    170                 engine.getWantClientAuth());
    171         assertFalse("Socket did not reset its want client auth state",
    172                 engine.getNeedClientAuth());
    173         engine.setNeedClientAuth(true);
    174         engine.setWantClientAuth(true);
    175         assertTrue("Result differs from expected",
    176                 engine.getWantClientAuth());
    177         assertFalse("Socket did not reset its want client auth state",
    178                 engine.getNeedClientAuth());
    179     }
    180 
    181     /**
    182      * getSupportedCipherSuites() method testing.
    183      */
    184     public void testGetSupportedCipherSuites() throws Exception {
    185         SSLEngine engine = getEngine();
    186         String[] supported = engine.getSupportedCipherSuites();
    187         assertNotNull(supported);
    188         supported[0] = "NOT_SUPPORTED_CIPHER_SUITE";
    189         supported = engine.getEnabledCipherSuites();
    190         for (int i=0; i<supported.length; i++) {
    191             if ("NOT_SUPPORTED_CIPHER_SUITE".equals(supported[i])) {
    192                 fail("Modification of the returned result "
    193                         + "causes the modification of the internal state");
    194             }
    195         }
    196     }
    197 
    198     /**
    199      * getEnabledCipherSuites() method testing.
    200      */
    201     public void testGetEnabledCipherSuites() throws Exception {
    202         SSLEngine engine = getEngine();
    203         String[] enabled = engine.getEnabledCipherSuites();
    204         assertNotNull(enabled);
    205         String[] supported = engine.getSupportedCipherSuites();
    206         for (int i=0; i<enabled.length; i++) {
    207             found: {
    208                 for (int j=0; j<supported.length; j++) {
    209                     if (enabled[i].equals(supported[j])) {
    210                         break found;
    211                     }
    212                 }
    213                 fail("Enabled suite does not belong to the set "
    214                         + "of supported cipher suites: " + enabled[i]);
    215             }
    216         }
    217         engine.setEnabledCipherSuites(supported);
    218         for (int i=0; i<supported.length; i++) {
    219             enabled = new String[supported.length - i];
    220             System.arraycopy(supported, 0,
    221                     enabled, 0, supported.length-i);
    222             engine.setEnabledCipherSuites(enabled);
    223             String[] result = engine.getEnabledCipherSuites();
    224             if (result.length != enabled.length) {
    225                 fail("Returned result differs from expected.");
    226             }
    227             for (int k=0; k<result.length; k++) {
    228                 found: {
    229                     for (int n=0; n<enabled.length; n++) {
    230                         if (result[k].equals(enabled[n])) {
    231                             break found;
    232                         }
    233                     }
    234                     if (result.length != enabled.length) {
    235                         fail("Returned result does not correspond "
    236                                 + "to expected.");
    237                     }
    238                 }
    239             }
    240         }
    241     }
    242 
    243     /**
    244      * setEnabledCipherSuites(String[] suites) method testing.
    245      */
    246     public void testSetEnabledCipherSuites() throws Exception {
    247         SSLEngine engine = getEngine();
    248         String[] enabled = engine.getEnabledCipherSuites();
    249         assertNotNull(enabled);
    250         String[] supported = engine.getSupportedCipherSuites();
    251         for (int i=0; i<enabled.length; i++) {
    252             found: {
    253                 for (int j=0; j<supported.length; j++) {
    254                     if (enabled[i].equals(supported[j])) {
    255                         break found;
    256                     }
    257                 }
    258                 fail("Enabled suite does not belong to the set "
    259                         + "of supported cipher suites: " + enabled[i]);
    260             }
    261         }
    262         engine.setEnabledCipherSuites(supported);
    263         engine.setEnabledCipherSuites(enabled);
    264         engine.setEnabledCipherSuites(supported);
    265         String[] more_than_supported = new String[supported.length+1];
    266         for (int i=0; i<supported.length+1; i++) {
    267             more_than_supported[i]
    268                 = "NOT_SUPPORTED_CIPHER_SUITE";
    269             System.arraycopy(supported, 0,
    270                     more_than_supported, 0, i);
    271             System.arraycopy(supported, i,
    272                     more_than_supported, i+1, supported.length-i);
    273             try {
    274                 engine.setEnabledCipherSuites(more_than_supported);
    275                 fail("Expected IllegalArgumentException was not thrown");
    276             } catch (IllegalArgumentException e) { }
    277         }
    278         enabled = engine.getEnabledCipherSuites();
    279         enabled[0] = "NOT_SUPPORTED_CIPHER_SUITE";
    280         enabled = engine.getEnabledCipherSuites();
    281         for (int i=0; i<enabled.length; i++) {
    282             if ("NOT_SUPPORTED_CIPHER_SUITE".equals(enabled[i])) {
    283                 fail("Modification of the returned result "
    284                         + "causes the modification of the internal state");
    285             }
    286         }
    287     }
    288 
    289     /**
    290      * getSupportedProtocols() method testing.
    291      */
    292     public void testGetSupportedProtocols() throws Exception {
    293         SSLEngine engine = getEngine();
    294         String[] supported = engine.getSupportedProtocols();
    295         assertNotNull(supported);
    296         assertFalse(supported.length == 0);
    297         supported[0] = "NOT_SUPPORTED_PROTOCOL";
    298         supported = engine.getSupportedProtocols();
    299         for (int i=0; i<supported.length; i++) {
    300             if ("NOT_SUPPORTED_PROTOCOL".equals(supported[i])) {
    301                 fail("Modification of the returned result "
    302                         + "causes the modification of the internal state");
    303             }
    304         }
    305     }
    306 
    307     /**
    308      * getEnabledProtocols() method testing.
    309      */
    310     public void testGetEnabledProtocols() throws Exception {
    311         SSLEngine engine = getEngine();
    312         String[] enabled = engine.getEnabledProtocols();
    313         assertNotNull(enabled);
    314         String[] supported = engine.getSupportedProtocols();
    315         for (int i=0; i<enabled.length; i++) {
    316             found: {
    317                 for (int j=0; j<supported.length; j++) {
    318                     if (enabled[i].equals(supported[j])) {
    319                         break found;
    320                     }
    321                 }
    322                 fail("Enabled protocol does not belong to the set "
    323                         + "of supported protocols: " + enabled[i]);
    324             }
    325         }
    326         engine.setEnabledProtocols(supported);
    327         for (int i=0; i<supported.length; i++) {
    328             enabled = new String[supported.length - i];
    329             System.arraycopy(supported, i,
    330                     enabled, 0, supported.length-i);
    331             engine.setEnabledProtocols(enabled);
    332             String[] result = engine.getEnabledProtocols();
    333             if (result.length != enabled.length) {
    334                 fail("Returned result differs from expected.");
    335             }
    336             for (int k=0; k<result.length; k++) {
    337                 found: {
    338                     for (int n=0; n<enabled.length; n++) {
    339                         if (result[k].equals(enabled[n])) {
    340                             break found;
    341                         }
    342                     }
    343                     if (result.length != enabled.length) {
    344                         fail("Returned result does not correspond "
    345                                 + "to expected.");
    346                     }
    347                 }
    348             }
    349         }
    350     }
    351 
    352     /**
    353      * setUseClientMode(boolean mode) method testing.
    354      * getUseClientMode() method testing.
    355      */
    356     public void testSetGetUseClientMode() throws Exception {
    357         SSLEngine engine = getEngine();
    358 
    359         engine.setUseClientMode(false);
    360         assertFalse("Result differs from expected",
    361                 engine.getUseClientMode());
    362         engine.setUseClientMode(true);
    363         assertTrue("Result differs from expected",
    364                 engine.getUseClientMode());
    365 
    366         engine.beginHandshake();
    367         try {
    368             engine.setUseClientMode(false);
    369             fail("Expected IllegalArgumentException was not thrown");
    370         } catch (IllegalArgumentException e) { }
    371 
    372         engine.wrap(ByteBuffer.allocate(0), ByteBuffer.allocate(
    373                 engine.getSession().getPacketBufferSize()));
    374         try {
    375             engine.setUseClientMode(false);
    376             fail("Expected IllegalArgumentException was not thrown");
    377         } catch (IllegalArgumentException e) { }
    378      }
    379 
    380     /**
    381      * setEnableSessionCreation(boolean flag) method testing.
    382      * getEnableSessionCreation() method testing.
    383      */
    384     public void testSetGetEnableSessionCreation() throws Exception {
    385         SSLEngine engine = getEngine();
    386 
    387         engine.setEnableSessionCreation(false);
    388         assertFalse("Result differs from expected",
    389                 engine.getEnableSessionCreation());
    390         engine.setEnableSessionCreation(true);
    391         assertTrue("Result differs from expected",
    392                 engine.getEnableSessionCreation());
    393     }
    394 
    395     /**
    396      * getSession() method testing.
    397      */
    398     public void testGetSession() throws Exception {
    399         SSLEngine engine = getEngine();
    400 
    401         SSLSession session = engine.getSession();
    402         if ((session == null)
    403                 || (!session.getCipherSuite()
    404                     .endsWith("_NULL_WITH_NULL_NULL"))) {
    405             fail("Returned session is null "
    406                     + "or not TLS_NULL_WITH_NULL_NULL");
    407         }
    408     }
    409 
    410     /**
    411      * beginHandshake() method testing
    412      *
    413      */
    414     public void testBeginHandshake() throws Exception {
    415         SSLEngine engine = getEngine();
    416         assertEquals("Incorrect initial handshake status",
    417                 engine.getHandshakeStatus(),
    418                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING);
    419         try {
    420             engine.beginHandshake();
    421             fail("Expected IllegalStateException was not thrown");
    422         } catch (IllegalStateException e) { }
    423 
    424         engine = getEngine();
    425         engine.setUseClientMode(false);
    426         engine.beginHandshake();
    427         assertEquals("Incorrect initial handshake status",
    428                 engine.getHandshakeStatus(),
    429                 SSLEngineResult.HandshakeStatus.NEED_UNWRAP);
    430 
    431         engine = getEngine();
    432         engine.setUseClientMode(true);
    433         engine.beginHandshake();
    434         assertEquals("Incorrect initial handshake status",
    435                 engine.getHandshakeStatus(),
    436                 SSLEngineResult.HandshakeStatus.NEED_WRAP);
    437     }
    438 
    439     /**
    440      * closeOutbound() method testing.
    441      */
    442     public void testCloseOutbound() throws Exception {
    443         SSLEngine engine = getEngine();
    444         assertFalse(engine.isOutboundDone());
    445         engine.closeOutbound();
    446         SSLEngineResult result = engine.wrap(ByteBuffer.allocate(0),
    447                 ByteBuffer.allocate(20000));
    448         assertEquals("Incorrect status", result.getStatus(),
    449                 SSLEngineResult.Status.CLOSED);
    450         assertEquals("Incorrect status", result.getHandshakeStatus(),
    451                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING);
    452         try {
    453             // should throw SSLException "engine already closed"
    454             engine.beginHandshake();
    455             fail("Expected exception was not thrown.");
    456         } catch (SSLException e) { }
    457         assertTrue(engine.isOutboundDone());
    458     }
    459 
    460     /**
    461      * closeInbound() method testing.
    462      */
    463     public void testCloseInbound() throws Exception {
    464         SSLEngine engine = getEngine();
    465         assertFalse(engine.isInboundDone());
    466         engine.closeInbound();
    467         SSLEngineResult result = engine.wrap(ByteBuffer.allocate(0),
    468                 ByteBuffer.allocate(20000));
    469         assertEquals("Incorrect status", result.getStatus(),
    470                 SSLEngineResult.Status.CLOSED);
    471         assertEquals("Incorrect status", result.getHandshakeStatus(),
    472                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING);
    473         try {
    474             // should throw SSLException "engine already closed"
    475             engine.beginHandshake();
    476             fail("Expected exception was not thrown.");
    477         } catch (SSLException e) { }
    478         assertTrue(engine.isInboundDone());
    479     }
    480 
    481     /**
    482      * closeInbound() method testing.
    483      * Tests error processing in the case of unexpected closeInbound.
    484      */
    485     public void testCloseInbound2() throws Exception {
    486         SSLEngine client = getEngine();
    487         SSLEngine server = getEngine();
    488         initEngines(client, server);
    489 
    490         int packetBufferSize =
    491             client.getSession().getPacketBufferSize();
    492         int applicationBufferSize =
    493             server.getSession().getApplicationBufferSize();
    494 
    495         ByteBuffer buffer = ByteBuffer.allocate(packetBufferSize);
    496         ByteBuffer app_data_buffer = ByteBuffer.allocate(applicationBufferSize);
    497 
    498         client.setUseClientMode(true);
    499         server.setUseClientMode(false);
    500 
    501         doHandshake(client, server);
    502 
    503         if (doLog) {
    504             System.out.println("\nError processing test:");
    505         }
    506         try {
    507             // should cause SSLException, prepare fatal alert "internal error",
    508             // and set HandshakeStatus to NEED_WRAP
    509             // (to send alert to another side)
    510             server.closeInbound();
    511             fail("Expected exception was not thrown.");
    512         } catch (Exception e) {
    513             if (doLog) {
    514                 System.out.println("Server threw exception: "
    515                         + e.getMessage());
    516             }
    517             // e.printStackTrace();
    518             // should do nothing
    519             server.closeInbound();
    520             assertEquals("Unexpected status:",
    521                     SSLEngineResult.HandshakeStatus.NEED_WRAP,
    522                     server.getHandshakeStatus());
    523 
    524             if (doLog) {
    525                 System.out.println("Wrapping of the alert message");
    526             }
    527             SSLEngineResult result = null;
    528             print(result = server.wrap(ByteBuffer.allocate(0), buffer));
    529             assertEquals("Unexpected status of operation:",
    530                     SSLEngineResult.Status.CLOSED,
    531                     result.getStatus());
    532             assertEquals("Unexpected status of operation:",
    533                     SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    534                     result.getHandshakeStatus());
    535             assertEquals(
    536                 "The length of the consumed data differs from expected",
    537                 0, result.bytesConsumed());
    538             assertTrue(
    539                 "The length of the produced data differs from expected",
    540                 result.bytesProduced() > 0);
    541             // tune buffer to be read
    542             buffer.flip();
    543             try {
    544                 // should rethrow the SSLException "internal error"
    545                 print(client.unwrap(buffer, app_data_buffer));
    546                 fail("Expected exception was not thrown.");
    547             } catch (Exception ex) {
    548                 if (doLog) {
    549                     System.out.println("Client rethrew received alert: "
    550                             + ex.getMessage());
    551                 }
    552                 // NOT_HANDSHAKING..
    553                 assertEquals("Unexpected status of operation:",
    554                         SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    555                         client.getHandshakeStatus());
    556                 client.closeOutbound();
    557                 // NEED_WRAP.. should it be so? it contradicts to the TLS spec:
    558                 // "Upon transmission or receipt of an fatal alert message, both
    559                 // parties immediately close the connection. Servers and clients
    560                 // are required to forget any session-identifiers, keys, and
    561                 // secrets associated with a failed connection."
    562                 // So in this case we expect NOT_HANDSHAKING
    563                 assertEquals("Unexpected status of operation:",
    564                         SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    565                         client.getHandshakeStatus());
    566                 assertTrue("Outbound should be closed.",
    567                         client.isOutboundDone());
    568                 assertTrue("Inbound should be closed.",
    569                         client.isInboundDone());
    570             }
    571         }
    572     }
    573 
    574     /**
    575      * closeInbound() method testing.
    576      * Tests error processing
    577      */
    578     public void testErrorProcessing() throws Exception {
    579         SSLEngine client = getEngine();
    580         SSLEngine server = getEngine();
    581         initEngines(client, server);
    582 
    583         int packetBufferSize =
    584             client.getSession().getPacketBufferSize();
    585         int applicationBufferSize =
    586             server.getSession().getApplicationBufferSize();
    587 
    588         ByteBuffer buffer = ByteBuffer.allocate(packetBufferSize);
    589         ByteBuffer app_data_buffer = ByteBuffer.allocate(applicationBufferSize);
    590 
    591         client.setUseClientMode(true);
    592         server.setUseClientMode(false);
    593 
    594         doHandshake(client, server);
    595 
    596         if (doLog) {
    597             System.out.println("\nError processing test:");
    598         }
    599         try {
    600             print(server.unwrap(ByteBuffer.allocate(40), app_data_buffer));
    601             fail("Expected exception was not thrown.");
    602         } catch (Exception e) {
    603             if (doLog) {
    604                 System.out.println("\nServer threw exception: "
    605                         +e.getMessage());
    606             }
    607             assertEquals("Unexpected status of operation:",
    608                     SSLEngineResult.HandshakeStatus.NEED_WRAP,
    609                     server.getHandshakeStatus());
    610 
    611             SSLEngineResult result = null;
    612             assertFalse("Outbound should not be closed.",
    613                     server.isOutboundDone());
    614             assertTrue("Inbound should be closed.",
    615                     server.isInboundDone());
    616 
    617             if (doLog) {
    618                 System.out.println(
    619                         "\nServer tries to unwrap the data after error");
    620             }
    621             print(result =
    622                     server.unwrap(ByteBuffer.allocate(40), app_data_buffer));
    623             assertEquals("Unexpected status of operation:",
    624                     SSLEngineResult.Status.CLOSED,
    625                     result.getStatus());
    626             assertEquals("Unexpected status of operation:",
    627                     SSLEngineResult.HandshakeStatus.NEED_WRAP,
    628                     result.getHandshakeStatus());
    629             assertEquals(
    630                 "The length of the consumed data differs from expected",
    631                 0, result.bytesConsumed());
    632             assertEquals(
    633                 "The length of the produced data differs from expected",
    634                 0, result.bytesProduced());
    635 
    636             if (doLog) {
    637                 System.out.println("\nServer wraps the fatal alert");
    638             }
    639             print(result = server.wrap(ByteBuffer.allocate(0), buffer));
    640             assertEquals("Unexpected status of operation:",
    641                     SSLEngineResult.Status.CLOSED,
    642                     result.getStatus());
    643             assertEquals("Unexpected status of operation:",
    644                     SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    645                     result.getHandshakeStatus());
    646             assertEquals(
    647                 "The length of the consumed data differs from expected",
    648                 0, result.bytesConsumed());
    649             assertTrue(
    650                 "The length of the produced data differs from expected",
    651                 result.bytesProduced() > 0);
    652 
    653             assertTrue("Outbound should be closed.",
    654                     server.isOutboundDone());
    655             assertTrue("Inbound should be closed.",
    656                     server.isInboundDone());
    657 
    658             buffer.flip();
    659             try {
    660                 if (doLog) {
    661                     System.out.println("\nClient unwraps the fatal alert");
    662                 }
    663                 print(client.unwrap(buffer, app_data_buffer));
    664                 fail("Expected exception was not thrown.");
    665             } catch (Exception ex) {
    666                 if (doLog) {
    667                     System.out.println("\nClient rethrew the exception: "
    668                             + ex.getMessage());
    669                 }
    670                 // NOT_HANDSHAKING..
    671                 assertEquals("Unexpected status of operation:",
    672                         SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    673                         client.getHandshakeStatus());
    674                 client.closeOutbound();
    675                 // NEED_WRAP.. should it be so? it contradicts to the TLS spec:
    676                 // "Upon transmission or receipt of an fatal alert message, both
    677                 // parties immediately close the connection. Servers and clients
    678                 // are required to forget any session-identifiers, keys, and
    679                 // secrets associated with a failed connection."
    680                 // So in this case we expect NOT_HANDSHAKING
    681                 assertEquals("Unexpected status of operation:",
    682                         SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    683                         client.getHandshakeStatus());
    684                 assertTrue("Outbound should be closed.",
    685                         client.isOutboundDone());
    686                 assertTrue("Inbound should be closed.",
    687                         client.isInboundDone());
    688             }
    689         }
    690     }
    691 
    692 
    693     // --------------------------------------------------------------------
    694     // ------------------------ Staff methods -----------------------------
    695     // --------------------------------------------------------------------
    696 
    697     /*
    698      * Performs the handshake over the specified engines
    699      */
    700     private void doHandshake(SSLEngine client,
    701             SSLEngine server) throws Exception {
    702         if (doLog) {
    703             System.out.println("\n--- doHandshake:");
    704             System.out.println("Server: "+server.getSession().getClass());
    705             System.out.println("Client: "+client.getSession().getClass());
    706         }
    707 
    708         client.beginHandshake();
    709         server.beginHandshake();
    710 
    711         doHandshakeImpl(client, server);
    712     }
    713 
    714     /*
    715      * Performs the handshake over the specified engines.
    716      * Note that method passes app data between the engines during
    717      * the handshake process.
    718      */
    719     private void doHandshakeImpl(SSLEngine client,
    720             SSLEngine server) throws Exception {
    721         if (doLog) {
    722             System.out.println("\n--- doHandshakeImpl:");
    723             System.out.println("Client's hsh status: "
    724                     + client.getHandshakeStatus());
    725             System.out.println("Client's session: "+client.getSession());
    726             System.out.println("Server's hsh status: "
    727                     + server.getHandshakeStatus());
    728             System.out.println("Server's session: "+server.getSession());
    729         }
    730 
    731         int packetBufferSize =
    732             client.getSession().getPacketBufferSize();
    733         int applicationBufferSize =
    734             server.getSession().getApplicationBufferSize();
    735 
    736         // buffer will contain handshake messages
    737         ByteBuffer clients_buffer = ByteBuffer.allocate(packetBufferSize+1000);
    738         ByteBuffer servers_buffer = ByteBuffer.allocate(packetBufferSize+1000);
    739         // buffers will contain application data messages
    740         ByteBuffer app_data = ByteBuffer.allocate(packetBufferSize);
    741         ByteBuffer app_data_plain = ByteBuffer.allocate(applicationBufferSize);
    742 
    743         SSLEngine[] engines = new SSLEngine[] {client, server};
    744         ByteBuffer[] buffers =
    745             new ByteBuffer[] {clients_buffer, servers_buffer};
    746 
    747         // choose which peer will start handshake negotiation
    748         // (initial handshake is initiated by client, but rehandshake
    749         // can be initiated by any peer)
    750         int step = (client.getHandshakeStatus()
    751                 != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) ? 0 : 1;
    752 
    753         SSLEngine current_engine = engines[step];
    754         ByteBuffer buffer;
    755         SSLEngineResult result = null;
    756         SSLEngineResult.HandshakeStatus status;
    757 
    758         while ((client.getHandshakeStatus()
    759                     != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)
    760                 || (server.getHandshakeStatus()
    761                     != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) {
    762             if (doLog) {
    763                 System.out.print("\n"
    764                         + ((current_engine == client) ? "CLIENT " : "SERVER "));
    765             }
    766             status = current_engine.getHandshakeStatus();
    767             if (status == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
    768                 // so another peer produced
    769                 // the handshaking data which has to be unwrapped
    770                 if (doLog) {
    771                     System.out.print("(NOT_HANDSHAKING) ");
    772                 }
    773                 status = SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
    774             }
    775             if (status == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
    776                 if (doLog) {
    777                     System.out.println("NEED_WRAP");
    778                 }
    779                 // will wrap handshake data into its special buffer
    780                 buffer = buffers[step];
    781                 if (buffer.remaining() == 0) {
    782                     // handshake data was fully read by another peer,
    783                     // so we need clear the buffer before reusing it
    784                     buffer.clear();
    785                 }
    786                 // wrap the next handshake message
    787                 print(result = current_engine.wrap(app_data, buffer));
    788                 // if there are no any messages to send, switch the engine
    789                 if (current_engine.getHandshakeStatus()
    790                         != SSLEngineResult.HandshakeStatus.NEED_WRAP) {
    791                     // switch the current engine
    792                     step ^= 1;
    793                     current_engine = engines[step];
    794                     // and prepare the buffer for reading
    795                     buffer.flip();
    796                 }
    797             } else if (status == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
    798                 if (doLog) {
    799                     System.out.println("NEED_UNWRAP");
    800                 }
    801 
    802                 // If there are no unread handshake messages produced by the
    803                 // current engine, try to wrap the application data and unwrap
    804                 // it by another engine. It will test app data flow during
    805                 // the rehandshake.
    806                 if (!buffers[step].hasRemaining()) {
    807                     if (doLog) {
    808                         System.out.println(
    809                                 "\nTry to WRAP the application data");
    810                     }
    811                     print(result = current_engine.wrap(
    812                                 ByteBuffer.wrap(new byte[] {0}), app_data));
    813                     // The output in app_data will be produced only if it
    814                     // is rehandshaking stage
    815                     // (i.e. initial handshake has been done)
    816                     if (result.bytesProduced() > 0) {
    817                         // if the app data message has been produced,
    818                         // unwrap it by another peer
    819                         if (doLog) {
    820                             System.out.print("\n" + ((current_engine != client)
    821                                                      ? "CLIENT " : "SERVER "));
    822                             System.out.println(
    823                                 "UNWRAPs app data sent during handshake");
    824                         }
    825                         app_data.flip();
    826                         print(result = engines[(step+1)%2].unwrap(
    827                                     app_data, app_data_plain));
    828                         app_data.clear();
    829                         app_data_plain.clear();
    830                     }
    831                 }
    832 
    833                 buffer = buffers[step^1];
    834 
    835                 // check if there is handshake data to be unwrapped
    836                 if (buffer.remaining() == 0) {
    837                     if (doLog) {
    838                         System.out.println(
    839                                 "There is no handshake data to be unwrapped.");
    840                     }
    841                     // switch the current engine
    842                     step ^= 1;
    843                     current_engine = engines[step];
    844                     if ((current_engine.getHandshakeStatus()
    845                                 == SSLEngineResult.HandshakeStatus.NEED_UNWRAP)
    846                             && (buffers[step^1].remaining() == 0)) {
    847                         System.out.println(
    848                                 "Both engines are in NEED_UNWRAP state");
    849                         fail("Both engines are in NEED_UNWRAP state");
    850                     }
    851                     continue;
    852                 }
    853 
    854                 print(result = current_engine.unwrap(buffer, app_data));
    855                 if (current_engine.getHandshakeStatus()
    856                         == SSLEngineResult.HandshakeStatus.NEED_TASK) {
    857                     if (doLog) {
    858                         System.out.println("NEED_TASK");
    859                     }
    860                     current_engine.getDelegatedTask().run();
    861                     if (doLog) {
    862                         System.out.println("status after the task: "
    863                                 +current_engine.getHandshakeStatus());
    864                     }
    865                 }
    866             } else {
    867                 fail("Unexpected HandshakeStatus: "+status);
    868             }
    869             assertEquals("Unexpected status of operation:",
    870                     SSLEngineResult.Status.OK,
    871                     result.getStatus());
    872         }
    873     }
    874 
    875     /*
    876      * Performs the session renegotiation process when one
    877      * of the peers is not allowed to create the session.
    878      */
    879     private void doNoRenegotiationTest(SSLEngine allowed,
    880             SSLEngine not_allowed, boolean is_initial) throws Exception {
    881         if (doLog) {
    882             System.out.println(
    883                     "\n--- doNoRenegotiationTest: is_initial: "+is_initial);
    884         }
    885 
    886         not_allowed.setEnableSessionCreation(false);
    887         not_allowed.getSession().invalidate();
    888 
    889         int packetBufferSize =
    890             allowed.getSession().getPacketBufferSize();
    891         int applicationBufferSize =
    892             not_allowed.getSession().getApplicationBufferSize();
    893 
    894         // buffer will contain handshake messages
    895         ByteBuffer buffer = ByteBuffer.allocate(packetBufferSize+1000);
    896         // buffers will contain application data messages
    897         ByteBuffer app_data = ByteBuffer.allocate(packetBufferSize);
    898         ByteBuffer app_data_plain = ByteBuffer.allocate(applicationBufferSize);
    899 
    900         SSLEngineResult result = null;
    901 
    902         allowed.beginHandshake();
    903         //not_allowed.beginHandshake();
    904 
    905         if (doLog) {
    906             System.out.println(
    907                 "\nAllowed peer wraps the initial session negotiation message");
    908         }
    909         // wrap the initial session negotiation message
    910         while (allowed.getHandshakeStatus().equals(
    911                     SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
    912             print(result = allowed.wrap(app_data_plain, buffer));
    913             assertTrue("Engine did not produce any data",
    914                     result.bytesProduced() > 0);
    915         }
    916         // prepare the buffer for reading
    917         buffer.flip();
    918         if (doLog) {
    919             System.out.println("\nNot allowed unwraps the message");
    920         }
    921         try {
    922             // unwrap the message. expecting whether SSLException or NEED_WRAP
    923             print(result = not_allowed.unwrap(buffer, app_data_plain));
    924         } catch (SSLException e) {
    925             if (is_initial) {
    926                 return; // ok, exception was thrown
    927             } else {
    928                 fail("Unexpected SSLException was thrown "+e);
    929             }
    930         }
    931         // if it is not an initial handshake phase it is posible
    932         // SSLException to be thrown.
    933         try {
    934             while (!not_allowed.getHandshakeStatus().equals(
    935                         SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
    936                 assertTrue("Engine did not consume any data",
    937                         result.bytesConsumed() > 0);
    938                 if (not_allowed.getHandshakeStatus().equals(
    939                             SSLEngineResult.HandshakeStatus.NEED_TASK)) {
    940                     not_allowed.getDelegatedTask().run();
    941                     if (doLog) {
    942                         System.out.println("Status after the task: "
    943                                 + not_allowed.getHandshakeStatus());
    944                     }
    945                     continue;
    946                 } else if (not_allowed.getHandshakeStatus().equals(
    947                             SSLEngineResult.HandshakeStatus.NEED_UNWRAP)) {
    948                     print(result = not_allowed.unwrap(buffer, app_data_plain));
    949                 } else {
    950                     fail("Unexpected status of operation: "
    951                             + not_allowed.getHandshakeStatus());
    952                 }
    953             }
    954             // prepare for writting
    955             buffer.clear();
    956             if (doLog) {
    957                 System.out.println(
    958                     "\nWrapping the message. Expecting no_renegotiation alert");
    959             }
    960             // wrapping the message. expecting no_renegotiation alert
    961             print(result = not_allowed.wrap(app_data_plain, buffer));
    962         } catch (SSLException e) {
    963             if (!is_initial) {
    964                 fail("Unexpected SSLException was thrown."+e.getMessage());
    965             }
    966             if (doLog) {
    967                 System.out.println("Throwed exception during the unwrapping "
    968                         + "of handshake initiation message:");
    969                 e.printStackTrace();
    970                 System.out.println("Handshake Status: "
    971                         + not_allowed.getHandshakeStatus());
    972             }
    973             if (not_allowed.getHandshakeStatus().equals(
    974                         SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
    975                 // needs to wrap fatal alert message
    976                 if (doLog) {
    977                     System.out.println(
    978                             "\nnot_allowed wraps fatal alert message");
    979                 }
    980                 // prepare for writting
    981                 buffer.clear();
    982                 print(result = not_allowed.wrap(app_data_plain, buffer));
    983             }
    984         }
    985         // check whether alert message has been sent
    986         assertTrue("Engine did not produce any data",
    987                 result.bytesProduced() > 0);
    988         // check whether not_allowed engine stoped handshake operation
    989         assertEquals("Unexpected status of operation: not_allowed "
    990                 + "to session creation peer did not stop its handshake process",
    991                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
    992                 not_allowed.getHandshakeStatus());
    993         // prepare for reading
    994         buffer.flip();
    995         try {
    996             print(result = allowed.unwrap(buffer, app_data_plain));
    997             assertTrue("Engine did not consume any data",
    998                     result.bytesConsumed() > 0);
    999             assertEquals("Responce from the peer not allowed to create "
   1000                     + "the session did not cause the stopping of "
   1001                     + "the session negotiation process",
   1002                     SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1003                     result.getHandshakeStatus());
   1004         } catch (SSLException e) {
   1005             if (!is_initial) {
   1006                 fail("Unexpected SSLException was thrown."+e.getMessage());
   1007             }
   1008             if (doLog) {
   1009                 System.out.println("Throwed exception during the unwrapping "
   1010                         + "of responce from allowed peer:");
   1011                 e.printStackTrace();
   1012                 System.out.println("Handshake Status: "
   1013                         + not_allowed.getHandshakeStatus());
   1014             }
   1015         }
   1016     }
   1017 
   1018     /*
   1019      * Tests the data exchange process between two engines
   1020      */
   1021     private void doDataExchange(SSLEngine client,
   1022                                 SSLEngine server) throws Exception {
   1023         if (doLog) {
   1024             System.out.println("\n--- doDataExchange:");
   1025         }
   1026         ByteBuffer co = ByteBuffer.allocate(
   1027                 client.getSession().getPacketBufferSize());
   1028         ByteBuffer si = ByteBuffer.allocate(
   1029                 server.getSession().getPacketBufferSize());
   1030         SSLEngineResult result;
   1031 
   1032         String data_2b_sent = "data to be sent";
   1033         ByteBuffer data = ByteBuffer.wrap(data_2b_sent.getBytes());
   1034 
   1035         if (doLog) {
   1036             System.out.println("\nTry to wrap the data into small buffer");
   1037         }
   1038         print(result = client.wrap(data, ByteBuffer.allocate(35)));
   1039         assertEquals("Unexpected status of operation:",
   1040                 SSLEngineResult.Status.BUFFER_OVERFLOW,
   1041                 result.getStatus());
   1042 
   1043         if (doLog) {
   1044             System.out.println("\nWrapping the data of length "
   1045                     + data.remaining());
   1046         }
   1047         print(result = client.wrap(data, co));
   1048         assertEquals("Unexpected status of operation:",
   1049                 SSLEngineResult.Status.OK,
   1050                 result.getStatus());
   1051 
   1052         // tune the buffer to read from it
   1053         co.limit(co.position());
   1054         co.rewind();
   1055 
   1056         if (doLog) {
   1057             System.out.println("\nTry to unwrap the data into small buffer");
   1058         }
   1059         print(result = server.unwrap(co, ByteBuffer.allocate(0)));
   1060         assertEquals("Unexpected status of operation:",
   1061                 SSLEngineResult.Status.BUFFER_OVERFLOW,
   1062                 result.getStatus());
   1063         if (doLog) {
   1064             System.out.println("\nUnwrapping the data into buffer");
   1065         }
   1066         print(result = server.unwrap(co, si));
   1067         assertEquals("Unexpected status of operation:",
   1068                 SSLEngineResult.Status.OK,
   1069                 result.getStatus());
   1070         assertEquals(
   1071             "The length of the received data differs from expected",
   1072             "data to be sent".length(), result.bytesProduced());
   1073 
   1074         // take the data from the buffer
   1075         byte[] resulting_data = new byte[result.bytesProduced()];
   1076         si.rewind();
   1077         si.get(resulting_data);
   1078         si.clear();
   1079         assertTrue(Arrays.equals(data_2b_sent.getBytes(), resulting_data));
   1080 
   1081         co.clear();
   1082         for (int i=1; i<10; i++) {
   1083             byte[] buff = new byte[i];
   1084             data = ByteBuffer.wrap(buff);
   1085             if (doLog) {
   1086                 System.out.println("\nWrap the data");
   1087             }
   1088             print(result = client.wrap(data, co));
   1089             assertEquals("Unexpected status of operation:",
   1090                     SSLEngineResult.Status.OK,
   1091                     result.getStatus());
   1092             if (doLog) {
   1093                 System.out.println("\nUnwrap the data");
   1094             }
   1095             co.rewind();
   1096             print(result = server.unwrap(co, si));
   1097             assertEquals("Unexpected status of operation:",
   1098                     SSLEngineResult.Status.OK,
   1099                     result.getStatus());
   1100             assertEquals(
   1101                 "The length of the received data differs from expected",
   1102                 i, result.bytesProduced());
   1103             resulting_data = new byte[i];
   1104             si.rewind();
   1105             si.get(resulting_data);
   1106             si.clear();
   1107             assertTrue(Arrays.equals(buff, resulting_data));
   1108             co.clear();
   1109             si.clear();
   1110         }
   1111     }
   1112 
   1113     /*
   1114      * Performs the closure process over the two communicationg engines.
   1115      * The handshake process should be performed before the call of this
   1116      * method.
   1117      */
   1118     private void doClose(SSLEngine client, SSLEngine server) throws Exception {
   1119         if (doLog) {
   1120             System.out.println("\n--- doClose: ");
   1121         }
   1122         ByteBuffer buffer = ByteBuffer.allocate(
   1123                 // +100 because we put the data into the buffer multiple times
   1124                 server.getSession().getPacketBufferSize()+100);
   1125         ByteBuffer app_data_buffer = ByteBuffer.allocate(
   1126                 client.getSession().getApplicationBufferSize());
   1127         SSLEngineResult result;
   1128         // first: send 0 just for fun
   1129         if (doLog) {
   1130             System.out.println("\nServer sends pending outboud data:");
   1131         }
   1132         print(result = server.wrap(ByteBuffer.wrap(new byte[] {0}), buffer));
   1133         assertEquals("Unexpected status of operation:",
   1134                 SSLEngineResult.Status.OK,
   1135                 result.getStatus());
   1136         assertEquals("Unexpected status of operation:",
   1137                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1138                 result.getHandshakeStatus());
   1139         // second: initiate a close
   1140         if (doLog) {
   1141             System.out.println("\nServer initiates a closure:");
   1142         }
   1143         server.closeOutbound();
   1144         // should do nothing:
   1145         server.closeOutbound();
   1146 
   1147         assertEquals("Unexpected status of operation:",
   1148                 SSLEngineResult.HandshakeStatus.NEED_WRAP,
   1149                 server.getHandshakeStatus());
   1150 
   1151         // will cause SSLException because closure alert was not received yet:
   1152         // server.closeInbound();
   1153 
   1154         // wrap closure alert (previosly sent 0 should not be lost)
   1155         print(result = server.wrap(ByteBuffer.allocate(0), buffer));
   1156         assertEquals("Unexpected status of operation:",
   1157                 SSLEngineResult.Status.CLOSED,
   1158                 result.getStatus());
   1159         assertEquals("Unexpected status of operation:",
   1160                 SSLEngineResult.HandshakeStatus.NEED_UNWRAP,
   1161                 result.getHandshakeStatus());
   1162 
   1163         if (doLog) {
   1164             System.out.println("\nServer sends pending outboud data again:");
   1165         }
   1166         // will do nothing because closure alert has been sent
   1167         // and outbound has been closed
   1168         print(result = server.wrap(ByteBuffer.wrap(new byte[] {0}), buffer));
   1169         assertEquals("Unexpected status of operation:",
   1170                 SSLEngineResult.Status.CLOSED,
   1171                 result.getStatus());
   1172         assertEquals("Unexpected status of operation:",
   1173                 SSLEngineResult.HandshakeStatus.NEED_UNWRAP,
   1174                 result.getHandshakeStatus());
   1175         assertEquals(
   1176             "The length of the consumed data differs from expected",
   1177             0, result.bytesConsumed());
   1178         assertEquals(
   1179             "The length of the produced data differs from expected",
   1180             0, result.bytesProduced());
   1181 
   1182         // prepare the buffer for reading
   1183         buffer.flip();
   1184 
   1185         if (doLog) {
   1186             System.out.println(
   1187                     "\nClient receives pending servers' outbound data");
   1188         }
   1189         print(result = client.unwrap(buffer, app_data_buffer));
   1190         assertEquals("Unexpected status of operation:",
   1191                 SSLEngineResult.Status.OK,
   1192                 result.getStatus());
   1193         assertEquals("Unexpected status of operation:",
   1194                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1195                 result.getHandshakeStatus());
   1196         assertEquals(
   1197             "The length of the produced data differs from expected",
   1198             1, result.bytesProduced());
   1199 
   1200         app_data_buffer.clear();
   1201 
   1202         if (doLog) {
   1203             System.out.println("\nClient receives close notify");
   1204         }
   1205         print(result = client.unwrap(buffer, app_data_buffer));
   1206         assertEquals("Unexpected status of operation:",
   1207                 SSLEngineResult.Status.CLOSED,
   1208                 result.getStatus());
   1209         assertEquals("Unexpected status of operation:",
   1210                 SSLEngineResult.HandshakeStatus.NEED_WRAP,
   1211                 result.getHandshakeStatus());
   1212         assertTrue(
   1213             "The length of the consumed data differs from expected",
   1214             result.bytesConsumed() > 0);
   1215         assertEquals(
   1216             "The length of the received data differs from expected",
   1217             0, result.bytesProduced());
   1218 
   1219         // prepare the buffer for writing
   1220         app_data_buffer.clear();
   1221 
   1222         // it's needless, but should work (don't cause exceptions):
   1223         client.closeInbound();
   1224         client.closeOutbound();
   1225 
   1226         if (doLog) {
   1227             System.out.println("\nClient tries to read data again");
   1228         }
   1229         // CLOSED, 0 consumed, 0 produced
   1230         print(result = client.unwrap(buffer, app_data_buffer));
   1231         assertEquals("Unexpected status of operation:",
   1232                 SSLEngineResult.Status.CLOSED,
   1233                 result.getStatus());
   1234         assertEquals("Unexpected status of operation:",
   1235                 SSLEngineResult.HandshakeStatus.NEED_WRAP,
   1236                 result.getHandshakeStatus());
   1237         assertEquals(
   1238             "The length of the consumed data differs from expected",
   1239             0, result.bytesConsumed());
   1240         assertEquals(
   1241             "The length of the received data differs from expected",
   1242             0, result.bytesProduced());
   1243 
   1244         // prepare the buffer for writing
   1245         buffer.clear();
   1246 
   1247         if (doLog) {
   1248             System.out.println("\nClient sends responding close notify");
   1249         }
   1250         print(result = client.wrap(ByteBuffer.wrap(new byte[] {0}), buffer));
   1251         assertEquals("Unexpected status of operation:",
   1252                 SSLEngineResult.Status.CLOSED,
   1253                 result.getStatus());
   1254         assertEquals("Unexpected status of operation:",
   1255                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1256                 result.getHandshakeStatus());
   1257         assertEquals(
   1258             "The length of the consumed data differs from expected",
   1259             0, result.bytesConsumed());
   1260         assertTrue(
   1261             "The length of the produced data differs from expected",
   1262             result.bytesProduced() > 0);
   1263         if (doLog) {
   1264             System.out.println(
   1265                     "\nClient tries to send data after closure alert");
   1266         }
   1267         // this data will not be sent (should do nothing - 0 cons, 0 prod)
   1268         print(result = client.wrap(ByteBuffer.wrap(new byte[] {0}), buffer));
   1269         assertEquals("Unexpected status of operation:",
   1270                 SSLEngineResult.Status.CLOSED,
   1271                 result.getStatus());
   1272         assertEquals("Unexpected status of operation:",
   1273                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1274                 result.getHandshakeStatus());
   1275         assertEquals(
   1276             "The length of the consumed data differs from expected",
   1277             0, result.bytesConsumed());
   1278         assertEquals(
   1279             "The length of the produced data differs from expected",
   1280             0, result.bytesProduced());
   1281 
   1282         // prepare the buffers for reading
   1283         app_data_buffer.clear();
   1284         buffer.flip();
   1285 
   1286         if (doLog) {
   1287             System.out.println("\nServer receives close notify");
   1288         }
   1289         print(result = server.unwrap(buffer, app_data_buffer));
   1290         assertEquals("Unexpected status of operation:",
   1291                 SSLEngineResult.Status.CLOSED,
   1292                 result.getStatus());
   1293         assertEquals("Unexpected status of operation:",
   1294                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1295                 result.getHandshakeStatus());
   1296         assertTrue(
   1297             "The length of the consumed data differs from expected",
   1298             result.bytesConsumed() > 0);
   1299         assertEquals(
   1300             "The length of the produced data differs from expected",
   1301             0, result.bytesProduced());
   1302 
   1303         if (doLog) {
   1304             System.out.println("\nServer tries to read after closure");
   1305         }
   1306         // will be ignored
   1307         print(result = server.unwrap(buffer, app_data_buffer));
   1308         assertEquals("Unexpected status of operation:",
   1309                 SSLEngineResult.Status.CLOSED,
   1310                 result.getStatus());
   1311         assertEquals("Unexpected status of operation:",
   1312                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1313                 result.getHandshakeStatus());
   1314         assertEquals(
   1315             "The length of the consumed data differs from expected",
   1316             0, result.bytesConsumed());
   1317         assertEquals(
   1318             "The length of the produced data differs from expected",
   1319             0, result.bytesProduced());
   1320 
   1321         // it's needless, but should work:
   1322         client.closeInbound();
   1323         // will be ignored
   1324 
   1325         if (doLog) {
   1326             System.out.println("\nServer tries to write after closure");
   1327         }
   1328         buffer.clear();
   1329         print(result = server.wrap(ByteBuffer.allocate(0), buffer));
   1330         assertEquals("Unexpected status of operation:",
   1331                 SSLEngineResult.Status.CLOSED,
   1332                 result.getStatus());
   1333         assertEquals("Unexpected status of operation:",
   1334                 SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
   1335                 result.getHandshakeStatus());
   1336         assertEquals(
   1337             "The length of the consumed data differs from expected",
   1338             0, result.bytesConsumed());
   1339         assertEquals(
   1340             "The length of the produced data differs from expected",
   1341             0, result.bytesProduced());
   1342     }
   1343 
   1344     private static void print(SSLEngineResult result) {
   1345         if (doLog) {
   1346             System.out.println("result:\n"+result);
   1347         }
   1348     }
   1349 
   1350     /**
   1351      * Returns the engine to be tested.
   1352      */
   1353     private SSLEngine getEngine() throws Exception {
   1354         return JSSETestData.getContext().createSSLEngine("localhost", 2345);
   1355     }
   1356 
   1357     /**
   1358      * Initializes the engines.
   1359      */
   1360     private void initEngines(SSLEngine client, SSLEngine server) {
   1361         String prefix = "TLS_";
   1362 
   1363         client.setEnabledProtocols(new String[] {"TLSv1"});
   1364         server.setEnabledProtocols(new String[] {"TLSv1"});
   1365         client.setEnabledCipherSuites(
   1366                 new String[] {prefix+cipher_suites[0]});
   1367         server.setEnabledCipherSuites(
   1368                 new String[] {prefix+cipher_suites[0]});
   1369 
   1370         client.setUseClientMode(true);
   1371         server.setUseClientMode(false);
   1372     }
   1373 
   1374     public static Test suite() {
   1375         return new TestSuite(SSLEngineImplTest.class);
   1376     }
   1377 
   1378 }
   1379