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