rev 52979 : 8215281: Use String.isEmpty() when applicable in java.base
Reviewed-by: TBD

   1 /*
   2  * Copyright (c) 1999, 2018, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  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
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.io.*;
  29 import java.net.Socket;
  30 import java.security.*;
  31 import java.security.cert.*;
  32 import java.util.*;
  33 import javax.net.ssl.*;
  34 import sun.security.action.GetPropertyAction;
  35 import sun.security.provider.certpath.AlgorithmChecker;
  36 import sun.security.validator.Validator;
  37 
  38 /**
  39  * Implementation of an SSLContext.
  40  *
  41  * Implementation note: Instances of this class and the child classes are
  42  * immutable, except that the context initialization (SSLContext.init()) may
  43  * reset the key, trust managers and source of secure random.
  44  */
  45 
  46 public abstract class SSLContextImpl extends SSLContextSpi {
  47 
  48     private final EphemeralKeyManager ephemeralKeyManager;
  49     private final SSLSessionContextImpl clientCache;
  50     private final SSLSessionContextImpl serverCache;
  51 
  52     private boolean isInitialized;
  53 
  54     private X509ExtendedKeyManager keyManager;
  55     private X509TrustManager trustManager;
  56     private SecureRandom secureRandom;
  57 
  58     // DTLS cookie exchange manager
  59     private volatile HelloCookieManager.Builder helloCookieManagerBuilder;
  60 
  61     private final boolean clientEnableStapling = Utilities.getBooleanProperty(
  62             "jdk.tls.client.enableStatusRequestExtension", true);
  63     private final boolean serverEnableStapling = Utilities.getBooleanProperty(
  64             "jdk.tls.server.enableStatusRequestExtension", false);
  65     private static final Collection<CipherSuite> clientCustomizedCipherSuites =
  66             getCustomizedCipherSuites("jdk.tls.client.cipherSuites");
  67     private static final Collection<CipherSuite> serverCustomizedCipherSuites =
  68             getCustomizedCipherSuites("jdk.tls.server.cipherSuites");
  69 
  70     private volatile StatusResponseManager statusResponseManager;
  71 
  72     SSLContextImpl() {
  73         ephemeralKeyManager = new EphemeralKeyManager();
  74         clientCache = new SSLSessionContextImpl();
  75         serverCache = new SSLSessionContextImpl();
  76     }
  77 
  78     @Override
  79     protected void engineInit(KeyManager[] km, TrustManager[] tm,
  80                                 SecureRandom sr) throws KeyManagementException {
  81         isInitialized = false;
  82         keyManager = chooseKeyManager(km);
  83 
  84         if (tm == null) {
  85             try {
  86                 TrustManagerFactory tmf = TrustManagerFactory.getInstance(
  87                         TrustManagerFactory.getDefaultAlgorithm());
  88                 tmf.init((KeyStore)null);
  89                 tm = tmf.getTrustManagers();
  90             } catch (Exception e) {
  91                 // eat
  92             }
  93         }
  94         trustManager = chooseTrustManager(tm);
  95 
  96         if (sr == null) {
  97             secureRandom = JsseJce.getSecureRandom();
  98         } else {
  99             if (SunJSSE.isFIPS() &&
 100                         (sr.getProvider() != SunJSSE.cryptoProvider)) {
 101                 throw new KeyManagementException
 102                     ("FIPS mode: SecureRandom must be from provider "
 103                     + SunJSSE.cryptoProvider.getName());
 104             }
 105             secureRandom = sr;
 106         }
 107 
 108         /*
 109          * The initial delay of seeding the random number generator
 110          * could be long enough to cause the initial handshake on our
 111          * first connection to timeout and fail. Make sure it is
 112          * primed and ready by getting some initial output from it.
 113          */
 114         if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 115             SSLLogger.finest("trigger seeding of SecureRandom");
 116         }
 117         secureRandom.nextInt();
 118         if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 119             SSLLogger.finest("done seeding of SecureRandom");
 120         }
 121 
 122         isInitialized = true;
 123     }
 124 
 125     private X509TrustManager chooseTrustManager(TrustManager[] tm)
 126             throws KeyManagementException {
 127         // We only use the first instance of X509TrustManager passed to us.
 128         for (int i = 0; tm != null && i < tm.length; i++) {
 129             if (tm[i] instanceof X509TrustManager) {
 130                 if (SunJSSE.isFIPS() &&
 131                         !(tm[i] instanceof X509TrustManagerImpl)) {
 132                     throw new KeyManagementException
 133                         ("FIPS mode: only SunJSSE TrustManagers may be used");
 134                 }
 135 
 136                 if (tm[i] instanceof X509ExtendedTrustManager) {
 137                     return (X509TrustManager)tm[i];
 138                 } else {
 139                     return new AbstractTrustManagerWrapper(
 140                                         (X509TrustManager)tm[i]);
 141                 }
 142             }
 143         }
 144 
 145         // nothing found, return a dummy X509TrustManager.
 146         return DummyX509TrustManager.INSTANCE;
 147     }
 148 
 149     private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
 150             throws KeyManagementException {
 151         for (int i = 0; kms != null && i < kms.length; i++) {
 152             KeyManager km = kms[i];
 153             if (!(km instanceof X509KeyManager)) {
 154                 continue;
 155             }
 156             if (SunJSSE.isFIPS()) {
 157                 // In FIPS mode, require that one of SunJSSE's own keymanagers
 158                 // is used. Otherwise, we cannot be sure that only keys from
 159                 // the FIPS token are used.
 160                 if ((km instanceof X509KeyManagerImpl)
 161                             || (km instanceof SunX509KeyManagerImpl)) {
 162                     return (X509ExtendedKeyManager)km;
 163                 } else {
 164                     // throw exception, we don't want to silently use the
 165                     // dummy keymanager without telling the user.
 166                     throw new KeyManagementException
 167                         ("FIPS mode: only SunJSSE KeyManagers may be used");
 168                 }
 169             }
 170             if (km instanceof X509ExtendedKeyManager) {
 171                 return (X509ExtendedKeyManager)km;
 172             }
 173 
 174             if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 175                 SSLLogger.warning(
 176                     "X509KeyManager passed to SSLContext.init():  need an " +
 177                     "X509ExtendedKeyManager for SSLEngine use");
 178             }
 179             return new AbstractKeyManagerWrapper((X509KeyManager)km);
 180         }
 181 
 182         // nothing found, return a dummy X509ExtendedKeyManager
 183         return DummyX509KeyManager.INSTANCE;
 184     }
 185 
 186     abstract SSLEngine createSSLEngineImpl();
 187     abstract SSLEngine createSSLEngineImpl(String host, int port);
 188 
 189     @Override
 190     protected SSLEngine engineCreateSSLEngine() {
 191         if (!isInitialized) {
 192             throw new IllegalStateException("SSLContext is not initialized");
 193         }
 194         return createSSLEngineImpl();
 195     }
 196 
 197     @Override
 198     protected SSLEngine engineCreateSSLEngine(String host, int port) {
 199         if (!isInitialized) {
 200             throw new IllegalStateException("SSLContext is not initialized");
 201         }
 202         return createSSLEngineImpl(host, port);
 203     }
 204 
 205     @Override
 206     protected SSLSocketFactory engineGetSocketFactory() {
 207         if (!isInitialized) {
 208             throw new IllegalStateException("SSLContext is not initialized");
 209         }
 210         if (isDTLS()) {
 211             throw new UnsupportedOperationException(
 212                     "DTLS not supported with SSLSocket");
 213         }
 214        return new SSLSocketFactoryImpl(this);
 215     }
 216 
 217     @Override
 218     protected SSLServerSocketFactory engineGetServerSocketFactory() {
 219         if (!isInitialized) {
 220             throw new IllegalStateException("SSLContext is not initialized");
 221         }
 222         if (isDTLS()) {
 223             throw new UnsupportedOperationException(
 224                     "DTLS not supported with SSLServerSocket");
 225         }
 226         return new SSLServerSocketFactoryImpl(this);
 227     }
 228 
 229     @Override
 230     protected SSLSessionContext engineGetClientSessionContext() {
 231         return clientCache;
 232     }
 233 
 234     @Override
 235     protected SSLSessionContext engineGetServerSessionContext() {
 236         return serverCache;
 237     }
 238 
 239     SecureRandom getSecureRandom() {
 240         return secureRandom;
 241     }
 242 
 243     X509ExtendedKeyManager getX509KeyManager() {
 244         return keyManager;
 245     }
 246 
 247     X509TrustManager getX509TrustManager() {
 248         return trustManager;
 249     }
 250 
 251     EphemeralKeyManager getEphemeralKeyManager() {
 252         return ephemeralKeyManager;
 253     }
 254 
 255     // Used for DTLS in server mode only.
 256     HelloCookieManager getHelloCookieManager(ProtocolVersion protocolVersion) {
 257         if (helloCookieManagerBuilder == null) {
 258             synchronized (this) {
 259                 if (helloCookieManagerBuilder == null) {
 260                     helloCookieManagerBuilder =
 261                             new HelloCookieManager.Builder(secureRandom);
 262                 }
 263             }
 264         }
 265 
 266         return helloCookieManagerBuilder.valueOf(protocolVersion);
 267     }
 268 
 269     StatusResponseManager getStatusResponseManager() {
 270         if (serverEnableStapling && statusResponseManager == null) {
 271             synchronized (this) {
 272                 if (statusResponseManager == null) {
 273                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 274                         SSLLogger.finest(
 275                                 "Initializing StatusResponseManager");
 276                     }
 277                     statusResponseManager = new StatusResponseManager();
 278                 }
 279             }
 280         }
 281 
 282         return statusResponseManager;
 283     }
 284 
 285     // Get supported protocols.
 286     abstract List<ProtocolVersion> getSupportedProtocolVersions();
 287 
 288     // Get default protocols for server mode.
 289     abstract List<ProtocolVersion> getServerDefaultProtocolVersions();
 290 
 291     // Get default protocols for client mode.
 292     abstract List<ProtocolVersion> getClientDefaultProtocolVersions();
 293 
 294     // Get supported CipherSuite list.
 295     abstract List<CipherSuite> getSupportedCipherSuites();
 296 
 297     // Get default CipherSuite list for server mode.
 298     abstract List<CipherSuite> getServerDefaultCipherSuites();
 299 
 300     // Get default CipherSuite list for client mode.
 301     abstract List<CipherSuite> getClientDefaultCipherSuites();
 302 
 303     // Is the context for DTLS protocols?
 304     abstract boolean isDTLS();
 305 
 306     // Get default protocols.
 307     List<ProtocolVersion> getDefaultProtocolVersions(boolean roleIsServer) {
 308         return roleIsServer ? getServerDefaultProtocolVersions()
 309                             : getClientDefaultProtocolVersions();
 310     }
 311 
 312     // Get default CipherSuite list.
 313     List<CipherSuite> getDefaultCipherSuites(boolean roleIsServer) {
 314         return roleIsServer ? getServerDefaultCipherSuites()
 315                             : getClientDefaultCipherSuites();
 316     }
 317 
 318     /**
 319      * Return whether a protocol list is the original default enabled
 320      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
 321      */
 322     boolean isDefaultProtocolVesions(List<ProtocolVersion> protocols) {
 323         return (protocols == getServerDefaultProtocolVersions()) ||
 324                (protocols == getClientDefaultProtocolVersions());
 325     }
 326 
 327     /**
 328      * Return whether a protocol list is the original default enabled
 329      * protocols.  See: SSLSocket/SSLEngine.setEnabledProtocols()
 330      */
 331     boolean isDefaultCipherSuiteList(List<CipherSuite> cipherSuites) {
 332         return (cipherSuites == getServerDefaultCipherSuites()) ||
 333                (cipherSuites == getClientDefaultCipherSuites());
 334     }
 335 
 336     /**
 337      * Return whether client or server side stapling has been enabled
 338      * for this SSLContextImpl
 339      * @param isClient true if the caller is operating in a client side role,
 340      * false if acting as a server.
 341      * @return true if stapling has been enabled for the specified role, false
 342      * otherwise.
 343      */
 344     boolean isStaplingEnabled(boolean isClient) {
 345         return isClient ? clientEnableStapling : serverEnableStapling;
 346     }
 347 
 348     /*
 349      * Return the list of all available CipherSuites that are supported
 350      * using currently installed providers.
 351      */
 352     private static List<CipherSuite> getApplicableSupportedCipherSuites(
 353             List<ProtocolVersion> protocols) {
 354 
 355         return getApplicableCipherSuites(
 356                 CipherSuite.allowedCipherSuites(), protocols);
 357     }
 358 
 359     /*
 360      * Return the list of all available CipherSuites that are default enabled
 361      * in client or server side.
 362      */
 363     private static List<CipherSuite> getApplicableEnabledCipherSuites(
 364             List<ProtocolVersion> protocols, boolean isClient) {
 365 
 366         if (isClient) {
 367             if (!clientCustomizedCipherSuites.isEmpty()) {
 368                 return getApplicableCipherSuites(
 369                         clientCustomizedCipherSuites, protocols);
 370             }
 371         } else {
 372             if (!serverCustomizedCipherSuites.isEmpty()) {
 373                 return getApplicableCipherSuites(
 374                         serverCustomizedCipherSuites, protocols);
 375             }
 376         }
 377 
 378         return getApplicableCipherSuites(
 379                 CipherSuite.defaultCipherSuites(), protocols);
 380     }
 381 
 382     /*
 383      * Return the list of available CipherSuites which are applicable to
 384      * the specified protocols.
 385      */
 386     private static List<CipherSuite> getApplicableCipherSuites(
 387             Collection<CipherSuite> allowedCipherSuites,
 388             List<ProtocolVersion> protocols) {
 389         TreeSet<CipherSuite> suites = new TreeSet<>();
 390         if (protocols != null && (!protocols.isEmpty())) {
 391             for (CipherSuite suite : allowedCipherSuites) {
 392                 if (!suite.isAvailable()) {
 393                     continue;
 394                 }
 395 
 396                 boolean isSupported = false;
 397                 for (ProtocolVersion protocol : protocols) {
 398                     if (!suite.supports(protocol)) {
 399                         continue;
 400                     }
 401 
 402                     if (SSLAlgorithmConstraints.DEFAULT.permits(
 403                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
 404                             suite.name, null)) {
 405                         suites.add(suite);
 406                         isSupported = true;
 407                     } else if (SSLLogger.isOn &&
 408                             SSLLogger.isOn("ssl,sslctx,verbose")) {
 409                         SSLLogger.fine(
 410                                 "Ignore disabled cipher suite: " + suite.name);
 411                     }
 412 
 413                     break;
 414                 }
 415 
 416                 if (!isSupported && SSLLogger.isOn &&
 417                         SSLLogger.isOn("ssl,sslctx,verbose")) {
 418                     SSLLogger.finest(
 419                             "Ignore unsupported cipher suite: " + suite);
 420                 }
 421             }
 422         }
 423 
 424         return new ArrayList<>(suites);
 425     }
 426 
 427     /*
 428      * Get the customized cipher suites specified by the given system property.
 429      */
 430     private static Collection<CipherSuite> getCustomizedCipherSuites(
 431             String propertyName) {
 432 
 433         String property = GetPropertyAction.privilegedGetProperty(propertyName);
 434         if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 435             SSLLogger.fine(
 436                     "System property " + propertyName + " is set to '" +
 437                     property + "'");
 438         }
 439         if (property != null && property.length() != 0) {
 440             // remove double quote marks from beginning/end of the property
 441             if (property.length() > 1 && property.charAt(0) == '"' &&
 442                     property.charAt(property.length() - 1) == '"') {
 443                 property = property.substring(1, property.length() - 1);
 444             }
 445         }
 446 
 447         if (property != null && property.length() != 0) {
 448             String[] cipherSuiteNames = property.split(",");
 449             Collection<CipherSuite> cipherSuites =
 450                         new ArrayList<>(cipherSuiteNames.length);
 451             for (int i = 0; i < cipherSuiteNames.length; i++) {
 452                 cipherSuiteNames[i] = cipherSuiteNames[i].trim();
 453                 if (cipherSuiteNames[i].isEmpty()) {
 454                     continue;
 455                 }
 456 
 457                 CipherSuite suite;
 458                 try {
 459                     suite = CipherSuite.nameOf(cipherSuiteNames[i]);
 460                 } catch (IllegalArgumentException iae) {
 461                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 462                         SSLLogger.fine(
 463                                 "Unknown or unsupported cipher suite name: " +
 464                                 cipherSuiteNames[i]);
 465                     }
 466 
 467                     continue;
 468                 }
 469 
 470                 if (suite != null && suite.isAvailable()) {
 471                     cipherSuites.add(suite);
 472                 } else {
 473                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
 474                         SSLLogger.fine(
 475                                 "The current installed providers do not " +
 476                                 "support cipher suite: " + cipherSuiteNames[i]);
 477                     }
 478                 }
 479             }
 480 
 481             return cipherSuites;
 482         }
 483 
 484         return Collections.emptyList();
 485     }
 486 
 487 
 488     private static List<ProtocolVersion> getAvailableProtocols(
 489             ProtocolVersion[] protocolCandidates) {
 490 
 491         List<ProtocolVersion> availableProtocols =
 492                 Collections.<ProtocolVersion>emptyList();
 493         if (protocolCandidates != null && protocolCandidates.length != 0) {
 494             availableProtocols = new ArrayList<>(protocolCandidates.length);
 495             for (ProtocolVersion p : protocolCandidates) {
 496                 if (p.isAvailable) {
 497                     availableProtocols.add(p);
 498                 }
 499             }
 500         }
 501 
 502         return availableProtocols;
 503     }
 504 
 505     /*
 506      * The SSLContext implementation for SSL/(D)TLS algorithm
 507      *
 508      * SSL/TLS protocols specify the forward compatibility and version
 509      * roll-back attack protections, however, a number of SSL/TLS server
 510      * vendors did not implement these aspects properly, and some current
 511      * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
 512      *
 513      * Considering above interoperability issues, SunJSSE will not set
 514      * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
 515      *
 516      * For SSL/TLS servers, there is no such interoperability issues as
 517      * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
 518      * enabled protocols for server by default.
 519      *
 520      * We may change the behavior when popular TLS/SSL vendors support TLS
 521      * forward compatibility properly.
 522      *
 523      * SSLv2Hello is no longer necessary.  This interoperability option was
 524      * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
 525      * and there were a fair number of SSLv2-only servers deployed.  Because
 526      * of the security issues in SSLv2, it is rarely (if ever) used, as
 527      * deployments should now be using SSLv3 and TLSv1.
 528      *
 529      * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
 530      * by default. Applications still can use it by enabling SSLv2Hello with
 531      * the series of setEnabledProtocols APIs.
 532      */
 533 
 534     /*
 535      * The base abstract SSLContext implementation for the Transport Layer
 536      * Security (TLS) protocols.
 537      *
 538      * This abstract class encapsulates supported and the default server
 539      * SSL/TLS parameters.
 540      *
 541      * @see SSLContext
 542      */
 543     private abstract static class AbstractTLSContext extends SSLContextImpl {
 544         private static final List<ProtocolVersion> supportedProtocols;
 545         private static final List<ProtocolVersion> serverDefaultProtocols;
 546 
 547         private static final List<CipherSuite> supportedCipherSuites;
 548         private static final List<CipherSuite> serverDefaultCipherSuites;
 549 
 550         static {
 551             if (SunJSSE.isFIPS()) {
 552                 supportedProtocols = Arrays.asList(
 553                     ProtocolVersion.TLS13,
 554                     ProtocolVersion.TLS12,
 555                     ProtocolVersion.TLS11,
 556                     ProtocolVersion.TLS10
 557                 );
 558 
 559                 serverDefaultProtocols = getAvailableProtocols(
 560                         new ProtocolVersion[] {
 561                     ProtocolVersion.TLS13,
 562                     ProtocolVersion.TLS12,
 563                     ProtocolVersion.TLS11,
 564                     ProtocolVersion.TLS10
 565                 });
 566             } else {
 567                 supportedProtocols = Arrays.asList(
 568                     ProtocolVersion.TLS13,
 569                     ProtocolVersion.TLS12,
 570                     ProtocolVersion.TLS11,
 571                     ProtocolVersion.TLS10,
 572                     ProtocolVersion.SSL30,
 573                     ProtocolVersion.SSL20Hello
 574                 );
 575 
 576                 serverDefaultProtocols = getAvailableProtocols(
 577                         new ProtocolVersion[] {
 578                     ProtocolVersion.TLS13,
 579                     ProtocolVersion.TLS12,
 580                     ProtocolVersion.TLS11,
 581                     ProtocolVersion.TLS10,
 582                     ProtocolVersion.SSL30,
 583                     ProtocolVersion.SSL20Hello
 584                 });
 585             }
 586 
 587             supportedCipherSuites = getApplicableSupportedCipherSuites(
 588                     supportedProtocols);
 589             serverDefaultCipherSuites = getApplicableEnabledCipherSuites(
 590                     serverDefaultProtocols, false);
 591         }
 592 
 593         @Override
 594         List<ProtocolVersion> getSupportedProtocolVersions() {
 595             return supportedProtocols;
 596         }
 597 
 598         @Override
 599         List<CipherSuite> getSupportedCipherSuites() {
 600             return supportedCipherSuites;
 601         }
 602 
 603         @Override
 604         List<ProtocolVersion> getServerDefaultProtocolVersions() {
 605             return serverDefaultProtocols;
 606         }
 607 
 608         @Override
 609         List<CipherSuite> getServerDefaultCipherSuites() {
 610             return serverDefaultCipherSuites;
 611         }
 612 
 613         @Override
 614         SSLEngine createSSLEngineImpl() {
 615             return new SSLEngineImpl(this);
 616         }
 617 
 618         @Override
 619         SSLEngine createSSLEngineImpl(String host, int port) {
 620             return new SSLEngineImpl(this, host, port);
 621         }
 622 
 623         @Override
 624         boolean isDTLS() {
 625             return false;
 626         }
 627 
 628         static ProtocolVersion[] getSupportedProtocols() {
 629             if (SunJSSE.isFIPS()) {
 630                 return new ProtocolVersion[] {
 631                         ProtocolVersion.TLS13,
 632                         ProtocolVersion.TLS12,
 633                         ProtocolVersion.TLS11,
 634                         ProtocolVersion.TLS10
 635                 };
 636             } else {
 637                 return new ProtocolVersion[]{
 638                         ProtocolVersion.TLS13,
 639                         ProtocolVersion.TLS12,
 640                         ProtocolVersion.TLS11,
 641                         ProtocolVersion.TLS10,
 642                         ProtocolVersion.SSL30,
 643                         ProtocolVersion.SSL20Hello
 644                 };
 645             }
 646         }
 647     }
 648 
 649     /*
 650      * The SSLContext implementation for SSLv3 and TLS10 algorithm
 651      *
 652      * @see SSLContext
 653      */
 654     public static final class TLS10Context extends AbstractTLSContext {
 655         private static final List<ProtocolVersion> clientDefaultProtocols;
 656         private static final List<CipherSuite> clientDefaultCipherSuites;
 657 
 658         static {
 659             if (SunJSSE.isFIPS()) {
 660                 clientDefaultProtocols = getAvailableProtocols(
 661                         new ProtocolVersion[] {
 662                     ProtocolVersion.TLS10
 663                 });
 664             } else {
 665                 clientDefaultProtocols = getAvailableProtocols(
 666                         new ProtocolVersion[] {
 667                     ProtocolVersion.TLS10,
 668                     ProtocolVersion.SSL30
 669                 });
 670             }
 671 
 672             clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
 673                     clientDefaultProtocols, true);
 674         }
 675 
 676         @Override
 677         List<ProtocolVersion> getClientDefaultProtocolVersions() {
 678             return clientDefaultProtocols;
 679         }
 680 
 681         @Override
 682         List<CipherSuite> getClientDefaultCipherSuites() {
 683             return clientDefaultCipherSuites;
 684         }
 685     }
 686 
 687     /*
 688      * The SSLContext implementation for TLS11 algorithm
 689      *
 690      * @see SSLContext
 691      */
 692     public static final class TLS11Context extends AbstractTLSContext {
 693         private static final List<ProtocolVersion> clientDefaultProtocols;
 694         private static final List<CipherSuite> clientDefaultCipherSuites;
 695 
 696         static {
 697             if (SunJSSE.isFIPS()) {
 698                 clientDefaultProtocols = getAvailableProtocols(
 699                         new ProtocolVersion[] {
 700                     ProtocolVersion.TLS11,
 701                     ProtocolVersion.TLS10
 702                 });
 703             } else {
 704                 clientDefaultProtocols = getAvailableProtocols(
 705                         new ProtocolVersion[] {
 706                     ProtocolVersion.TLS11,
 707                     ProtocolVersion.TLS10,
 708                     ProtocolVersion.SSL30
 709                 });
 710             }
 711 
 712             clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
 713                     clientDefaultProtocols, true);
 714 
 715         }
 716 
 717         @Override
 718         List<ProtocolVersion> getClientDefaultProtocolVersions() {
 719             return clientDefaultProtocols;
 720         }
 721 
 722         @Override
 723         List<CipherSuite> getClientDefaultCipherSuites() {
 724             return clientDefaultCipherSuites;
 725         }
 726     }
 727 
 728     /*
 729      * The SSLContext implementation for TLS12 algorithm
 730      *
 731      * @see SSLContext
 732      */
 733     public static final class TLS12Context extends AbstractTLSContext {
 734         private static final List<ProtocolVersion> clientDefaultProtocols;
 735         private static final List<CipherSuite> clientDefaultCipherSuites;
 736 
 737         static {
 738             if (SunJSSE.isFIPS()) {
 739                 clientDefaultProtocols = getAvailableProtocols(
 740                         new ProtocolVersion[] {
 741                     ProtocolVersion.TLS12,
 742                     ProtocolVersion.TLS11,
 743                     ProtocolVersion.TLS10
 744                 });
 745             } else {
 746                 clientDefaultProtocols = getAvailableProtocols(
 747                         new ProtocolVersion[] {
 748                     ProtocolVersion.TLS12,
 749                     ProtocolVersion.TLS11,
 750                     ProtocolVersion.TLS10,
 751                     ProtocolVersion.SSL30
 752                 });
 753             }
 754 
 755             clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
 756                     clientDefaultProtocols, true);
 757         }
 758 
 759         @Override
 760         List<ProtocolVersion> getClientDefaultProtocolVersions() {
 761             return clientDefaultProtocols;
 762         }
 763 
 764         @Override
 765         List<CipherSuite> getClientDefaultCipherSuites() {
 766             return clientDefaultCipherSuites;
 767         }
 768     }
 769 
 770     /*
 771      * The SSLContext implementation for TLS1.3 algorithm
 772      *
 773      * @see SSLContext
 774      */
 775     public static final class TLS13Context extends AbstractTLSContext {
 776         private static final List<ProtocolVersion> clientDefaultProtocols;
 777         private static final List<CipherSuite> clientDefaultCipherSuites;
 778 
 779         static {
 780             if (SunJSSE.isFIPS()) {
 781                 clientDefaultProtocols = getAvailableProtocols(
 782                         new ProtocolVersion[] {
 783                     ProtocolVersion.TLS13,
 784                     ProtocolVersion.TLS12,
 785                     ProtocolVersion.TLS11,
 786                     ProtocolVersion.TLS10
 787                 });
 788             } else {
 789                 clientDefaultProtocols = getAvailableProtocols(
 790                         new ProtocolVersion[] {
 791                     ProtocolVersion.TLS13,
 792                     ProtocolVersion.TLS12,
 793                     ProtocolVersion.TLS11,
 794                     ProtocolVersion.TLS10,
 795                     ProtocolVersion.SSL30
 796                 });
 797             }
 798 
 799             clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
 800                     clientDefaultProtocols, true);
 801         }
 802 
 803         @Override
 804         List<ProtocolVersion> getClientDefaultProtocolVersions() {
 805             return clientDefaultProtocols;
 806         }
 807 
 808         @Override
 809         List<CipherSuite> getClientDefaultCipherSuites() {
 810             return clientDefaultCipherSuites;
 811         }
 812     }
 813 
 814     /*
 815      * The interface for the customized SSL/(D)TLS SSLContext.
 816      *
 817      * @see SSLContext
 818      */
 819     private static class CustomizedSSLProtocols {
 820         private static final String JDK_TLS_CLIENT_PROTOCOLS =
 821                 "jdk.tls.client.protocols";
 822         private static final String JDK_TLS_SERVER_PROTOCOLS =
 823                 "jdk.tls.server.protocols";
 824         static IllegalArgumentException reservedException = null;
 825         static final ArrayList<ProtocolVersion> customizedClientProtocols =
 826                 new ArrayList<>();
 827         static final ArrayList<ProtocolVersion> customizedServerProtocols =
 828                 new ArrayList<>();
 829 
 830         // Don't want a java.lang.LinkageError for illegal system property.
 831         //
 832         // Please don't throw exception in this static block.  Otherwise,
 833         // java.lang.LinkageError may be thrown during the instantiation of
 834         // the provider service. Instead, please handle the initialization
 835         // exception in the caller's constructor.
 836         static {
 837             populate(JDK_TLS_CLIENT_PROTOCOLS, customizedClientProtocols);
 838             populate(JDK_TLS_SERVER_PROTOCOLS, customizedServerProtocols);
 839         }
 840 
 841         private static void populate(String propname,
 842                 ArrayList<ProtocolVersion> arrayList) {
 843             String property = GetPropertyAction.privilegedGetProperty(propname);
 844             if (property == null) {
 845                 return;
 846             }
 847 
 848             if (property.length() != 0) {
 849                 // remove double quote marks from beginning/end of the property
 850                 if (property.length() > 1 && property.charAt(0) == '"' &&
 851                         property.charAt(property.length() - 1) == '"') {
 852                     property = property.substring(1, property.length() - 1);
 853                 }
 854             }
 855 
 856             if (property.length() != 0) {
 857                 String[] protocols = property.split(",");
 858                 for (int i = 0; i < protocols.length; i++) {
 859                     protocols[i] = protocols[i].trim();
 860                     // Is it a supported protocol name?
 861                     ProtocolVersion pv =
 862                             ProtocolVersion.nameOf(protocols[i]);
 863                     if (pv == null) {
 864                         reservedException = new IllegalArgumentException(
 865                             propname + ": " + protocols[i] +
 866                             " is not a supported SSL protocol name");
 867                     }
 868 
 869                     if (SunJSSE.isFIPS() &&
 870                             ((pv == ProtocolVersion.SSL30) ||
 871                              (pv == ProtocolVersion.SSL20Hello))) {
 872                         reservedException = new IllegalArgumentException(
 873                                 propname + ": " + pv +
 874                                 " is not FIPS compliant");
 875 
 876                         break;
 877                     }
 878 
 879                     // ignore duplicated protocols
 880                     if (!arrayList.contains(pv)) {
 881                         arrayList.add(pv);
 882                     }
 883                 }
 884             }
 885         }
 886     }
 887 
 888     /*
 889      * The SSLContext implementation for customized TLS protocols
 890      *
 891      * @see SSLContext
 892      */
 893     private static class CustomizedTLSContext extends AbstractTLSContext {
 894 
 895         private static final List<ProtocolVersion> clientDefaultProtocols;
 896         private static final List<ProtocolVersion> serverDefaultProtocols;
 897         private static final List<CipherSuite> clientDefaultCipherSuites;
 898         private static final List<CipherSuite> serverDefaultCipherSuites;
 899         private static final IllegalArgumentException reservedException;
 900 
 901         // Don't want a java.lang.LinkageError for illegal system property.
 902         //
 903         // Please don't throw exception in this static block.  Otherwise,
 904         // java.lang.LinkageError may be thrown during the instantiation of
 905         // the provider service. Instead, let's handle the initialization
 906         // exception in constructor.
 907         static {
 908             reservedException = CustomizedSSLProtocols.reservedException;
 909             if (reservedException == null) {
 910                 clientDefaultProtocols = customizedProtocols(true,
 911                         CustomizedSSLProtocols.customizedClientProtocols);
 912                 serverDefaultProtocols = customizedProtocols(false,
 913                         CustomizedSSLProtocols.customizedServerProtocols);
 914 
 915                 clientDefaultCipherSuites =
 916                         getApplicableEnabledCipherSuites(
 917                                 clientDefaultProtocols, true);
 918                 serverDefaultCipherSuites =
 919                         getApplicableEnabledCipherSuites(
 920                                 serverDefaultProtocols, false);
 921 
 922             } else {
 923                 // unlikely to be used
 924                 clientDefaultProtocols = null;
 925                 serverDefaultProtocols = null;
 926                 clientDefaultCipherSuites = null;
 927                 serverDefaultCipherSuites = null;
 928             }
 929         }
 930 
 931         private static List<ProtocolVersion> customizedProtocols(
 932                 boolean client, List<ProtocolVersion> customized) {
 933             List<ProtocolVersion> refactored = new ArrayList<>();
 934             for (ProtocolVersion pv : customized) {
 935                 if (!pv.isDTLS) {
 936                     refactored.add(pv);
 937                 }
 938             }
 939 
 940             // Use the default enabled protocols if no customization
 941             ProtocolVersion[] candidates;
 942             if (refactored.isEmpty()) {
 943                 if (client) {
 944                     candidates = getProtocols();
 945                 } else {
 946                     candidates = getSupportedProtocols();
 947                 }
 948             } else {
 949                 // Use the customized TLS protocols.
 950                 candidates =
 951                     refactored.toArray(new ProtocolVersion[refactored.size()]);
 952             }
 953 
 954             return getAvailableProtocols(candidates);
 955         }
 956 
 957         static ProtocolVersion[] getProtocols() {
 958             if (SunJSSE.isFIPS()) {
 959                 return new ProtocolVersion[]{
 960                         ProtocolVersion.TLS13,
 961                         ProtocolVersion.TLS12,
 962                         ProtocolVersion.TLS11,
 963                         ProtocolVersion.TLS10
 964                 };
 965             } else {
 966                 return new ProtocolVersion[]{
 967                         ProtocolVersion.TLS13,
 968                         ProtocolVersion.TLS12,
 969                         ProtocolVersion.TLS11,
 970                         ProtocolVersion.TLS10,
 971                         ProtocolVersion.SSL30
 972                 };
 973             }
 974         }
 975 
 976         protected CustomizedTLSContext() {
 977             if (reservedException != null) {
 978                 throw reservedException;
 979             }
 980         }
 981 
 982         @Override
 983         List<ProtocolVersion> getClientDefaultProtocolVersions() {
 984             return clientDefaultProtocols;
 985         }
 986 
 987         @Override
 988         List<ProtocolVersion> getServerDefaultProtocolVersions() {
 989             return serverDefaultProtocols;
 990         }
 991 
 992         @Override
 993         List<CipherSuite> getClientDefaultCipherSuites() {
 994             return clientDefaultCipherSuites;
 995         }
 996 
 997         @Override
 998         List<CipherSuite> getServerDefaultCipherSuites() {
 999             return serverDefaultCipherSuites;
1000         }
1001 
1002 
1003     }
1004 
1005     /*
1006      * The SSLContext implementation for default "TLS" algorithm
1007      *
1008      * @see SSLContext
1009      */
1010     public static final class TLSContext extends CustomizedTLSContext {
1011         // use the default constructor and methods
1012     }
1013 
1014     // lazy initialization holder class idiom for static default parameters
1015     //
1016     // See Effective Java Second Edition: Item 71.
1017     private static final class DefaultManagersHolder {
1018         private static final String NONE = "NONE";
1019         private static final String P11KEYSTORE = "PKCS11";
1020 
1021         private static final TrustManager[] trustManagers;
1022         private static final KeyManager[] keyManagers;
1023 
1024         private static final Exception reservedException;
1025 
1026         static {
1027             Exception reserved = null;
1028             TrustManager[] tmMediator;
1029             try {
1030                 tmMediator = getTrustManagers();
1031             } catch (Exception e) {
1032                 reserved = e;
1033                 tmMediator = new TrustManager[0];
1034             }
1035             trustManagers = tmMediator;
1036 
1037             if (reserved == null) {
1038                 KeyManager[] kmMediator;
1039                 try {
1040                     kmMediator = getKeyManagers();
1041                 } catch (Exception e) {
1042                     reserved = e;
1043                     kmMediator = new KeyManager[0];
1044                 }
1045                 keyManagers = kmMediator;
1046             } else {
1047                 keyManagers = new KeyManager[0];
1048             }
1049 
1050             reservedException = reserved;
1051         }
1052 
1053         private static TrustManager[] getTrustManagers() throws Exception {
1054             TrustManagerFactory tmf = TrustManagerFactory.getInstance(
1055                     TrustManagerFactory.getDefaultAlgorithm());
1056             if ("SunJSSE".equals(tmf.getProvider().getName())) {
1057                 // The implementation will load the default KeyStore
1058                 // automatically.  Cached trust materials may be used
1059                 // for performance improvement.
1060                 tmf.init((KeyStore)null);
1061             } else {
1062                 // Use the explicitly specified KeyStore for third party's
1063                 // TrustManagerFactory implementation.
1064                 KeyStore ks = TrustStoreManager.getTrustedKeyStore();
1065                 tmf.init(ks);
1066             }
1067 
1068             return tmf.getTrustManagers();
1069         }
1070 
1071         private static KeyManager[] getKeyManagers() throws Exception {
1072 
1073             final Map<String,String> props = new HashMap<>();
1074             AccessController.doPrivileged(
1075                         new PrivilegedExceptionAction<Object>() {
1076                 @Override
1077                 public Object run() throws Exception {
1078                     props.put("keyStore",  System.getProperty(
1079                                 "javax.net.ssl.keyStore", ""));
1080                     props.put("keyStoreType", System.getProperty(
1081                                 "javax.net.ssl.keyStoreType",
1082                                 KeyStore.getDefaultType()));
1083                     props.put("keyStoreProvider", System.getProperty(
1084                                 "javax.net.ssl.keyStoreProvider", ""));
1085                     props.put("keyStorePasswd", System.getProperty(
1086                                 "javax.net.ssl.keyStorePassword", ""));
1087                     return null;
1088                 }
1089             });
1090 
1091             final String defaultKeyStore = props.get("keyStore");
1092             String defaultKeyStoreType = props.get("keyStoreType");
1093             String defaultKeyStoreProvider = props.get("keyStoreProvider");
1094             if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
1095                 SSLLogger.fine("keyStore is : " + defaultKeyStore);
1096                 SSLLogger.fine("keyStore type is : " +
1097                                         defaultKeyStoreType);
1098                 SSLLogger.fine("keyStore provider is : " +
1099                                         defaultKeyStoreProvider);
1100             }
1101 
1102             if (P11KEYSTORE.equals(defaultKeyStoreType) &&
1103                     !NONE.equals(defaultKeyStore)) {
1104                 throw new IllegalArgumentException("if keyStoreType is "
1105                     + P11KEYSTORE + ", then keyStore must be " + NONE);
1106             }
1107 
1108             FileInputStream fs = null;
1109             KeyStore ks = null;
1110             char[] passwd = null;
1111             try {
1112                 if (defaultKeyStore.length() != 0 &&
1113                         !NONE.equals(defaultKeyStore)) {
1114                     fs = AccessController.doPrivileged(
1115                             new PrivilegedExceptionAction<FileInputStream>() {
1116                         @Override
1117                         public FileInputStream run() throws Exception {
1118                             return new FileInputStream(defaultKeyStore);
1119                         }
1120                     });
1121                 }
1122 
1123                 String defaultKeyStorePassword = props.get("keyStorePasswd");
1124                 if (defaultKeyStorePassword.length() != 0) {
1125                     passwd = defaultKeyStorePassword.toCharArray();
1126                 }
1127 
1128                 /**
1129                  * Try to initialize key store.
1130                  */
1131                 if ((defaultKeyStoreType.length()) != 0) {
1132                     if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
1133                         SSLLogger.finest("init keystore");
1134                     }
1135                     if (defaultKeyStoreProvider.length() == 0) {
1136                         ks = KeyStore.getInstance(defaultKeyStoreType);
1137                     } else {
1138                         ks = KeyStore.getInstance(defaultKeyStoreType,
1139                                             defaultKeyStoreProvider);
1140                     }
1141 
1142                     // if defaultKeyStore is NONE, fs will be null
1143                     ks.load(fs, passwd);
1144                 }
1145             } finally {
1146                 if (fs != null) {
1147                     fs.close();
1148                     fs = null;
1149                 }
1150             }
1151 
1152             /*
1153              * Try to initialize key manager.
1154              */
1155             if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
1156                 SSLLogger.fine("init keymanager of type " +
1157                     KeyManagerFactory.getDefaultAlgorithm());
1158             }
1159             KeyManagerFactory kmf = KeyManagerFactory.getInstance(
1160                 KeyManagerFactory.getDefaultAlgorithm());
1161 
1162             if (P11KEYSTORE.equals(defaultKeyStoreType)) {
1163                 kmf.init(ks, null); // do not pass key passwd if using token
1164             } else {
1165                 kmf.init(ks, passwd);
1166             }
1167 
1168             return kmf.getKeyManagers();
1169         }
1170     }
1171 
1172     // lazy initialization holder class idiom for static default parameters
1173     //
1174     // See Effective Java Second Edition: Item 71.
1175     private static final class DefaultSSLContextHolder {
1176 
1177         private static final SSLContextImpl sslContext;
1178         static Exception reservedException = null;
1179 
1180         static {
1181             SSLContextImpl mediator = null;
1182             if (DefaultManagersHolder.reservedException != null) {
1183                 reservedException = DefaultManagersHolder.reservedException;
1184             } else {
1185                 try {
1186                     mediator = new DefaultSSLContext();
1187                 } catch (Exception e) {
1188                     reservedException = e;
1189                 }
1190             }
1191 
1192             sslContext = mediator;
1193         }
1194     }
1195 
1196     /*
1197      * The SSLContext implementation for default "Default" algorithm
1198      *
1199      * @see SSLContext
1200      */
1201     public static final class DefaultSSLContext extends CustomizedTLSContext {
1202 
1203         // public constructor for SSLContext.getInstance("Default")
1204         public DefaultSSLContext() throws Exception {
1205             if (DefaultManagersHolder.reservedException != null) {
1206                 throw DefaultManagersHolder.reservedException;
1207             }
1208 
1209             try {
1210                 super.engineInit(DefaultManagersHolder.keyManagers,
1211                         DefaultManagersHolder.trustManagers, null);
1212             } catch (Exception e) {
1213                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,defaultctx")) {
1214                     SSLLogger.fine("default context init failed: ", e);
1215                 }
1216                 throw e;
1217             }
1218         }
1219 
1220         @Override
1221         protected void engineInit(KeyManager[] km, TrustManager[] tm,
1222             SecureRandom sr) throws KeyManagementException {
1223             throw new KeyManagementException
1224                 ("Default SSLContext is initialized automatically");
1225         }
1226 
1227         static SSLContextImpl getDefaultImpl() throws Exception {
1228             if (DefaultSSLContextHolder.reservedException != null) {
1229                 throw DefaultSSLContextHolder.reservedException;
1230             }
1231 
1232             return DefaultSSLContextHolder.sslContext;
1233         }
1234     }
1235 
1236     /*
1237      * The base abstract SSLContext implementation for the Datagram Transport
1238      * Layer Security (DTLS) protocols.
1239      *
1240      * This abstract class encapsulates supported and the default server DTLS
1241      * parameters.
1242      *
1243      * @see SSLContext
1244      */
1245     private abstract static class AbstractDTLSContext extends SSLContextImpl {
1246         private static final List<ProtocolVersion> supportedProtocols;
1247         private static final List<ProtocolVersion> serverDefaultProtocols;
1248 
1249         private static final List<CipherSuite> supportedCipherSuites;
1250         private static final List<CipherSuite> serverDefaultCipherSuites;
1251 
1252         static {
1253             // Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
1254             supportedProtocols = Arrays.asList(
1255                 ProtocolVersion.DTLS12,
1256                 ProtocolVersion.DTLS10
1257             );
1258 
1259             // available protocols for server mode
1260             serverDefaultProtocols = getAvailableProtocols(
1261                     new ProtocolVersion[] {
1262                 ProtocolVersion.DTLS12,
1263                 ProtocolVersion.DTLS10
1264             });
1265 
1266             supportedCipherSuites = getApplicableSupportedCipherSuites(
1267                     supportedProtocols);
1268             serverDefaultCipherSuites = getApplicableEnabledCipherSuites(
1269                     serverDefaultProtocols, false);
1270         }
1271 
1272         @Override
1273         protected SSLParameters engineGetDefaultSSLParameters() {
1274             SSLEngine engine = createSSLEngineImpl();
1275             return engine.getSSLParameters();
1276         }
1277 
1278         @Override
1279         protected SSLParameters engineGetSupportedSSLParameters() {
1280             SSLEngine engine = createSSLEngineImpl();
1281             SSLParameters params = new SSLParameters();
1282             params.setCipherSuites(engine.getSupportedCipherSuites());
1283             params.setProtocols(engine.getSupportedProtocols());
1284             return params;
1285         }
1286 
1287         @Override
1288         List<ProtocolVersion> getSupportedProtocolVersions() {
1289             return supportedProtocols;
1290         }
1291 
1292         @Override
1293         List<CipherSuite> getSupportedCipherSuites() {
1294             return supportedCipherSuites;
1295         }
1296 
1297         @Override
1298         List<ProtocolVersion> getServerDefaultProtocolVersions() {
1299             return serverDefaultProtocols;
1300         }
1301 
1302         @Override
1303         List<CipherSuite> getServerDefaultCipherSuites() {
1304             return serverDefaultCipherSuites;
1305         }
1306 
1307         @Override
1308         SSLEngine createSSLEngineImpl() {
1309             return new SSLEngineImpl(this);
1310         }
1311 
1312         @Override
1313         SSLEngine createSSLEngineImpl(String host, int port) {
1314             return new SSLEngineImpl(this, host, port);
1315         }
1316 
1317         @Override
1318         boolean isDTLS() {
1319             return true;
1320         }
1321     }
1322 
1323     /*
1324      * The SSLContext implementation for DTLSv1.0 algorithm.
1325      *
1326      * @see SSLContext
1327      */
1328     public static final class DTLS10Context extends AbstractDTLSContext {
1329         private static final List<ProtocolVersion> clientDefaultProtocols;
1330         private static final List<CipherSuite> clientDefaultCipherSuites;
1331 
1332         static {
1333             // available protocols for client mode
1334             clientDefaultProtocols = getAvailableProtocols(
1335                     new ProtocolVersion[] {
1336                 ProtocolVersion.DTLS10
1337             });
1338 
1339             clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
1340                     clientDefaultProtocols, true);
1341         }
1342 
1343         @Override
1344         List<ProtocolVersion> getClientDefaultProtocolVersions() {
1345             return clientDefaultProtocols;
1346         }
1347 
1348         @Override
1349         List<CipherSuite> getClientDefaultCipherSuites() {
1350             return clientDefaultCipherSuites;
1351         }
1352     }
1353 
1354     /*
1355      * The SSLContext implementation for DTLSv1.2 algorithm.
1356      *
1357      * @see SSLContext
1358      */
1359     public static final class DTLS12Context extends AbstractDTLSContext {
1360         private static final List<ProtocolVersion> clientDefaultProtocols;
1361         private static final List<CipherSuite> clientDefaultCipherSuites;
1362 
1363         static {
1364             // available protocols for client mode
1365             clientDefaultProtocols = getAvailableProtocols(
1366                     new ProtocolVersion[] {
1367                 ProtocolVersion.DTLS12,
1368                 ProtocolVersion.DTLS10
1369             });
1370 
1371             clientDefaultCipherSuites = getApplicableEnabledCipherSuites(
1372                     clientDefaultProtocols, true);
1373         }
1374 
1375         @Override
1376         List<ProtocolVersion> getClientDefaultProtocolVersions() {
1377             return clientDefaultProtocols;
1378         }
1379 
1380         @Override
1381         List<CipherSuite> getClientDefaultCipherSuites() {
1382             return clientDefaultCipherSuites;
1383         }
1384     }
1385 
1386     /*
1387      * The SSLContext implementation for customized TLS protocols
1388      *
1389      * @see SSLContext
1390      */
1391     private static class CustomizedDTLSContext extends AbstractDTLSContext {
1392         private static final List<ProtocolVersion> clientDefaultProtocols;
1393         private static final List<ProtocolVersion> serverDefaultProtocols;
1394         private static final List<CipherSuite> clientDefaultCipherSuites;
1395         private static final List<CipherSuite> serverDefaultCipherSuites;
1396 
1397         private static IllegalArgumentException reservedException = null;
1398 
1399         // Don't want a java.lang.LinkageError for illegal system property.
1400         //
1401         // Please don't throw exception in this static block.  Otherwise,
1402         // java.lang.LinkageError may be thrown during the instantiation of
1403         // the provider service. Instead, let's handle the initialization
1404         // exception in constructor.
1405         static {
1406             reservedException = CustomizedSSLProtocols.reservedException;
1407             if (reservedException == null) {
1408                 clientDefaultProtocols = customizedProtocols(true,
1409                         CustomizedSSLProtocols.customizedClientProtocols);
1410                 serverDefaultProtocols = customizedProtocols(false,
1411                         CustomizedSSLProtocols.customizedServerProtocols);
1412 
1413                 clientDefaultCipherSuites =
1414                         getApplicableEnabledCipherSuites(
1415                                 clientDefaultProtocols, true);
1416                 serverDefaultCipherSuites =
1417                         getApplicableEnabledCipherSuites(
1418                                 serverDefaultProtocols, false);
1419 
1420             } else {
1421                 // unlikely to be used
1422                 clientDefaultProtocols = null;
1423                 serverDefaultProtocols = null;
1424                 clientDefaultCipherSuites = null;
1425                 serverDefaultCipherSuites = null;
1426             }
1427         }
1428 
1429         private static List<ProtocolVersion> customizedProtocols(boolean client,
1430                 List<ProtocolVersion> customized) {
1431             List<ProtocolVersion> refactored = new ArrayList<>();
1432             for (ProtocolVersion pv : customized) {
1433                 if (pv.isDTLS) {
1434                     refactored.add(pv);
1435                 }
1436             }
1437 
1438             ProtocolVersion[] candidates;
1439             // Use the default enabled protocols if no customization
1440             if (refactored.isEmpty()) {
1441                 candidates = new ProtocolVersion[]{
1442                         ProtocolVersion.DTLS12,
1443                         ProtocolVersion.DTLS10
1444                 };
1445                 if (!client)
1446                     return Arrays.asList(candidates);
1447             } else {
1448                 // Use the customized TLS protocols.
1449                 candidates =
1450                         new ProtocolVersion[customized.size()];
1451                 candidates = customized.toArray(candidates);
1452             }
1453 
1454             return getAvailableProtocols(candidates);
1455         }
1456 
1457         protected CustomizedDTLSContext() {
1458             if (reservedException != null) {
1459                 throw reservedException;
1460             }
1461         }
1462 
1463         @Override
1464         List<ProtocolVersion> getClientDefaultProtocolVersions() {
1465             return clientDefaultProtocols;
1466         }
1467 
1468         @Override
1469         List<ProtocolVersion> getServerDefaultProtocolVersions() {
1470             return serverDefaultProtocols;
1471         }
1472 
1473         @Override
1474         List<CipherSuite> getClientDefaultCipherSuites() {
1475             return clientDefaultCipherSuites;
1476         }
1477 
1478         @Override
1479         List<CipherSuite> getServerDefaultCipherSuites() {
1480             return serverDefaultCipherSuites;
1481         }
1482     }
1483 
1484     /*
1485      * The SSLContext implementation for default "DTLS" algorithm
1486      *
1487      * @see SSLContext
1488      */
1489     public static final class DTLSContext extends CustomizedDTLSContext {
1490         // use the default constructor and methods
1491     }
1492 
1493 }
1494 
1495 final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
1496             implements X509TrustManager {
1497 
1498     // the delegated trust manager
1499     private final X509TrustManager tm;
1500 
1501     AbstractTrustManagerWrapper(X509TrustManager tm) {
1502         this.tm = tm;
1503     }
1504 
1505     @Override
1506     public void checkClientTrusted(X509Certificate[] chain, String authType)
1507         throws CertificateException {
1508         tm.checkClientTrusted(chain, authType);
1509     }
1510 
1511     @Override
1512     public void checkServerTrusted(X509Certificate[] chain, String authType)
1513         throws CertificateException {
1514         tm.checkServerTrusted(chain, authType);
1515     }
1516 
1517     @Override
1518     public X509Certificate[] getAcceptedIssuers() {
1519         return tm.getAcceptedIssuers();
1520     }
1521 
1522     @Override
1523     public void checkClientTrusted(X509Certificate[] chain, String authType,
1524                 Socket socket) throws CertificateException {
1525         tm.checkClientTrusted(chain, authType);
1526         checkAdditionalTrust(chain, authType, socket, true);
1527     }
1528 
1529     @Override
1530     public void checkServerTrusted(X509Certificate[] chain, String authType,
1531             Socket socket) throws CertificateException {
1532         tm.checkServerTrusted(chain, authType);
1533         checkAdditionalTrust(chain, authType, socket, false);
1534     }
1535 
1536     @Override
1537     public void checkClientTrusted(X509Certificate[] chain, String authType,
1538             SSLEngine engine) throws CertificateException {
1539         tm.checkClientTrusted(chain, authType);
1540         checkAdditionalTrust(chain, authType, engine, true);
1541     }
1542 
1543     @Override
1544     public void checkServerTrusted(X509Certificate[] chain, String authType,
1545             SSLEngine engine) throws CertificateException {
1546         tm.checkServerTrusted(chain, authType);
1547         checkAdditionalTrust(chain, authType, engine, false);
1548     }
1549 
1550     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
1551                 Socket socket, boolean isClient) throws CertificateException {
1552         if (socket != null && socket.isConnected() &&
1553                                     socket instanceof SSLSocket) {
1554 
1555             SSLSocket sslSocket = (SSLSocket)socket;
1556             SSLSession session = sslSocket.getHandshakeSession();
1557             if (session == null) {
1558                 throw new CertificateException("No handshake session");
1559             }
1560 
1561             // check endpoint identity
1562             String identityAlg = sslSocket.getSSLParameters().
1563                                         getEndpointIdentificationAlgorithm();
1564             if (identityAlg != null && identityAlg.length() != 0) {
1565                 String hostname = session.getPeerHost();
1566                 X509TrustManagerImpl.checkIdentity(
1567                                     hostname, chain[0], identityAlg);
1568             }
1569 
1570             // try the best to check the algorithm constraints
1571             AlgorithmConstraints constraints;
1572             if (ProtocolVersion.useTLS12PlusSpec(session.getProtocol())) {
1573                 if (session instanceof ExtendedSSLSession) {
1574                     ExtendedSSLSession extSession =
1575                                     (ExtendedSSLSession)session;
1576                     String[] peerSupportedSignAlgs =
1577                             extSession.getLocalSupportedSignatureAlgorithms();
1578 
1579                     constraints = new SSLAlgorithmConstraints(
1580                                     sslSocket, peerSupportedSignAlgs, true);
1581                 } else {
1582                     constraints =
1583                             new SSLAlgorithmConstraints(sslSocket, true);
1584                 }
1585             } else {
1586                 constraints = new SSLAlgorithmConstraints(sslSocket, true);
1587             }
1588 
1589             checkAlgorithmConstraints(chain, constraints, isClient);
1590         }
1591     }
1592 
1593     private void checkAdditionalTrust(X509Certificate[] chain, String authType,
1594             SSLEngine engine, boolean isClient) throws CertificateException {
1595         if (engine != null) {
1596             SSLSession session = engine.getHandshakeSession();
1597             if (session == null) {
1598                 throw new CertificateException("No handshake session");
1599             }
1600 
1601             // check endpoint identity
1602             String identityAlg = engine.getSSLParameters().
1603                                         getEndpointIdentificationAlgorithm();
1604             if (identityAlg != null && identityAlg.length() != 0) {
1605                 String hostname = session.getPeerHost();
1606                 X509TrustManagerImpl.checkIdentity(
1607                                     hostname, chain[0], identityAlg);
1608             }
1609 
1610             // try the best to check the algorithm constraints
1611             AlgorithmConstraints constraints;
1612             if (ProtocolVersion.useTLS12PlusSpec(session.getProtocol())) {
1613                 if (session instanceof ExtendedSSLSession) {
1614                     ExtendedSSLSession extSession =
1615                                     (ExtendedSSLSession)session;
1616                     String[] peerSupportedSignAlgs =
1617                             extSession.getLocalSupportedSignatureAlgorithms();
1618 
1619                     constraints = new SSLAlgorithmConstraints(
1620                                     engine, peerSupportedSignAlgs, true);
1621                 } else {
1622                     constraints =
1623                             new SSLAlgorithmConstraints(engine, true);
1624                 }
1625             } else {
1626                 constraints = new SSLAlgorithmConstraints(engine, true);
1627             }
1628 
1629             checkAlgorithmConstraints(chain, constraints, isClient);
1630         }
1631     }
1632 
1633     private void checkAlgorithmConstraints(X509Certificate[] chain,
1634             AlgorithmConstraints constraints,
1635             boolean isClient) throws CertificateException {
1636         try {
1637             // Does the certificate chain end with a trusted certificate?
1638             int checkedLength = chain.length - 1;
1639 
1640             Collection<X509Certificate> trustedCerts = new HashSet<>();
1641             X509Certificate[] certs = tm.getAcceptedIssuers();
1642             if ((certs != null) && (certs.length > 0)){
1643                 Collections.addAll(trustedCerts, certs);
1644             }
1645 
1646             if (trustedCerts.contains(chain[checkedLength])) {
1647                     checkedLength--;
1648             }
1649 
1650             // A forward checker, need to check from trust to target
1651             if (checkedLength >= 0) {
1652                 AlgorithmChecker checker =
1653                     new AlgorithmChecker(constraints, null,
1654                             (isClient ? Validator.VAR_TLS_CLIENT :
1655                                         Validator.VAR_TLS_SERVER));
1656                 checker.init(false);
1657                 for (int i = checkedLength; i >= 0; i--) {
1658                     X509Certificate cert = chain[i];
1659                     // We don't care about the unresolved critical extensions.
1660                     checker.check(cert, Collections.<String>emptySet());
1661                 }
1662             }
1663         } catch (CertPathValidatorException cpve) {
1664             throw new CertificateException(
1665                 "Certificates do not conform to algorithm constraints", cpve);
1666         }
1667     }
1668 }
1669 
1670 // Dummy X509TrustManager implementation, rejects all peer certificates.
1671 // Used if the application did not specify a proper X509TrustManager.
1672 final class DummyX509TrustManager extends X509ExtendedTrustManager
1673             implements X509TrustManager {
1674 
1675     static final X509TrustManager INSTANCE = new DummyX509TrustManager();
1676 
1677     private DummyX509TrustManager() {
1678         // empty
1679     }
1680 
1681     /*
1682      * Given the partial or complete certificate chain
1683      * provided by the peer, build a certificate path
1684      * to a trusted root and return if it can be
1685      * validated and is trusted for client SSL authentication.
1686      * If not, it throws an exception.
1687      */
1688     @Override
1689     public void checkClientTrusted(X509Certificate[] chain, String authType)
1690         throws CertificateException {
1691         throw new CertificateException(
1692             "No X509TrustManager implementation avaiable");
1693     }
1694 
1695     /*
1696      * Given the partial or complete certificate chain
1697      * provided by the peer, build a certificate path
1698      * to a trusted root and return if it can be
1699      * validated and is trusted for server SSL authentication.
1700      * If not, it throws an exception.
1701      */
1702     @Override
1703     public void checkServerTrusted(X509Certificate[] chain, String authType)
1704         throws CertificateException {
1705         throw new CertificateException(
1706             "No X509TrustManager implementation available");
1707     }
1708 
1709     /*
1710      * Return an array of issuer certificates which are trusted
1711      * for authenticating peers.
1712      */
1713     @Override
1714     public X509Certificate[] getAcceptedIssuers() {
1715         return new X509Certificate[0];
1716     }
1717 
1718     @Override
1719     public void checkClientTrusted(X509Certificate[] chain, String authType,
1720                 Socket socket) throws CertificateException {
1721         throw new CertificateException(
1722             "No X509TrustManager implementation available");
1723     }
1724 
1725     @Override
1726     public void checkServerTrusted(X509Certificate[] chain, String authType,
1727             Socket socket) throws CertificateException {
1728         throw new CertificateException(
1729             "No X509TrustManager implementation available");
1730     }
1731 
1732     @Override
1733     public void checkClientTrusted(X509Certificate[] chain, String authType,
1734             SSLEngine engine) throws CertificateException {
1735         throw new CertificateException(
1736             "No X509TrustManager implementation available");
1737     }
1738 
1739     @Override
1740     public void checkServerTrusted(X509Certificate[] chain, String authType,
1741             SSLEngine engine) throws CertificateException {
1742         throw new CertificateException(
1743             "No X509TrustManager implementation available");
1744     }
1745 }
1746 
1747 /*
1748  * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
1749  */
1750 final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
1751 
1752     private final X509KeyManager km;
1753 
1754     AbstractKeyManagerWrapper(X509KeyManager km) {
1755         this.km = km;
1756     }
1757 
1758     @Override
1759     public String[] getClientAliases(String keyType, Principal[] issuers) {
1760         return km.getClientAliases(keyType, issuers);
1761     }
1762 
1763     @Override
1764     public String chooseClientAlias(String[] keyType, Principal[] issuers,
1765             Socket socket) {
1766         return km.chooseClientAlias(keyType, issuers, socket);
1767     }
1768 
1769     @Override
1770     public String[] getServerAliases(String keyType, Principal[] issuers) {
1771         return km.getServerAliases(keyType, issuers);
1772     }
1773 
1774     @Override
1775     public String chooseServerAlias(String keyType, Principal[] issuers,
1776             Socket socket) {
1777         return km.chooseServerAlias(keyType, issuers, socket);
1778     }
1779 
1780     @Override
1781     public X509Certificate[] getCertificateChain(String alias) {
1782         return km.getCertificateChain(alias);
1783     }
1784 
1785     @Override
1786     public PrivateKey getPrivateKey(String alias) {
1787         return km.getPrivateKey(alias);
1788     }
1789 
1790     // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
1791     // X509ExtendedKeymanager. It defines them to return null;
1792 }
1793 
1794 
1795 // Dummy X509KeyManager implementation, never returns any certificates/keys.
1796 // Used if the application did not specify a proper X509TrustManager.
1797 final class DummyX509KeyManager extends X509ExtendedKeyManager {
1798 
1799     static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
1800 
1801     private DummyX509KeyManager() {
1802         // empty
1803     }
1804 
1805     /*
1806      * Get the matching aliases for authenticating the client side of a secure
1807      * socket given the public key type and the list of
1808      * certificate issuer authorities recognized by the peer (if any).
1809      */
1810     @Override
1811     public String[] getClientAliases(String keyType, Principal[] issuers) {
1812         return null;
1813     }
1814 
1815     /*
1816      * Choose an alias to authenticate the client side of a secure
1817      * socket given the public key type and the list of
1818      * certificate issuer authorities recognized by the peer (if any).
1819      */
1820     @Override
1821     public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
1822             Socket socket) {
1823         return null;
1824     }
1825 
1826     /*
1827      * Choose an alias to authenticate the client side of an
1828      * engine given the public key type and the list of
1829      * certificate issuer authorities recognized by the peer (if any).
1830      */
1831     @Override
1832     public String chooseEngineClientAlias(
1833             String[] keyTypes, Principal[] issuers, SSLEngine engine) {
1834         return null;
1835     }
1836 
1837     /*
1838      * Get the matching aliases for authenticating the server side of a secure
1839      * socket given the public key type and the list of
1840      * certificate issuer authorities recognized by the peer (if any).
1841      */
1842     @Override
1843     public String[] getServerAliases(String keyType, Principal[] issuers) {
1844         return null;
1845     }
1846 
1847     /*
1848      * Choose an alias to authenticate the server side of a secure
1849      * socket given the public key type and the list of
1850      * certificate issuer authorities recognized by the peer (if any).
1851      */
1852     @Override
1853     public String chooseServerAlias(String keyType, Principal[] issuers,
1854             Socket socket) {
1855         return null;
1856     }
1857 
1858     /*
1859      * Choose an alias to authenticate the server side of an engine
1860      * given the public key type and the list of
1861      * certificate issuer authorities recognized by the peer (if any).
1862      */
1863     @Override
1864     public String chooseEngineServerAlias(
1865             String keyType, Principal[] issuers, SSLEngine engine) {
1866         return null;
1867     }
1868 
1869     /**
1870      * Returns the certificate chain associated with the given alias.
1871      *
1872      * @param alias the alias name
1873      *
1874      * @return the certificate chain (ordered with the user's certificate first
1875      * and the root certificate authority last)
1876      */
1877     @Override
1878     public X509Certificate[] getCertificateChain(String alias) {
1879         return null;
1880     }
1881 
1882     /*
1883      * Returns the key associated with the given alias, using the given
1884      * password to recover it.
1885      *
1886      * @param alias the alias name
1887      *
1888      * @return the requested key
1889      */
1890     @Override
1891     public PrivateKey getPrivateKey(String alias) {
1892         return null;
1893     }
1894 }
--- EOF ---