jdk/src/java.base/share/classes/sun/security/ssl/ProtocolVersion.java
changeset 30904 ec0224270f90
parent 30374 2abaf49910ea
child 32649 2ee9017c7597
equal deleted inserted replaced
30903:0c7d705209c6 30904:ec0224270f90
     1 /*
     1 /*
     2  * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2002, 2015, 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
    25 
    25 
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.util.*;
    28 import java.util.*;
    29 import java.security.CryptoPrimitive;
    29 import java.security.CryptoPrimitive;
       
    30 import sun.security.ssl.CipherSuite.*;
    30 
    31 
    31 /**
    32 /**
    32  * Type safe enum for an SSL/TLS protocol version. Instances are obtained
    33  * Type safe enum for an SSL/TLS protocol version. Instances are obtained
    33  * using the static factory methods or by referencing the static members
    34  * using the static factory methods or by referencing the static members
    34  * in this class. Member variables are final and can be accessed without
    35  * in this class. Member variables are final and can be accessed without
    59     final static int LIMIT_MIN_VALUE = 0x0000;
    60     final static int LIMIT_MIN_VALUE = 0x0000;
    60 
    61 
    61     // Dummy protocol version value for invalid SSLSession
    62     // Dummy protocol version value for invalid SSLSession
    62     final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
    63     final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
    63 
    64 
    64     // If enabled, send/ accept SSLv2 hello messages
    65     // If enabled, send/accept SSLv2 hello messages
    65     final static ProtocolVersion SSL20Hello = new ProtocolVersion(0x0002,
    66     final static ProtocolVersion SSL20Hello =
    66                                                                 "SSLv2Hello");
    67                                 new ProtocolVersion(0x0002, "SSLv2Hello");
    67 
    68 
    68     // SSL 3.0
    69     // SSL 3.0
    69     final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3");
    70     final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3");
    70 
    71 
    71     // TLS 1.0
    72     // TLS 1.0
    75     final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
    76     final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
    76 
    77 
    77     // TLS 1.2
    78     // TLS 1.2
    78     final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
    79     final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
    79 
    80 
       
    81     // DTLS 1.0
       
    82     // {254, 255}, the version value of DTLS 1.0.
       
    83     final static ProtocolVersion DTLS10 =
       
    84                                 new ProtocolVersion(0xFEFF, "DTLSv1.0");
       
    85 
       
    86     // No DTLS 1.1, that version number was skipped in order to harmonize
       
    87     // version numbers with TLS.
       
    88 
       
    89     // DTLS 1.2
       
    90     // {254, 253}, the version value of DTLS 1.2.
       
    91     final static ProtocolVersion DTLS12 =
       
    92                                 new ProtocolVersion(0xFEFD, "DTLSv1.2");
       
    93 
    80     private static final boolean FIPS = SunJSSE.isFIPS();
    94     private static final boolean FIPS = SunJSSE.isFIPS();
    81 
    95 
    82     // minimum version we implement (SSL 3.0)
    96     // minimum version we implement (SSL 3.0)
    83     final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
    97     final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
    84 
    98 
    85     // maximum version we implement (TLS 1.2)
    99     // maximum version we implement (TLS 1.2)
    86     final static ProtocolVersion MAX = TLS12;
   100     final static ProtocolVersion MAX = TLS12;
    87 
   101 
    88     // ProtocolVersion to use by default (TLS 1.2)
   102     // SSL/TLS ProtocolVersion to use by default (TLS 1.2)
    89     final static ProtocolVersion DEFAULT = TLS12;
   103     final static ProtocolVersion DEFAULT_TLS = TLS12;
       
   104 
       
   105     // DTLS ProtocolVersion to use by default (TLS 1.2)
       
   106     final static ProtocolVersion DEFAULT_DTLS = DTLS12;
    90 
   107 
    91     // Default version for hello messages (SSLv2Hello)
   108     // Default version for hello messages (SSLv2Hello)
    92     final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
   109     final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
    93 
   110 
    94     // Available protocols
   111     // Available protocols
   106     // name used in JSSE (e.g. TLSv1 for TLS 1.0)
   123     // name used in JSSE (e.g. TLSv1 for TLS 1.0)
   107     final String name;
   124     final String name;
   108 
   125 
   109     // Initialize the available protocols.
   126     // Initialize the available protocols.
   110     static {
   127     static {
   111         Set<ProtocolVersion> protocols = new HashSet<>(5);
   128         Set<ProtocolVersion> protocols = new HashSet<>(7);
   112 
   129 
   113         ProtocolVersion[] pvs = new ProtocolVersion[] {
   130         ProtocolVersion[] pvs = new ProtocolVersion[] {
   114                 SSL20Hello, SSL30, TLS10, TLS11, TLS12};
   131                 SSL20Hello, SSL30, TLS10, TLS11, TLS12, DTLS10, DTLS12};
   115         EnumSet<CryptoPrimitive> cryptoPrimitives =
   132         EnumSet<CryptoPrimitive> cryptoPrimitives =
   116             EnumSet.<CryptoPrimitive>of(CryptoPrimitive.KEY_AGREEMENT);
   133             EnumSet.<CryptoPrimitive>of(CryptoPrimitive.KEY_AGREEMENT);
   117         for (ProtocolVersion p : pvs) {
   134         for (ProtocolVersion p : pvs) {
   118             if (SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits(
   135             if (SSLAlgorithmConstraints.DEFAULT_SSL_ONLY.permits(
   119                     cryptoPrimitives, p.name, null)) {
   136                     cryptoPrimitives, p.name, null)) {
   143             return TLS11;
   160             return TLS11;
   144         } else if (v == TLS12.v) {
   161         } else if (v == TLS12.v) {
   145             return TLS12;
   162             return TLS12;
   146         } else if (v == SSL20Hello.v) {
   163         } else if (v == SSL20Hello.v) {
   147             return SSL20Hello;
   164             return SSL20Hello;
       
   165         } else if (v == DTLS10.v) {
       
   166             return DTLS10;
       
   167         } else if (v == DTLS12.v) {
       
   168             return DTLS12;
   148         } else {
   169         } else {
   149             int major = (v >>> 8) & 0xFF;
   170             int major = (v >>> 8) & 0xFF;
   150             int minor = v & 0xFF;
   171             int minor = v & 0xFF;
   151             return new ProtocolVersion(v, "Unknown-" + major + "." + minor);
   172             return new ProtocolVersion(v, "Unknown-" + major + "." + minor);
   152         }
   173         }
   170         if (name == null) {
   191         if (name == null) {
   171             throw new IllegalArgumentException("Protocol cannot be null");
   192             throw new IllegalArgumentException("Protocol cannot be null");
   172         }
   193         }
   173 
   194 
   174         if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
   195         if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
   175             throw new IllegalArgumentException
   196             throw new IllegalArgumentException(
   176                 ("Only TLS 1.0 or later allowed in FIPS mode");
   197                     "Only TLS 1.0 or later allowed in FIPS mode");
   177         }
   198         }
   178 
   199 
   179         if (name.equals(SSL30.name)) {
   200         if (name.equals(SSL30.name)) {
   180             return SSL30;
   201             return SSL30;
   181         } else if (name.equals(TLS10.name)) {
   202         } else if (name.equals(TLS10.name)) {
   184             return TLS11;
   205             return TLS11;
   185         } else if (name.equals(TLS12.name)) {
   206         } else if (name.equals(TLS12.name)) {
   186             return TLS12;
   207             return TLS12;
   187         } else if (name.equals(SSL20Hello.name)) {
   208         } else if (name.equals(SSL20Hello.name)) {
   188             return SSL20Hello;
   209             return SSL20Hello;
       
   210         } else if (name.equals(DTLS10.name)) {
       
   211             return DTLS10;
       
   212         } else if (name.equals(DTLS12.name)) {
       
   213             return DTLS12;
   189         } else {
   214         } else {
   190             throw new IllegalArgumentException(name);
   215             throw new IllegalArgumentException(name);
   191         }
   216         }
   192     }
   217     }
   193 
   218 
   199     /**
   224     /**
   200      * Compares this object with the specified object for order.
   225      * Compares this object with the specified object for order.
   201      */
   226      */
   202     @Override
   227     @Override
   203     public int compareTo(ProtocolVersion protocolVersion) {
   228     public int compareTo(ProtocolVersion protocolVersion) {
   204         return this.v - protocolVersion.v;
   229         if (maybeDTLSProtocol()) {
       
   230             if (!protocolVersion.maybeDTLSProtocol()) {
       
   231                 throw new IllegalArgumentException("Not DTLS protocol");
       
   232             }
       
   233 
       
   234             return protocolVersion.v - this.v;
       
   235         } else {
       
   236             if (protocolVersion.maybeDTLSProtocol()) {
       
   237                 throw new IllegalArgumentException("Not TLS protocol");
       
   238             }
       
   239 
       
   240             return this.v - protocolVersion.v;
       
   241         }
       
   242     }
       
   243 
       
   244     /**
       
   245      * Returns true if a ProtocolVersion represents a DTLS protocol.
       
   246      */
       
   247     boolean isDTLSProtocol() {
       
   248         return this.v == DTLS12.v || this.v == DTLS10.v;
       
   249     }
       
   250 
       
   251     /**
       
   252      * Returns true if a ProtocolVersion may represent a DTLS protocol.
       
   253      */
       
   254     boolean maybeDTLSProtocol() {
       
   255         return (this.major & 0x80) != 0;
       
   256     }
       
   257 
       
   258     boolean useTLS12PlusSpec() {
       
   259         return maybeDTLSProtocol() ? (this.v <= DTLS12.v) : (this.v >= TLS12.v);
       
   260     }
       
   261 
       
   262     boolean useTLS11PlusSpec() {
       
   263         return maybeDTLSProtocol() ? true : (this.v >= TLS11.v);
       
   264     }
       
   265 
       
   266     boolean useTLS10PlusSpec() {
       
   267         return maybeDTLSProtocol() ? true : (this.v >= TLS10.v);
       
   268     }
       
   269 
       
   270     boolean obsoletes(CipherSuite suite) {
       
   271         ProtocolVersion proto = this;
       
   272         if (proto.isDTLSProtocol()) {
       
   273             // DTLS bans stream ciphers.
       
   274             if (suite.cipher.cipherType == CipherType.STREAM_CIPHER) {
       
   275                 return true;
       
   276             }
       
   277 
       
   278             proto = mapToTLSProtocol(this);
       
   279         }
       
   280 
       
   281         return (proto.v >= suite.obsoleted);
       
   282     }
       
   283 
       
   284     boolean supports(CipherSuite suite) {
       
   285         ProtocolVersion proto = this;
       
   286         if (proto.isDTLSProtocol()) {
       
   287             // DTLS bans stream ciphers.
       
   288             if (suite.cipher.cipherType == CipherType.STREAM_CIPHER) {
       
   289                 return false;
       
   290             }
       
   291 
       
   292             proto = mapToTLSProtocol(this);
       
   293         }
       
   294 
       
   295         return (proto.v >= suite.supported);
       
   296     }
       
   297 
       
   298     // Map a specified protocol to the corresponding TLS version.
       
   299     //
       
   300     // DTLS 1.2 -> TLS 1.2
       
   301     // DTLS 1.0 -> TLS 1.1
       
   302     private static ProtocolVersion mapToTLSProtocol(
       
   303             ProtocolVersion protocolVersion) {
       
   304 
       
   305         if (protocolVersion.isDTLSProtocol()) {
       
   306             if (protocolVersion.v == DTLS10.v) {
       
   307                 protocolVersion = TLS11;
       
   308             } else {    // DTLS12
       
   309                 protocolVersion = TLS12;
       
   310             }
       
   311         }
       
   312 
       
   313         return protocolVersion;
   205     }
   314     }
   206 }
   315 }