1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.conscrypt; 19 20 import java.security.KeyManagementException; 21 import java.security.KeyStore; 22 import java.security.KeyStoreException; 23 import java.security.NoSuchAlgorithmException; 24 import java.security.SecureRandom; 25 import java.security.UnrecoverableKeyException; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import javax.crypto.SecretKey; 29 import javax.net.ssl.KeyManager; 30 import javax.net.ssl.KeyManagerFactory; 31 import javax.net.ssl.TrustManager; 32 import javax.net.ssl.TrustManagerFactory; 33 import javax.net.ssl.X509ExtendedKeyManager; 34 import javax.net.ssl.X509KeyManager; 35 import javax.net.ssl.X509TrustManager; 36 import javax.security.auth.x500.X500Principal; 37 38 /** 39 * The instances of this class encapsulate all the info 40 * about enabled cipher suites and protocols, 41 * as well as the information about client/server mode of 42 * ssl socket, whether it require/want client authentication or not, 43 * and controls whether new SSL sessions may be established by this 44 * socket or not. 45 */ 46 final class SSLParametersImpl implements Cloneable { 47 48 // default source of X.509 certificate based authentication keys 49 private static volatile X509KeyManager defaultX509KeyManager; 50 // default source of X.509 certificate based authentication trust decisions 51 private static volatile X509TrustManager defaultX509TrustManager; 52 // default SSL parameters 53 private static volatile SSLParametersImpl defaultParameters; 54 55 // client session context contains the set of reusable 56 // client-side SSL sessions 57 private final ClientSessionContext clientSessionContext; 58 // server session context contains the set of reusable 59 // server-side SSL sessions 60 private final ServerSessionContext serverSessionContext; 61 // source of X.509 certificate based authentication keys or null if not provided 62 private final X509KeyManager x509KeyManager; 63 // source of Pre-Shared Key (PSK) authentication keys or null if not provided. 64 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 65 private final PSKKeyManager pskKeyManager; 66 // source of X.509 certificate based authentication trust decisions or null if not provided 67 private final X509TrustManager x509TrustManager; 68 69 // protocols enabled for SSL connection 70 String[] enabledProtocols; 71 // set to indicate when obsolete protocols are filtered 72 boolean isEnabledProtocolsFiltered; 73 // cipher suites enabled for SSL connection 74 String[] enabledCipherSuites; 75 76 // if the peer with this parameters tuned to work in client mode 77 private boolean client_mode = true; 78 // if the peer with this parameters tuned to require client authentication 79 private boolean need_client_auth = false; 80 // if the peer with this parameters tuned to request client authentication 81 private boolean want_client_auth = false; 82 // if the peer with this parameters allowed to cteate new SSL session 83 private boolean enable_session_creation = true; 84 // Endpoint identification algorithm (e.g., HTTPS) 85 private String endpointIdentificationAlgorithm; 86 // Whether to use the local cipher suites order 87 private boolean useCipherSuitesOrder; 88 89 // client-side only, bypasses the property based configuration, used for tests 90 private boolean ctVerificationEnabled; 91 92 // server-side only. SCT and OCSP data to send to clients which request it 93 byte[] sctExtension; 94 byte[] ocspResponse; 95 96 byte[] applicationProtocols = EmptyArray.BYTE; 97 ApplicationProtocolSelectorAdapter applicationProtocolSelector; 98 boolean useSessionTickets; 99 private Boolean useSni; 100 101 /** 102 * Whether the TLS Channel ID extension is enabled. This field is 103 * server-side only. 104 */ 105 boolean channelIdEnabled; 106 107 /** 108 * Initializes the parameters. Naturally this constructor is used 109 * in SSLContextImpl.engineInit method which directly passes its 110 * parameters. In other words this constructor holds all 111 * the functionality provided by SSLContext.init method. 112 * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[], 113 * SecureRandom)} for more information 114 */ 115 SSLParametersImpl(KeyManager[] kms, TrustManager[] tms, 116 SecureRandom sr, ClientSessionContext clientSessionContext, 117 ServerSessionContext serverSessionContext, String[] protocols) 118 throws KeyManagementException { 119 this.serverSessionContext = serverSessionContext; 120 this.clientSessionContext = clientSessionContext; 121 122 // initialize key managers 123 if (kms == null) { 124 x509KeyManager = getDefaultX509KeyManager(); 125 // There's no default PSK key manager 126 pskKeyManager = null; 127 } else { 128 x509KeyManager = findFirstX509KeyManager(kms); 129 pskKeyManager = findFirstPSKKeyManager(kms); 130 } 131 132 // initialize x509TrustManager 133 if (tms == null) { 134 x509TrustManager = getDefaultX509TrustManager(); 135 } else { 136 x509TrustManager = findFirstX509TrustManager(tms); 137 } 138 139 // initialize the list of cipher suites and protocols enabled by default 140 enabledProtocols = NativeCrypto.checkEnabledProtocols( 141 protocols == null ? NativeCrypto.DEFAULT_PROTOCOLS : protocols).clone(); 142 boolean x509CipherSuitesNeeded = (x509KeyManager != null) || (x509TrustManager != null); 143 boolean pskCipherSuitesNeeded = pskKeyManager != null; 144 enabledCipherSuites = getDefaultCipherSuites( 145 x509CipherSuitesNeeded, pskCipherSuitesNeeded); 146 147 // We ignore the SecureRandom passed in by the caller. The native code below 148 // directly accesses /dev/urandom, which makes it irrelevant. 149 } 150 151 static SSLParametersImpl getDefault() throws KeyManagementException { 152 SSLParametersImpl result = defaultParameters; 153 if (result == null) { 154 // single-check idiom 155 defaultParameters = result = new SSLParametersImpl(null, 156 null, 157 null, 158 new ClientSessionContext(), 159 new ServerSessionContext(), 160 null); 161 } 162 return (SSLParametersImpl) result.clone(); 163 } 164 165 /** 166 * Returns the appropriate session context. 167 */ 168 AbstractSessionContext getSessionContext() { 169 return client_mode ? clientSessionContext : serverSessionContext; 170 } 171 172 /** 173 * @return client session context 174 */ 175 ClientSessionContext getClientSessionContext() { 176 return clientSessionContext; 177 } 178 179 /** 180 * @return X.509 key manager or {@code null} for none. 181 */ 182 X509KeyManager getX509KeyManager() { 183 return x509KeyManager; 184 } 185 186 /** 187 * @return Pre-Shared Key (PSK) key manager or {@code null} for none. 188 */ 189 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 190 PSKKeyManager getPSKKeyManager() { 191 return pskKeyManager; 192 } 193 194 /** 195 * @return X.509 trust manager or {@code null} for none. 196 */ 197 X509TrustManager getX509TrustManager() { 198 return x509TrustManager; 199 } 200 201 /** 202 * @return the names of enabled cipher suites 203 */ 204 String[] getEnabledCipherSuites() { 205 return enabledCipherSuites.clone(); 206 } 207 208 /** 209 * Sets the enabled cipher suites after filtering through OpenSSL. 210 */ 211 void setEnabledCipherSuites(String[] cipherSuites) { 212 enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(cipherSuites).clone(); 213 } 214 215 /** 216 * @return the set of enabled protocols 217 */ 218 String[] getEnabledProtocols() { 219 return enabledProtocols.clone(); 220 } 221 222 /** 223 * Sets the list of available protocols for use in SSL connection. 224 * @throws IllegalArgumentException if {@code protocols == null} 225 */ 226 void setEnabledProtocols(String[] protocols) { 227 if (protocols == null) { 228 throw new IllegalArgumentException("protocols == null"); 229 } 230 String[] filteredProtocols = 231 filterFromProtocols(protocols, NativeCrypto.OBSOLETE_PROTOCOL_SSLV3); 232 isEnabledProtocolsFiltered = protocols.length != filteredProtocols.length; 233 enabledProtocols = NativeCrypto.checkEnabledProtocols(filteredProtocols).clone(); 234 } 235 236 /** 237 * Sets the list of ALPN protocols. 238 * 239 * @param protocols the list of ALPN protocols 240 */ 241 void setApplicationProtocols(String[] protocols) { 242 this.applicationProtocols = SSLUtils.encodeProtocols(protocols); 243 } 244 245 String[] getApplicationProtocols() { 246 return SSLUtils.decodeProtocols(applicationProtocols); 247 } 248 249 /** 250 * Used for server-mode only. Sets or clears the application-provided ALPN protocol selector. 251 * If set, will override the protocol list provided by {@link #setApplicationProtocols(String[])}. 252 */ 253 void setApplicationProtocolSelector(ApplicationProtocolSelectorAdapter applicationProtocolSelector) { 254 this.applicationProtocolSelector = applicationProtocolSelector; 255 } 256 257 /** 258 * Tunes the peer holding this parameters to work in client mode. 259 * @param mode if the peer is configured to work in client mode 260 */ 261 void setUseClientMode(boolean mode) { 262 client_mode = mode; 263 } 264 265 /** 266 * Returns the value indicating if the parameters configured to work 267 * in client mode. 268 */ 269 boolean getUseClientMode() { 270 return client_mode; 271 } 272 273 /** 274 * Tunes the peer holding this parameters to require client authentication 275 */ 276 void setNeedClientAuth(boolean need) { 277 need_client_auth = need; 278 // reset the want_client_auth setting 279 want_client_auth = false; 280 } 281 282 /** 283 * Returns the value indicating if the peer with this parameters tuned 284 * to require client authentication 285 */ 286 boolean getNeedClientAuth() { 287 return need_client_auth; 288 } 289 290 /** 291 * Tunes the peer holding this parameters to request client authentication 292 */ 293 void setWantClientAuth(boolean want) { 294 want_client_auth = want; 295 // reset the need_client_auth setting 296 need_client_auth = false; 297 } 298 299 /** 300 * Returns the value indicating if the peer with this parameters 301 * tuned to request client authentication 302 */ 303 boolean getWantClientAuth() { 304 return want_client_auth; 305 } 306 307 /** 308 * Allows/disallows the peer holding this parameters to 309 * create new SSL session 310 */ 311 void setEnableSessionCreation(boolean flag) { 312 enable_session_creation = flag; 313 } 314 315 /** 316 * Returns the value indicating if the peer with this parameters 317 * allowed to cteate new SSL session 318 */ 319 boolean getEnableSessionCreation() { 320 return enable_session_creation; 321 } 322 323 void setUseSessionTickets(boolean useSessionTickets) { 324 this.useSessionTickets = useSessionTickets; 325 } 326 327 /** 328 * Whether connections using this SSL connection should use the TLS 329 * extension Server Name Indication (SNI). 330 */ 331 void setUseSni(boolean flag) { 332 useSni = flag; 333 } 334 335 /** 336 * Returns whether connections using this SSL connection should use the TLS 337 * extension Server Name Indication (SNI). 338 */ 339 boolean getUseSni() { 340 return useSni != null ? useSni : isSniEnabledByDefault(); 341 } 342 343 /** 344 * For testing only. 345 */ 346 void setCTVerificationEnabled(boolean enabled) { 347 ctVerificationEnabled = enabled; 348 } 349 350 /** 351 * For testing only. 352 */ 353 void setSCTExtension(byte[] extension) { 354 sctExtension = extension; 355 } 356 357 /** 358 * For testing only. 359 */ 360 void setOCSPResponse(byte[] response) { 361 ocspResponse = response; 362 } 363 364 byte[] getOCSPResponse() { 365 return ocspResponse; 366 } 367 368 /** 369 * This filters {@code obsoleteProtocol} from the list of {@code protocols} 370 * down to help with app compatibility. 371 */ 372 private static String[] filterFromProtocols(String[] protocols, String obsoleteProtocol) { 373 if (protocols.length == 1 && obsoleteProtocol.equals(protocols[0])) { 374 return EMPTY_STRING_ARRAY; 375 } 376 377 ArrayList<String> newProtocols = new ArrayList<String>(); 378 for (String protocol : protocols) { 379 if (!obsoleteProtocol.equals(protocol)) { 380 newProtocols.add(protocol); 381 } 382 } 383 return newProtocols.toArray(EMPTY_STRING_ARRAY); 384 } 385 386 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 387 388 /** 389 * Returns whether Server Name Indication (SNI) is enabled by default for 390 * sockets. For more information on SNI, see RFC 6066 section 3. 391 */ 392 private boolean isSniEnabledByDefault() { 393 try { 394 String enableSNI = System.getProperty("jsse.enableSNIExtension", "true"); 395 if ("true".equalsIgnoreCase(enableSNI)) { 396 return true; 397 } else if ("false".equalsIgnoreCase(enableSNI)) { 398 return false; 399 } else { 400 throw new RuntimeException( 401 "Can only set \"jsse.enableSNIExtension\" to \"true\" or \"false\""); 402 } 403 } catch (SecurityException e) { 404 return true; 405 } 406 } 407 408 /** 409 * For abstracting the X509KeyManager calls between 410 * {@link X509KeyManager#chooseClientAlias(String[], java.security.Principal[], java.net.Socket)} 411 * and 412 * {@link X509ExtendedKeyManager#chooseEngineClientAlias(String[], java.security.Principal[], javax.net.ssl.SSLEngine)} 413 */ 414 interface AliasChooser { 415 String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 416 String[] keyTypes); 417 418 String chooseServerAlias(X509KeyManager keyManager, String keyType); 419 } 420 421 /** 422 * For abstracting the {@code PSKKeyManager} calls between those taking an {@code SSLSocket} and 423 * those taking an {@code SSLEngine}. 424 */ 425 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 426 interface PSKCallbacks { 427 String chooseServerPSKIdentityHint(PSKKeyManager keyManager); 428 String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint); 429 SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity); 430 } 431 432 /** 433 * Returns the clone of this object. 434 * @return the clone. 435 */ 436 @Override 437 protected Object clone() { 438 try { 439 return super.clone(); 440 } catch (CloneNotSupportedException e) { 441 throw new AssertionError(e); 442 } 443 } 444 445 private static X509KeyManager getDefaultX509KeyManager() throws KeyManagementException { 446 X509KeyManager result = defaultX509KeyManager; 447 if (result == null) { 448 // single-check idiom 449 defaultX509KeyManager = result = createDefaultX509KeyManager(); 450 } 451 return result; 452 } 453 private static X509KeyManager createDefaultX509KeyManager() throws KeyManagementException { 454 try { 455 String algorithm = KeyManagerFactory.getDefaultAlgorithm(); 456 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 457 kmf.init(null, null); 458 KeyManager[] kms = kmf.getKeyManagers(); 459 X509KeyManager result = findFirstX509KeyManager(kms); 460 if (result == null) { 461 throw new KeyManagementException("No X509KeyManager among default KeyManagers: " 462 + Arrays.toString(kms)); 463 } 464 return result; 465 } catch (NoSuchAlgorithmException e) { 466 throw new KeyManagementException(e); 467 } catch (KeyStoreException e) { 468 throw new KeyManagementException(e); 469 } catch (UnrecoverableKeyException e) { 470 throw new KeyManagementException(e); 471 } 472 } 473 474 /** 475 * Finds the first {@link X509KeyManager} element in the provided array. 476 * 477 * @return the first {@code X509KeyManager} or {@code null} if not found. 478 */ 479 private static X509KeyManager findFirstX509KeyManager(KeyManager[] kms) { 480 for (KeyManager km : kms) { 481 if (km instanceof X509KeyManager) { 482 return (X509KeyManager)km; 483 } 484 } 485 return null; 486 } 487 488 /** 489 * Finds the first {@link PSKKeyManager} element in the provided array. 490 * 491 * @return the first {@code PSKKeyManager} or {@code null} if not found. 492 */ 493 @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package 494 private static PSKKeyManager findFirstPSKKeyManager(KeyManager[] kms) { 495 for (KeyManager km : kms) { 496 if (km instanceof PSKKeyManager) { 497 return (PSKKeyManager)km; 498 } else if (km != null) { 499 try { 500 return DuckTypedPSKKeyManager.getInstance(km); 501 } catch (NoSuchMethodException ignored) {} 502 } 503 } 504 return null; 505 } 506 507 /** 508 * Gets the default X.509 trust manager. 509 */ 510 static X509TrustManager getDefaultX509TrustManager() 511 throws KeyManagementException { 512 X509TrustManager result = defaultX509TrustManager; 513 if (result == null) { 514 // single-check idiom 515 defaultX509TrustManager = result = createDefaultX509TrustManager(); 516 } 517 return result; 518 } 519 520 private static X509TrustManager createDefaultX509TrustManager() 521 throws KeyManagementException { 522 try { 523 String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 524 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 525 tmf.init((KeyStore) null); 526 TrustManager[] tms = tmf.getTrustManagers(); 527 X509TrustManager trustManager = findFirstX509TrustManager(tms); 528 if (trustManager == null) { 529 throw new KeyManagementException( 530 "No X509TrustManager in among default TrustManagers: " 531 + Arrays.toString(tms)); 532 } 533 return trustManager; 534 } catch (NoSuchAlgorithmException e) { 535 throw new KeyManagementException(e); 536 } catch (KeyStoreException e) { 537 throw new KeyManagementException(e); 538 } 539 } 540 541 /** 542 * Finds the first {@link X509TrustManager} element in the provided array. 543 * 544 * @return the first {@code X509ExtendedTrustManager} or 545 * {@code X509TrustManager} or {@code null} if not found. 546 */ 547 private static X509TrustManager findFirstX509TrustManager(TrustManager[] tms) { 548 for (TrustManager tm : tms) { 549 if (tm instanceof X509TrustManager) { 550 return (X509TrustManager) tm; 551 } 552 } 553 return null; 554 } 555 556 String getEndpointIdentificationAlgorithm() { 557 return endpointIdentificationAlgorithm; 558 } 559 560 void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm) { 561 this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; 562 } 563 564 boolean getUseCipherSuitesOrder() { 565 return useCipherSuitesOrder; 566 } 567 568 void setUseCipherSuitesOrder(boolean useCipherSuitesOrder) { 569 this.useCipherSuitesOrder = useCipherSuitesOrder; 570 } 571 572 private static String[] getDefaultCipherSuites( 573 boolean x509CipherSuitesNeeded, 574 boolean pskCipherSuitesNeeded) { 575 if (x509CipherSuitesNeeded) { 576 // X.509 based cipher suites need to be listed. 577 if (pskCipherSuitesNeeded) { 578 // Both X.509 and PSK based cipher suites need to be listed. Because TLS-PSK is not 579 // normally used, we assume that when PSK cipher suites are requested here they 580 // should be preferred over other cipher suites. Thus, we give PSK cipher suites 581 // higher priority than X.509 cipher suites. 582 // NOTE: There are cipher suites that use both X.509 and PSK (e.g., those based on 583 // RSA_PSK key exchange). However, these cipher suites are not currently supported. 584 return concat( 585 NativeCrypto.DEFAULT_PSK_CIPHER_SUITES, 586 NativeCrypto.DEFAULT_X509_CIPHER_SUITES, 587 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 588 } else { 589 // Only X.509 cipher suites need to be listed. 590 return concat( 591 NativeCrypto.DEFAULT_X509_CIPHER_SUITES, 592 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 593 } 594 } else if (pskCipherSuitesNeeded) { 595 // Only PSK cipher suites need to be listed. 596 return concat( 597 NativeCrypto.DEFAULT_PSK_CIPHER_SUITES, 598 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 599 } else { 600 // Neither X.509 nor PSK cipher suites need to be listed. 601 return new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}; 602 } 603 } 604 605 private static String[] concat(String[]... arrays) { 606 int resultLength = 0; 607 for (String[] array : arrays) { 608 resultLength += array.length; 609 } 610 String[] result = new String[resultLength]; 611 int resultOffset = 0; 612 for (String[] array : arrays) { 613 System.arraycopy(array, 0, result, resultOffset, array.length); 614 resultOffset += array.length; 615 } 616 return result; 617 } 618 619 /** 620 * Check if SCT verification is enforced for a given hostname. 621 */ 622 boolean isCTVerificationEnabled(String hostname) { 623 if (hostname == null) { 624 return false; 625 } 626 627 // Bypass the check. This is used for testing only 628 if (ctVerificationEnabled) { 629 return true; 630 } 631 return Platform.isCTVerificationRequired(hostname); 632 } 633 } 634