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