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