src/java.base/share/classes/sun/security/ssl/RandomCookie.java
changeset 50768 68fa3d4026ea
parent 47216 71c04702a3d5
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
     1 /*
     2  * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 
       
    27 package sun.security.ssl;
    26 package sun.security.ssl;
    28 
    27 
    29 import java.io.*;
    28 import java.io.*;
       
    29 import java.nio.ByteBuffer;
    30 import java.security.SecureRandom;
    30 import java.security.SecureRandom;
       
    31 import java.util.Arrays;
    31 
    32 
    32 /*
    33 /*
    33  * RandomCookie ... SSL hands standard format random cookies (nonces)
    34  * RandomCookie ... SSL hands standard format random cookies (nonces)
    34  * around.  These know how to encode/decode themselves on SSL streams,
    35  * around.  These know how to encode/decode themselves on SSL streams,
    35  * and can be created and printed.
    36  * and can be created and printed.
    36  *
    37  *
    37  * @author David Brownell
    38  * @author David Brownell
    38  */
    39  */
    39 final class RandomCookie {
    40 final class RandomCookie {
       
    41     final byte[] randomBytes = new byte[32];   // exactly 32 bytes
    40 
    42 
    41     byte[] random_bytes;  // exactly 32 bytes
    43     private static final byte[] hrrRandomBytes = new byte[] {
       
    44             (byte)0xCF, (byte)0x21, (byte)0xAD, (byte)0x74,
       
    45             (byte)0xE5, (byte)0x9A, (byte)0x61, (byte)0x11,
       
    46             (byte)0xBE, (byte)0x1D, (byte)0x8C, (byte)0x02,
       
    47             (byte)0x1E, (byte)0x65, (byte)0xB8, (byte)0x91,
       
    48             (byte)0xC2, (byte)0xA2, (byte)0x11, (byte)0x16,
       
    49             (byte)0x7A, (byte)0xBB, (byte)0x8C, (byte)0x5E,
       
    50             (byte)0x07, (byte)0x9E, (byte)0x09, (byte)0xE2,
       
    51             (byte)0xC8, (byte)0xA8, (byte)0x33, (byte)0x9C
       
    52         };
       
    53 
       
    54     private static final byte[] t12Protection = new byte[] {
       
    55             (byte)0x44, (byte)0x4F, (byte)0x57, (byte)0x4E,
       
    56             (byte)0x47, (byte)0x52, (byte)0x44, (byte)0x01
       
    57         };
       
    58 
       
    59     private static final byte[] t11Protection = new byte[] {
       
    60             (byte)0x44, (byte)0x4F, (byte)0x57, (byte)0x4E,
       
    61             (byte)0x47, (byte)0x52, (byte)0x44, (byte)0x00
       
    62         };
       
    63 
       
    64     static final RandomCookie hrrRandom = new RandomCookie(hrrRandomBytes);
    42 
    65 
    43     RandomCookie(SecureRandom generator) {
    66     RandomCookie(SecureRandom generator) {
    44         random_bytes = new byte[32];
    67         generator.nextBytes(randomBytes);
    45         generator.nextBytes(random_bytes);
       
    46     }
    68     }
    47 
    69 
    48     RandomCookie(HandshakeInStream m) throws IOException {
    70     // Used for server random generation with version downgrade protection.
    49         random_bytes = new byte[32];
    71     RandomCookie(HandshakeContext context) {
    50         m.read(random_bytes, 0, 32);
    72         SecureRandom generator = context.sslContext.getSecureRandom();
       
    73         generator.nextBytes(randomBytes);
       
    74 
       
    75         // TLS 1.3 has a downgrade protection mechanism embedded in the
       
    76         // server's random value.  TLS 1.3 servers which negotiate TLS 1.2
       
    77         // or below in response to a ClientHello MUST set the last eight
       
    78         // bytes of their Random value specially.
       
    79         byte[] protection = null;
       
    80         if (context.maximumActiveProtocol.useTLS13PlusSpec()) {
       
    81             if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
       
    82                 if (context.negotiatedProtocol.useTLS12PlusSpec()) {
       
    83                     protection = t12Protection;
       
    84                 } else {
       
    85                     protection = t11Protection;
       
    86                 }
       
    87             }
       
    88         } else if (context.maximumActiveProtocol.useTLS12PlusSpec()) {
       
    89             if (!context.negotiatedProtocol.useTLS12PlusSpec()) {
       
    90                 protection = t11Protection;
       
    91             }
       
    92         }
       
    93 
       
    94         if (protection != null) {
       
    95             System.arraycopy(protection, 0, randomBytes,
       
    96                     randomBytes.length - protection.length, protection.length);
       
    97         }
    51     }
    98     }
    52 
    99 
    53     void send(HandshakeOutStream out) throws IOException {
   100     RandomCookie(ByteBuffer m) throws IOException {
    54         out.write(random_bytes, 0, 32);
   101         m.get(randomBytes);
    55     }
   102     }
    56 
   103 
    57     void print(PrintStream s) {
   104     private RandomCookie(byte[] randomBytes) {
    58         s.print("random_bytes = {");
   105         System.arraycopy(randomBytes, 0, this.randomBytes, 0, 32);
    59         for (int i = 0; i < 32; i++) {
   106     }
    60             int k = random_bytes[i] & 0xFF;
   107 
    61             if (i != 0) {
   108     @Override
    62                 s.print(' ');
   109     public String toString() {
       
   110         return "random_bytes = {" + Utilities.toHexString(randomBytes) + "}";
       
   111     }
       
   112 
       
   113     boolean isHelloRetryRequest() {
       
   114         return Arrays.equals(hrrRandomBytes, randomBytes);
       
   115     }
       
   116 
       
   117     // Used for client random validation of version downgrade protection.
       
   118     boolean isVersionDowngrade(HandshakeContext context) {
       
   119         if (context.maximumActiveProtocol.useTLS13PlusSpec()) {
       
   120             if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
       
   121                 return isT12Downgrade() || isT11Downgrade();
    63             }
   122             }
    64             s.print(Utilities.hexDigits[k >>> 4]);
   123         } else if (context.maximumActiveProtocol.useTLS12PlusSpec()) {
    65             s.print(Utilities.hexDigits[k & 0xf]);
   124             if (!context.negotiatedProtocol.useTLS12PlusSpec()) {
       
   125                 return isT11Downgrade();
       
   126             }
    66         }
   127         }
    67         s.println("}");
   128 
       
   129         return false;
       
   130     }
       
   131 
       
   132     private boolean isT12Downgrade() {
       
   133         return Arrays.equals(randomBytes, 24, 32, t12Protection, 0, 8);
       
   134     }
       
   135 
       
   136     private boolean isT11Downgrade() {
       
   137         return Arrays.equals(randomBytes, 24, 32, t11Protection, 0, 8);
    68     }
   138     }
    69 }
   139 }