jdk/test/javax/net/ssl/DTLS/DTLSSequenceNumberTest.java
changeset 31057 babdeee3c007
child 40949 be7a612613ae
equal deleted inserted replaced
31008:5b500c93ce48 31057:babdeee3c007
       
     1 /*
       
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 8043758
       
    27  * @summary Testing DTLS records sequence number property support in application
       
    28  *          data exchange.
       
    29  * @key randomness
       
    30  * @library /sun/security/krb5/auto /lib/testlibrary /javax/net/ssl/TLSCommon
       
    31  * @run main/othervm -Dtest.security.protocol=DTLS
       
    32  *      -Dtest.mode=norm DTLSSequenceNumberTest
       
    33  * @run main/othervm -Dtest.security.protocol=DTLS
       
    34  *      -Dtest.mode=norm_sni DTLSSequenceNumberTest
       
    35  * @run main/othervm -Dtest.security.protocol=DTLS
       
    36  *      -Dtest.mode=krb DTLSSequenceNumberTest
       
    37  */
       
    38 
       
    39 import java.nio.ByteBuffer;
       
    40 import java.util.TreeMap;
       
    41 import javax.net.ssl.SSLContext;
       
    42 import javax.net.ssl.SSLEngine;
       
    43 import javax.net.ssl.SSLEngineResult;
       
    44 import javax.net.ssl.SSLException;
       
    45 import java.util.Random;
       
    46 import jdk.testlibrary.RandomFactory;
       
    47 
       
    48 /**
       
    49  * Testing DTLS records sequence number property support in application data
       
    50  * exchange.
       
    51  */
       
    52 public class DTLSSequenceNumberTest extends SSLEngineTestCase {
       
    53 
       
    54     private final String BIG_MESSAGE = "Very very big message. One two three"
       
    55             + " four five six seven eight nine ten eleven twelve thirteen"
       
    56             + " fourteen fifteen sixteen seventeen eighteen nineteen twenty.";
       
    57     private final byte[] BIG_MESSAGE_BYTES = BIG_MESSAGE.getBytes();
       
    58     private final int PIECES_NUMBER = 15;
       
    59 
       
    60     public static void main(String[] args) {
       
    61         DTLSSequenceNumberTest test = new DTLSSequenceNumberTest();
       
    62         setUpAndStartKDCIfNeeded();
       
    63         test.runTests();
       
    64     }
       
    65 
       
    66     @Override
       
    67     protected void testOneCipher(String cipher) throws SSLException {
       
    68         SSLContext context = getContext();
       
    69         int maxPacketSize = getMaxPacketSize();
       
    70         boolean useSNI = !TEST_MODE.equals("norm");
       
    71         SSLEngine clientEngine = getClientSSLEngine(context, useSNI);
       
    72         SSLEngine serverEngine = getServerSSLEngine(context, useSNI);
       
    73         clientEngine.setEnabledCipherSuites(new String[]{cipher});
       
    74         serverEngine.setEnabledCipherSuites(new String[]{cipher});
       
    75         serverEngine.setNeedClientAuth(!cipher.contains("anon"));
       
    76         doHandshake(clientEngine, serverEngine, maxPacketSize,
       
    77                 HandshakeMode.INITIAL_HANDSHAKE);
       
    78         checkSeqNumPropertyWithAppDataSend(clientEngine, serverEngine);
       
    79         checkSeqNumPropertyWithAppDataSend(serverEngine, clientEngine);
       
    80     }
       
    81 
       
    82     private void checkSeqNumPropertyWithAppDataSend(SSLEngine sendEngine,
       
    83             SSLEngine recvEngine) throws SSLException {
       
    84         String sender, reciever;
       
    85         if (sendEngine.getUseClientMode() && !recvEngine.getUseClientMode()) {
       
    86             sender = "Client";
       
    87             reciever = "Server";
       
    88         } else if (recvEngine.getUseClientMode() && !sendEngine.getUseClientMode()) {
       
    89             sender = "Server";
       
    90             reciever = "Client";
       
    91         } else {
       
    92             throw new Error("Both engines are in the same mode");
       
    93         }
       
    94         System.out.println("================================================="
       
    95                 + "===========");
       
    96         System.out.println("Checking DTLS sequence number support"
       
    97                 + " by sending data from " + sender + " to " + reciever);
       
    98         ByteBuffer[] sentMessages = new ByteBuffer[PIECES_NUMBER];
       
    99         ByteBuffer[] netBuffers = new ByteBuffer[PIECES_NUMBER];
       
   100         TreeMap<Long, ByteBuffer> recvMap = new TreeMap<>(Long::compareUnsigned);
       
   101         int symbolsInAMessage;
       
   102         int symbolsInTheLastMessage;
       
   103         int[] recievingSequence = new int[PIECES_NUMBER];
       
   104         for (int i = 0; i < PIECES_NUMBER; i++) {
       
   105             recievingSequence[i] = i;
       
   106         }
       
   107         shuffleArray(recievingSequence);
       
   108         if (BIG_MESSAGE.length() % PIECES_NUMBER == 0) {
       
   109             symbolsInAMessage = BIG_MESSAGE.length() / PIECES_NUMBER;
       
   110             symbolsInTheLastMessage = symbolsInAMessage;
       
   111         } else {
       
   112             symbolsInAMessage = BIG_MESSAGE.length() / (PIECES_NUMBER - 1);
       
   113             symbolsInTheLastMessage = BIG_MESSAGE.length() % (PIECES_NUMBER - 1);
       
   114         }
       
   115         for (int i = 0; i < PIECES_NUMBER - 1; i++) {
       
   116             sentMessages[i] = ByteBuffer.wrap(BIG_MESSAGE_BYTES,
       
   117                     i * symbolsInAMessage, symbolsInAMessage);
       
   118         }
       
   119         sentMessages[PIECES_NUMBER - 1] = ByteBuffer.wrap(BIG_MESSAGE_BYTES,
       
   120                 (PIECES_NUMBER - 1) * symbolsInAMessage, symbolsInTheLastMessage);
       
   121         long prevSeqNum = 0L;
       
   122         //Wrapping massages in direct order
       
   123         for (int i = 0; i < PIECES_NUMBER; i++) {
       
   124             netBuffers[i] = ByteBuffer.allocate(sendEngine.getSession()
       
   125                     .getPacketBufferSize());
       
   126             SSLEngineResult[] r = new SSLEngineResult[1];
       
   127             netBuffers[i] = doWrap(sendEngine, sender, 0, sentMessages[i], r);
       
   128             long seqNum = r[0].sequenceNumber();
       
   129             if (Long.compareUnsigned(seqNum, prevSeqNum) <= 0) {
       
   130                 throw new AssertionError("Sequence number of the wrapped "
       
   131                         + "message is less or equal than that of the"
       
   132                         + " previous one! "
       
   133                         + "Was " + prevSeqNum + ", now " + seqNum + ".");
       
   134             }
       
   135             prevSeqNum = seqNum;
       
   136         }
       
   137         //Unwrapping messages in random order and trying to reconstruct order
       
   138         //from sequence number.
       
   139         for (int i = 0; i < PIECES_NUMBER; i++) {
       
   140             int recvNow = recievingSequence[i];
       
   141             SSLEngineResult[] r = new SSLEngineResult[1];
       
   142             ByteBuffer recvMassage = doUnWrap(recvEngine, reciever,
       
   143                     netBuffers[recvNow], r);
       
   144             long seqNum = r[0].sequenceNumber();
       
   145             recvMap.put(seqNum, recvMassage);
       
   146         }
       
   147         int mapSize = recvMap.size();
       
   148         if (mapSize != PIECES_NUMBER) {
       
   149             throw new AssertionError("The number of received massages "
       
   150                     + mapSize + " is not equal to the number of sent messages "
       
   151                     + PIECES_NUMBER + "!");
       
   152         }
       
   153         byte[] recvBigMsgBytes = new byte[BIG_MESSAGE_BYTES.length];
       
   154         int counter = 0;
       
   155         for (ByteBuffer msg : recvMap.values()) {
       
   156             System.arraycopy(msg.array(), 0, recvBigMsgBytes,
       
   157                     counter * symbolsInAMessage, msg.remaining());
       
   158             counter++;
       
   159         }
       
   160         String recvBigMsg = new String(recvBigMsgBytes);
       
   161         if (!recvBigMsg.equals(BIG_MESSAGE)) {
       
   162             throw new AssertionError("Received big message is not equal to"
       
   163                     + " one that was sent! Received message is: " + recvBigMsg);
       
   164         }
       
   165     }
       
   166 
       
   167     private static void shuffleArray(int[] ar) {
       
   168         final Random RNG = RandomFactory.getRandom();
       
   169         for (int i = ar.length - 1; i > 0; i--) {
       
   170             int index = RNG.nextInt(i + 1);
       
   171             int a = ar[index];
       
   172             ar[index] = ar[i];
       
   173             ar[i] = a;
       
   174         }
       
   175     }
       
   176 }