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 org.conscrypt.ct.CTVerifier; 21 import org.conscrypt.ct.CTLogStoreImpl; 22 import org.conscrypt.util.EmptyArray; 23 import java.io.IOException; 24 import java.io.UnsupportedEncodingException; 25 import java.security.InvalidKeyException; 26 import java.security.KeyManagementException; 27 import java.security.KeyStore; 28 import java.security.KeyStoreException; 29 import java.security.NoSuchAlgorithmException; 30 import java.security.PrivateKey; 31 import java.security.PublicKey; 32 import java.security.SecureRandom; 33 import java.security.Security; 34 import java.security.UnrecoverableKeyException; 35 import java.security.cert.CertificateEncodingException; 36 import java.security.cert.X509Certificate; 37 import java.util.Arrays; 38 import java.util.Collections; 39 import java.util.HashSet; 40 import java.util.List; 41 import java.util.Set; 42 import javax.crypto.SecretKey; 43 import javax.net.ssl.KeyManager; 44 import javax.net.ssl.KeyManagerFactory; 45 import javax.net.ssl.SSLException; 46 import javax.net.ssl.SSLSession; 47 import javax.net.ssl.SSLHandshakeException; 48 import javax.net.ssl.TrustManager; 49 import javax.net.ssl.TrustManagerFactory; 50 import javax.net.ssl.X509ExtendedKeyManager; 51 import javax.net.ssl.X509KeyManager; 52 import javax.net.ssl.X509TrustManager; 53 import javax.security.auth.x500.X500Principal; 54 55 /** 56 * The instances of this class encapsulate all the info 57 * about enabled cipher suites and protocols, 58 * as well as the information about client/server mode of 59 * ssl socket, whether it require/want client authentication or not, 60 * and controls whether new SSL sessions may be established by this 61 * socket or not. 62 */ 63 public class SSLParametersImpl implements Cloneable { 64 65 // default source of X.509 certificate based authentication keys 66 private static volatile X509KeyManager defaultX509KeyManager; 67 // default source of X.509 certificate based authentication trust decisions 68 private static volatile X509TrustManager defaultX509TrustManager; 69 // default source of random numbers 70 private static volatile SecureRandom defaultSecureRandom; 71 // default SSL parameters 72 private static volatile SSLParametersImpl defaultParameters; 73 // default CT Verifier 74 private static volatile CTVerifier defaultCTVerifier; 75 76 // client session context contains the set of reusable 77 // client-side SSL sessions 78 private final ClientSessionContext clientSessionContext; 79 // server session context contains the set of reusable 80 // server-side SSL sessions 81 private final ServerSessionContext serverSessionContext; 82 // source of X.509 certificate based authentication keys or null if not provided 83 private final X509KeyManager x509KeyManager; 84 // source of Pre-Shared Key (PSK) authentication keys or null if not provided. 85 private final PSKKeyManager pskKeyManager; 86 // source of X.509 certificate based authentication trust decisions or null if not provided 87 private final X509TrustManager x509TrustManager; 88 // source of random numbers 89 private SecureRandom secureRandom; 90 91 // protocols enabled for SSL connection 92 private String[] enabledProtocols; 93 // cipher suites enabled for SSL connection 94 private String[] enabledCipherSuites; 95 96 // if the peer with this parameters tuned to work in client mode 97 private boolean client_mode = true; 98 // if the peer with this parameters tuned to require client authentication 99 private boolean need_client_auth = false; 100 // if the peer with this parameters tuned to request client authentication 101 private boolean want_client_auth = false; 102 // if the peer with this parameters allowed to cteate new SSL session 103 private boolean enable_session_creation = true; 104 // Endpoint identification algorithm (e.g., HTTPS) 105 private String endpointIdentificationAlgorithm; 106 // Whether to use the local cipher suites order 107 private boolean useCipherSuitesOrder; 108 109 // client-side only, bypasses the property based configuration, used for tests 110 private boolean ctVerificationEnabled; 111 // client-side only, if null defaultCTVerifier is used instead. Used for tests 112 private CTVerifier ctVerifier; 113 114 // server-side only. SCT and OCSP data to send to clients which request it 115 private byte[] sctExtension; 116 private byte[] ocspResponse; 117 118 byte[] npnProtocols; 119 byte[] alpnProtocols; 120 boolean useSessionTickets; 121 private Boolean useSni; 122 123 /** 124 * Whether the TLS Channel ID extension is enabled. This field is 125 * server-side only. 126 */ 127 boolean channelIdEnabled; 128 129 /** 130 * Initializes the parameters. Naturally this constructor is used 131 * in SSLContextImpl.engineInit method which directly passes its 132 * parameters. In other words this constructor holds all 133 * the functionality provided by SSLContext.init method. 134 * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[], 135 * SecureRandom)} for more information 136 */ SSLParametersImpl(KeyManager[] kms, TrustManager[] tms, SecureRandom sr, ClientSessionContext clientSessionContext, ServerSessionContext serverSessionContext, String[] protocols)137 protected SSLParametersImpl(KeyManager[] kms, TrustManager[] tms, 138 SecureRandom sr, ClientSessionContext clientSessionContext, 139 ServerSessionContext serverSessionContext, String[] protocols) 140 throws KeyManagementException { 141 this.serverSessionContext = serverSessionContext; 142 this.clientSessionContext = clientSessionContext; 143 144 // initialize key managers 145 if (kms == null) { 146 x509KeyManager = getDefaultX509KeyManager(); 147 // There's no default PSK key manager 148 pskKeyManager = null; 149 } else { 150 x509KeyManager = findFirstX509KeyManager(kms); 151 pskKeyManager = findFirstPSKKeyManager(kms); 152 } 153 154 // initialize x509TrustManager 155 if (tms == null) { 156 x509TrustManager = getDefaultX509TrustManager(); 157 } else { 158 x509TrustManager = findFirstX509TrustManager(tms); 159 } 160 161 // initialize secure random 162 // We simply use the SecureRandom passed in by the caller. If it's 163 // null, we don't replace it by a new instance. The native code below 164 // then directly accesses /dev/urandom. Not the most elegant solution, 165 // but faster than going through the SecureRandom object. 166 secureRandom = sr; 167 168 // initialize the list of cipher suites and protocols enabled by default 169 enabledProtocols = NativeCrypto.checkEnabledProtocols( 170 protocols == null ? NativeCrypto.DEFAULT_PROTOCOLS : protocols).clone(); 171 boolean x509CipherSuitesNeeded = (x509KeyManager != null) || (x509TrustManager != null); 172 boolean pskCipherSuitesNeeded = pskKeyManager != null; 173 enabledCipherSuites = getDefaultCipherSuites( 174 x509CipherSuitesNeeded, pskCipherSuitesNeeded); 175 } 176 getDefault()177 protected static SSLParametersImpl getDefault() throws KeyManagementException { 178 SSLParametersImpl result = defaultParameters; 179 if (result == null) { 180 // single-check idiom 181 defaultParameters = result = new SSLParametersImpl(null, 182 null, 183 null, 184 new ClientSessionContext(), 185 new ServerSessionContext(), 186 null); 187 } 188 return (SSLParametersImpl) result.clone(); 189 } 190 191 /** 192 * Returns the appropriate session context. 193 */ getSessionContext()194 public AbstractSessionContext getSessionContext() { 195 return client_mode ? clientSessionContext : serverSessionContext; 196 } 197 198 /** 199 * @return server session context 200 */ getServerSessionContext()201 protected ServerSessionContext getServerSessionContext() { 202 return serverSessionContext; 203 } 204 205 /** 206 * @return client session context 207 */ getClientSessionContext()208 protected ClientSessionContext getClientSessionContext() { 209 return clientSessionContext; 210 } 211 212 /** 213 * @return X.509 key manager or {@code null} for none. 214 */ getX509KeyManager()215 protected X509KeyManager getX509KeyManager() { 216 return x509KeyManager; 217 } 218 219 /** 220 * @return Pre-Shared Key (PSK) key manager or {@code null} for none. 221 */ getPSKKeyManager()222 protected PSKKeyManager getPSKKeyManager() { 223 return pskKeyManager; 224 } 225 226 /** 227 * @return X.509 trust manager or {@code null} for none. 228 */ getX509TrustManager()229 protected X509TrustManager getX509TrustManager() { 230 return x509TrustManager; 231 } 232 233 /** 234 * @return secure random 235 */ getSecureRandom()236 protected SecureRandom getSecureRandom() { 237 if (secureRandom != null) { 238 return secureRandom; 239 } 240 SecureRandom result = defaultSecureRandom; 241 if (result == null) { 242 // single-check idiom 243 defaultSecureRandom = result = new SecureRandom(); 244 } 245 secureRandom = result; 246 return secureRandom; 247 } 248 249 /** 250 * @return the secure random member reference, even it is null 251 */ getSecureRandomMember()252 protected SecureRandom getSecureRandomMember() { 253 return secureRandom; 254 } 255 256 /** 257 * @return certificate transparency verifier 258 */ getCTVerifier()259 protected CTVerifier getCTVerifier() { 260 if (ctVerifier != null) { 261 return ctVerifier; 262 } 263 CTVerifier result = defaultCTVerifier; 264 if (result == null) { 265 // single-check idiom 266 defaultCTVerifier = result = new CTVerifier(new CTLogStoreImpl()); 267 } 268 ctVerifier = result; 269 return ctVerifier; 270 } 271 272 /** 273 * @return the names of enabled cipher suites 274 */ getEnabledCipherSuites()275 protected String[] getEnabledCipherSuites() { 276 return enabledCipherSuites.clone(); 277 } 278 279 /** 280 * Sets the enabled cipher suites after filtering through OpenSSL. 281 */ setEnabledCipherSuites(String[] cipherSuites)282 protected void setEnabledCipherSuites(String[] cipherSuites) { 283 enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(cipherSuites).clone(); 284 } 285 286 /** 287 * @return the set of enabled protocols 288 */ getEnabledProtocols()289 protected String[] getEnabledProtocols() { 290 return enabledProtocols.clone(); 291 } 292 293 /** 294 * Sets the set of available protocols for use in SSL connection. 295 * @param protocols String[] 296 */ setEnabledProtocols(String[] protocols)297 protected void setEnabledProtocols(String[] protocols) { 298 enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols).clone(); 299 } 300 301 /** 302 * Tunes the peer holding this parameters to work in client mode. 303 * @param mode if the peer is configured to work in client mode 304 */ setUseClientMode(boolean mode)305 protected void setUseClientMode(boolean mode) { 306 client_mode = mode; 307 } 308 309 /** 310 * Returns the value indicating if the parameters configured to work 311 * in client mode. 312 */ getUseClientMode()313 protected boolean getUseClientMode() { 314 return client_mode; 315 } 316 317 /** 318 * Tunes the peer holding this parameters to require client authentication 319 */ setNeedClientAuth(boolean need)320 protected void setNeedClientAuth(boolean need) { 321 need_client_auth = need; 322 // reset the want_client_auth setting 323 want_client_auth = false; 324 } 325 326 /** 327 * Returns the value indicating if the peer with this parameters tuned 328 * to require client authentication 329 */ getNeedClientAuth()330 protected boolean getNeedClientAuth() { 331 return need_client_auth; 332 } 333 334 /** 335 * Tunes the peer holding this parameters to request client authentication 336 */ setWantClientAuth(boolean want)337 protected void setWantClientAuth(boolean want) { 338 want_client_auth = want; 339 // reset the need_client_auth setting 340 need_client_auth = false; 341 } 342 343 /** 344 * Returns the value indicating if the peer with this parameters 345 * tuned to request client authentication 346 */ getWantClientAuth()347 protected boolean getWantClientAuth() { 348 return want_client_auth; 349 } 350 351 /** 352 * Allows/disallows the peer holding this parameters to 353 * create new SSL session 354 */ setEnableSessionCreation(boolean flag)355 protected void setEnableSessionCreation(boolean flag) { 356 enable_session_creation = flag; 357 } 358 359 /** 360 * Returns the value indicating if the peer with this parameters 361 * allowed to cteate new SSL session 362 */ getEnableSessionCreation()363 protected boolean getEnableSessionCreation() { 364 return enable_session_creation; 365 } 366 367 /** 368 * Whether connections using this SSL connection should use the TLS 369 * extension Server Name Indication (SNI). 370 */ setUseSni(boolean flag)371 protected void setUseSni(boolean flag) { 372 useSni = Boolean.valueOf(flag); 373 } 374 375 /** 376 * Returns whether connections using this SSL connection should use the TLS 377 * extension Server Name Indication (SNI). 378 */ getUseSni()379 protected boolean getUseSni() { 380 return useSni != null ? useSni.booleanValue() : isSniEnabledByDefault(); 381 } 382 setCTVerifier(CTVerifier verifier)383 public void setCTVerifier(CTVerifier verifier) { 384 ctVerifier = verifier; 385 } 386 setCTVerificationEnabled(boolean enabled)387 public void setCTVerificationEnabled(boolean enabled) { 388 ctVerificationEnabled = enabled; 389 } 390 setSCTExtension(byte[] extension)391 public void setSCTExtension(byte[] extension) { 392 sctExtension = extension; 393 } 394 setOCSPResponse(byte[] response)395 public void setOCSPResponse(byte[] response) { 396 ocspResponse = response; 397 } 398 encodeIssuerX509Principals(X509Certificate[] certificates)399 static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates) 400 throws CertificateEncodingException { 401 byte[][] principalBytes = new byte[certificates.length][]; 402 for (int i = 0; i < certificates.length; i++) { 403 principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded(); 404 } 405 return principalBytes; 406 } 407 408 /** 409 * Return a possibly null array of X509Certificates given the possibly null 410 * array of DER encoded bytes. 411 */ createCertChain(long[] certificateRefs)412 private static OpenSSLX509Certificate[] createCertChain(long[] certificateRefs) 413 throws IOException { 414 if (certificateRefs == null) { 415 return null; 416 } 417 OpenSSLX509Certificate[] certificates = new OpenSSLX509Certificate[certificateRefs.length]; 418 for (int i = 0; i < certificateRefs.length; i++) { 419 certificates[i] = new OpenSSLX509Certificate(certificateRefs[i]); 420 } 421 return certificates; 422 } 423 getSessionToReuse(long sslNativePointer, String hostname, int port)424 OpenSSLSessionImpl getSessionToReuse(long sslNativePointer, String hostname, int port) 425 throws SSLException { 426 OpenSSLSessionImpl sessionToReuse = null; 427 428 if (client_mode) { 429 // look for client session to reuse 430 SSLSession cachedSession = getCachedClientSession(clientSessionContext, hostname, port); 431 if (cachedSession != null) { 432 if (cachedSession instanceof OpenSSLSessionImpl) { 433 sessionToReuse = (OpenSSLSessionImpl) cachedSession; 434 } else if (cachedSession instanceof OpenSSLExtendedSessionImpl) { 435 sessionToReuse = ((OpenSSLExtendedSessionImpl) cachedSession).getDelegate(); 436 } 437 438 if (sessionToReuse != null) { 439 NativeCrypto.SSL_set_session(sslNativePointer, 440 sessionToReuse.sslSessionNativePointer); 441 } 442 } 443 } 444 445 return sessionToReuse; 446 } 447 setTlsChannelId(long sslNativePointer, OpenSSLKey channelIdPrivateKey)448 void setTlsChannelId(long sslNativePointer, OpenSSLKey channelIdPrivateKey) 449 throws SSLHandshakeException, SSLException { 450 // TLS Channel ID 451 if (channelIdEnabled) { 452 if (client_mode) { 453 // Client-side TLS Channel ID 454 if (channelIdPrivateKey == null) { 455 throw new SSLHandshakeException("Invalid TLS channel ID key specified"); 456 } 457 NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, 458 channelIdPrivateKey.getNativeRef()); 459 } else { 460 // Server-side TLS Channel ID 461 NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer); 462 } 463 } 464 } 465 setCertificate(long sslNativePointer, String alias)466 void setCertificate(long sslNativePointer, String alias) throws CertificateEncodingException, 467 SSLException { 468 if (alias == null) { 469 return; 470 } 471 X509KeyManager keyManager = getX509KeyManager(); 472 if (keyManager == null) { 473 return; 474 } 475 PrivateKey privateKey = keyManager.getPrivateKey(alias); 476 if (privateKey == null) { 477 return; 478 } 479 X509Certificate[] certificates = keyManager.getCertificateChain(alias); 480 if (certificates == null) { 481 return; 482 } 483 PublicKey publicKey = (certificates.length > 0) ? certificates[0].getPublicKey() : null; 484 485 /* 486 * Make sure we keep a reference to the OpenSSLX509Certificate by using 487 * this array. Otherwise, if they're not OpenSSLX509Certificate 488 * instances originally, they may be garbage collected before we 489 * complete our JNI calls. 490 */ 491 OpenSSLX509Certificate[] openSslCerts = new OpenSSLX509Certificate[certificates.length]; 492 long[] x509refs = new long[certificates.length]; 493 for (int i = 0; i < certificates.length; i++) { 494 OpenSSLX509Certificate openSslCert = OpenSSLX509Certificate 495 .fromCertificate(certificates[i]); 496 openSslCerts[i] = openSslCert; 497 x509refs[i] = openSslCert.getContext(); 498 } 499 500 // Note that OpenSSL says to use SSL_use_certificate before 501 // SSL_use_PrivateKey. 502 NativeCrypto.SSL_use_certificate(sslNativePointer, x509refs); 503 504 final OpenSSLKey key; 505 try { 506 key = OpenSSLKey.fromPrivateKeyForTLSStackOnly(privateKey, publicKey); 507 NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getNativeRef()); 508 } catch (InvalidKeyException e) { 509 throw new SSLException(e); 510 } 511 512 // We may not have access to all the information to check the private key 513 // if it's a wrapped platform key, so skip this check. 514 if (!key.isWrapped()) { 515 // Makes sure the set PrivateKey and X509Certificate refer to the same 516 // key by comparing the public values. 517 NativeCrypto.SSL_check_private_key(sslNativePointer); 518 } 519 } 520 setSSLParameters(long sslCtxNativePointer, long sslNativePointer, AliasChooser chooser, PSKCallbacks pskCallbacks, String sniHostname)521 void setSSLParameters(long sslCtxNativePointer, long sslNativePointer, AliasChooser chooser, 522 PSKCallbacks pskCallbacks, String sniHostname) throws SSLException, IOException { 523 if (npnProtocols != null) { 524 NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 525 } 526 527 if (client_mode && alpnProtocols != null) { 528 NativeCrypto.SSL_set_alpn_protos(sslNativePointer, alpnProtocols); 529 } 530 531 NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 532 NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 533 534 // setup server certificates and private keys. 535 // clients will receive a call back to request certificates. 536 if (!client_mode) { 537 Set<String> keyTypes = new HashSet<String>(); 538 for (long sslCipherNativePointer : NativeCrypto.SSL_get_ciphers(sslNativePointer)) { 539 String keyType = getServerX509KeyType(sslCipherNativePointer); 540 if (keyType != null) { 541 keyTypes.add(keyType); 542 } 543 } 544 X509KeyManager keyManager = getX509KeyManager(); 545 if (keyManager != null) { 546 for (String keyType : keyTypes) { 547 try { 548 setCertificate(sslNativePointer, 549 chooser.chooseServerAlias(x509KeyManager, keyType)); 550 } catch (CertificateEncodingException e) { 551 throw new IOException(e); 552 } 553 } 554 } 555 556 if (sctExtension != null) { 557 NativeCrypto.SSL_CTX_set_signed_cert_timestamp_list(sslCtxNativePointer, 558 sctExtension); 559 } 560 561 if (ocspResponse != null) { 562 NativeCrypto.SSL_CTX_set_ocsp_response(sslCtxNativePointer, ocspResponse); 563 } 564 565 NativeCrypto.SSL_set_options(sslNativePointer, 566 NativeConstants.SSL_OP_CIPHER_SERVER_PREFERENCE); 567 } 568 569 // Enable Pre-Shared Key (PSK) key exchange if requested 570 PSKKeyManager pskKeyManager = getPSKKeyManager(); 571 if (pskKeyManager != null) { 572 boolean pskEnabled = false; 573 for (String enabledCipherSuite : enabledCipherSuites) { 574 if ((enabledCipherSuite != null) && (enabledCipherSuite.contains("PSK"))) { 575 pskEnabled = true; 576 break; 577 } 578 } 579 if (pskEnabled) { 580 if (client_mode) { 581 NativeCrypto.set_SSL_psk_client_callback_enabled(sslNativePointer, true); 582 } else { 583 NativeCrypto.set_SSL_psk_server_callback_enabled(sslNativePointer, true); 584 String identityHint = pskCallbacks.chooseServerPSKIdentityHint(pskKeyManager); 585 NativeCrypto.SSL_use_psk_identity_hint(sslNativePointer, identityHint); 586 } 587 } 588 } 589 590 if (useSessionTickets) { 591 NativeCrypto.SSL_clear_options(sslNativePointer, NativeConstants.SSL_OP_NO_TICKET); 592 } 593 if (getUseSni() && AddressUtils.isValidSniHostname(sniHostname)) { 594 NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, sniHostname); 595 } 596 597 // BEAST attack mitigation (1/n-1 record splitting for CBC cipher suites 598 // with TLSv1 and SSLv3). 599 NativeCrypto.SSL_set_mode(sslNativePointer, NativeConstants.SSL_MODE_CBC_RECORD_SPLITTING); 600 601 boolean enableSessionCreation = getEnableSessionCreation(); 602 if (!enableSessionCreation) { 603 NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, enableSessionCreation); 604 } 605 } 606 607 /** 608 * Returns whether Server Name Indication (SNI) is enabled by default for 609 * sockets. For more information on SNI, see RFC 6066 section 3. 610 */ isSniEnabledByDefault()611 private boolean isSniEnabledByDefault() { 612 String enableSNI = System.getProperty("jsse.enableSNIExtension", "true"); 613 if ("true".equalsIgnoreCase(enableSNI)) { 614 return true; 615 } else if ("false".equalsIgnoreCase(enableSNI)) { 616 return false; 617 } else { 618 throw new RuntimeException( 619 "Can only set \"jsse.enableSNIExtension\" to \"true\" or \"false\""); 620 } 621 } 622 setCertificateValidation(long sslNativePointer)623 void setCertificateValidation(long sslNativePointer) throws IOException { 624 // setup peer certificate verification 625 if (!client_mode) { 626 // needing client auth takes priority... 627 boolean certRequested; 628 if (getNeedClientAuth()) { 629 NativeCrypto.SSL_set_verify(sslNativePointer, 630 NativeCrypto.SSL_VERIFY_PEER 631 | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 632 certRequested = true; 633 // ... over just wanting it... 634 } else if (getWantClientAuth()) { 635 NativeCrypto.SSL_set_verify(sslNativePointer, NativeCrypto.SSL_VERIFY_PEER); 636 certRequested = true; 637 // ... and we must disable verification if we don't want client auth. 638 } else { 639 NativeCrypto.SSL_set_verify(sslNativePointer, NativeCrypto.SSL_VERIFY_NONE); 640 certRequested = false; 641 } 642 643 if (certRequested) { 644 X509TrustManager trustManager = getX509TrustManager(); 645 X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 646 if (issuers != null && issuers.length != 0) { 647 byte[][] issuersBytes; 648 try { 649 issuersBytes = encodeIssuerX509Principals(issuers); 650 } catch (CertificateEncodingException e) { 651 throw new IOException("Problem encoding principals", e); 652 } 653 NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 654 } 655 } 656 } 657 } 658 setupSession(long sslSessionNativePointer, long sslNativePointer, final OpenSSLSessionImpl sessionToReuse, String hostname, int port, boolean handshakeCompleted)659 OpenSSLSessionImpl setupSession(long sslSessionNativePointer, long sslNativePointer, 660 final OpenSSLSessionImpl sessionToReuse, String hostname, int port, 661 boolean handshakeCompleted) throws IOException { 662 OpenSSLSessionImpl sslSession = null; 663 if (sessionToReuse != null && NativeCrypto.SSL_session_reused(sslNativePointer)) { 664 sslSession = sessionToReuse; 665 sslSession.lastAccessedTime = System.currentTimeMillis(); 666 NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 667 } else { 668 if (!getEnableSessionCreation()) { 669 // Should have been prevented by 670 // NativeCrypto.SSL_set_session_creation_enabled 671 throw new IllegalStateException("SSL Session may not be created"); 672 } 673 X509Certificate[] localCertificates = createCertChain(NativeCrypto 674 .SSL_get_certificate(sslNativePointer)); 675 X509Certificate[] peerCertificates = createCertChain(NativeCrypto 676 .SSL_get_peer_cert_chain(sslNativePointer)); 677 sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 678 peerCertificates, hostname, port, getSessionContext()); 679 // if not, putSession later in handshakeCompleted() callback 680 if (handshakeCompleted) { 681 getSessionContext().putSession(sslSession); 682 } 683 } 684 return sslSession; 685 } 686 chooseClientCertificate(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals, long sslNativePointer, AliasChooser chooser)687 void chooseClientCertificate(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals, 688 long sslNativePointer, AliasChooser chooser) throws SSLException, 689 CertificateEncodingException { 690 Set<String> keyTypesSet = getSupportedClientKeyTypes(keyTypeBytes); 691 String[] keyTypes = keyTypesSet.toArray(new String[keyTypesSet.size()]); 692 693 X500Principal[] issuers; 694 if (asn1DerEncodedPrincipals == null) { 695 issuers = null; 696 } else { 697 issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 698 for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 699 issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 700 } 701 } 702 X509KeyManager keyManager = getX509KeyManager(); 703 String alias = (keyManager != null) ? chooser.chooseClientAlias(keyManager, issuers, 704 keyTypes) : null; 705 setCertificate(sslNativePointer, alias); 706 } 707 708 /** 709 * @see NativeCrypto.SSLHandshakeCallbacks#clientPSKKeyRequested(String, byte[], byte[]) 710 */ clientPSKKeyRequested( String identityHint, byte[] identityBytesOut, byte[] key, PSKCallbacks pskCallbacks)711 int clientPSKKeyRequested( 712 String identityHint, byte[] identityBytesOut, byte[] key, PSKCallbacks pskCallbacks) { 713 PSKKeyManager pskKeyManager = getPSKKeyManager(); 714 if (pskKeyManager == null) { 715 return 0; 716 } 717 718 String identity = pskCallbacks.chooseClientPSKIdentity(pskKeyManager, identityHint); 719 // Store identity in NULL-terminated modified UTF-8 representation into ientityBytesOut 720 byte[] identityBytes; 721 if (identity == null) { 722 identity = ""; 723 identityBytes = EmptyArray.BYTE; 724 } else if (identity.isEmpty()) { 725 identityBytes = EmptyArray.BYTE; 726 } else { 727 try { 728 identityBytes = identity.getBytes("UTF-8"); 729 } catch (UnsupportedEncodingException e) { 730 throw new RuntimeException("UTF-8 encoding not supported", e); 731 } 732 } 733 if (identityBytes.length + 1 > identityBytesOut.length) { 734 // Insufficient space in the output buffer 735 return 0; 736 } 737 if (identityBytes.length > 0) { 738 System.arraycopy(identityBytes, 0, identityBytesOut, 0, identityBytes.length); 739 } 740 identityBytesOut[identityBytes.length] = 0; 741 742 SecretKey secretKey = pskCallbacks.getPSKKey(pskKeyManager, identityHint, identity); 743 byte[] secretKeyBytes = secretKey.getEncoded(); 744 if (secretKeyBytes == null) { 745 return 0; 746 } else if (secretKeyBytes.length > key.length) { 747 // Insufficient space in the output buffer 748 return 0; 749 } 750 System.arraycopy(secretKeyBytes, 0, key, 0, secretKeyBytes.length); 751 return secretKeyBytes.length; 752 } 753 754 /** 755 * @see NativeCrypto.SSLHandshakeCallbacks#serverPSKKeyRequested(String, String, byte[]) 756 */ serverPSKKeyRequested( String identityHint, String identity, byte[] key, PSKCallbacks pskCallbacks)757 int serverPSKKeyRequested( 758 String identityHint, String identity, byte[] key, PSKCallbacks pskCallbacks) { 759 PSKKeyManager pskKeyManager = getPSKKeyManager(); 760 if (pskKeyManager == null) { 761 return 0; 762 } 763 SecretKey secretKey = pskCallbacks.getPSKKey(pskKeyManager, identityHint, identity); 764 byte[] secretKeyBytes = secretKey.getEncoded(); 765 if (secretKeyBytes == null) { 766 return 0; 767 } else if (secretKeyBytes.length > key.length) { 768 return 0; 769 } 770 System.arraycopy(secretKeyBytes, 0, key, 0, secretKeyBytes.length); 771 return secretKeyBytes.length; 772 } 773 774 /** 775 * Gets the suitable session reference from the session cache container. 776 */ getCachedClientSession(ClientSessionContext sessionContext, String hostName, int port)777 SSLSession getCachedClientSession(ClientSessionContext sessionContext, String hostName, 778 int port) { 779 if (hostName == null) { 780 return null; 781 } 782 783 SSLSession session = sessionContext.getSession(hostName, port); 784 if (session == null) { 785 return null; 786 } 787 788 String protocol = session.getProtocol(); 789 boolean protocolFound = false; 790 for (String enabledProtocol : enabledProtocols) { 791 if (protocol.equals(enabledProtocol)) { 792 protocolFound = true; 793 break; 794 } 795 } 796 if (!protocolFound) { 797 return null; 798 } 799 800 String cipherSuite = session.getCipherSuite(); 801 boolean cipherSuiteFound = false; 802 for (String enabledCipherSuite : enabledCipherSuites) { 803 if (cipherSuite.equals(enabledCipherSuite)) { 804 cipherSuiteFound = true; 805 break; 806 } 807 } 808 if (!cipherSuiteFound) { 809 return null; 810 } 811 812 return session; 813 } 814 815 /** 816 * For abstracting the X509KeyManager calls between 817 * {@link X509KeyManager#chooseClientAlias(String[], java.security.Principal[], java.net.Socket)} 818 * and 819 * {@link X509ExtendedKeyManager#chooseEngineClientAlias(String[], java.security.Principal[], javax.net.ssl.SSLEngine)} 820 */ 821 public interface AliasChooser { chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, String[] keyTypes)822 String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 823 String[] keyTypes); 824 chooseServerAlias(X509KeyManager keyManager, String keyType)825 String chooseServerAlias(X509KeyManager keyManager, String keyType); 826 } 827 828 /** 829 * For abstracting the {@code PSKKeyManager} calls between those taking an {@code SSLSocket} and 830 * those taking an {@code SSLEngine}. 831 */ 832 public interface PSKCallbacks { chooseServerPSKIdentityHint(PSKKeyManager keyManager)833 String chooseServerPSKIdentityHint(PSKKeyManager keyManager); chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint)834 String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint); getPSKKey(PSKKeyManager keyManager, String identityHint, String identity)835 SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity); 836 } 837 838 /** 839 * Returns the clone of this object. 840 * @return the clone. 841 */ 842 @Override clone()843 protected Object clone() { 844 try { 845 return super.clone(); 846 } catch (CloneNotSupportedException e) { 847 throw new AssertionError(e); 848 } 849 } 850 getDefaultX509KeyManager()851 private static X509KeyManager getDefaultX509KeyManager() throws KeyManagementException { 852 X509KeyManager result = defaultX509KeyManager; 853 if (result == null) { 854 // single-check idiom 855 defaultX509KeyManager = result = createDefaultX509KeyManager(); 856 } 857 return result; 858 } createDefaultX509KeyManager()859 private static X509KeyManager createDefaultX509KeyManager() throws KeyManagementException { 860 try { 861 String algorithm = KeyManagerFactory.getDefaultAlgorithm(); 862 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 863 kmf.init(null, null); 864 KeyManager[] kms = kmf.getKeyManagers(); 865 X509KeyManager result = findFirstX509KeyManager(kms); 866 if (result == null) { 867 throw new KeyManagementException("No X509KeyManager among default KeyManagers: " 868 + Arrays.toString(kms)); 869 } 870 return result; 871 } catch (NoSuchAlgorithmException e) { 872 throw new KeyManagementException(e); 873 } catch (KeyStoreException e) { 874 throw new KeyManagementException(e); 875 } catch (UnrecoverableKeyException e) { 876 throw new KeyManagementException(e); 877 } 878 } 879 880 /** 881 * Finds the first {@link X509KeyManager} element in the provided array. 882 * 883 * @return the first {@code X509KeyManager} or {@code null} if not found. 884 */ findFirstX509KeyManager(KeyManager[] kms)885 private static X509KeyManager findFirstX509KeyManager(KeyManager[] kms) { 886 for (KeyManager km : kms) { 887 if (km instanceof X509KeyManager) { 888 return (X509KeyManager)km; 889 } 890 } 891 return null; 892 } 893 894 /** 895 * Finds the first {@link PSKKeyManager} element in the provided array. 896 * 897 * @return the first {@code PSKKeyManager} or {@code null} if not found. 898 */ findFirstPSKKeyManager(KeyManager[] kms)899 private static PSKKeyManager findFirstPSKKeyManager(KeyManager[] kms) { 900 for (KeyManager km : kms) { 901 if (km instanceof PSKKeyManager) { 902 return (PSKKeyManager)km; 903 } else if (km != null) { 904 try { 905 return DuckTypedPSKKeyManager.getInstance(km); 906 } catch (NoSuchMethodException ignored) {} 907 } 908 } 909 return null; 910 } 911 912 /** 913 * Gets the default X.509 trust manager. 914 * <p> 915 * TODO: Move this to a published API under dalvik.system. 916 */ getDefaultX509TrustManager()917 public static X509TrustManager getDefaultX509TrustManager() 918 throws KeyManagementException { 919 X509TrustManager result = defaultX509TrustManager; 920 if (result == null) { 921 // single-check idiom 922 defaultX509TrustManager = result = createDefaultX509TrustManager(); 923 } 924 return result; 925 } 926 createDefaultX509TrustManager()927 private static X509TrustManager createDefaultX509TrustManager() 928 throws KeyManagementException { 929 try { 930 String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 931 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 932 tmf.init((KeyStore) null); 933 TrustManager[] tms = tmf.getTrustManagers(); 934 X509TrustManager trustManager = findFirstX509TrustManager(tms); 935 if (trustManager == null) { 936 throw new KeyManagementException( 937 "No X509TrustManager in among default TrustManagers: " 938 + Arrays.toString(tms)); 939 } 940 return trustManager; 941 } catch (NoSuchAlgorithmException e) { 942 throw new KeyManagementException(e); 943 } catch (KeyStoreException e) { 944 throw new KeyManagementException(e); 945 } 946 } 947 948 /** 949 * Finds the first {@link X509ExtendedTrustManager} or 950 * {@link X509TrustManager} element in the provided array. 951 * 952 * @return the first {@code X509ExtendedTrustManager} or 953 * {@code X509TrustManager} or {@code null} if not found. 954 */ findFirstX509TrustManager(TrustManager[] tms)955 private static X509TrustManager findFirstX509TrustManager(TrustManager[] tms) { 956 for (TrustManager tm : tms) { 957 if (tm instanceof X509TrustManager) { 958 return (X509TrustManager) tm; 959 } 960 } 961 return null; 962 } 963 getEndpointIdentificationAlgorithm()964 public String getEndpointIdentificationAlgorithm() { 965 return endpointIdentificationAlgorithm; 966 } 967 setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm)968 public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm) { 969 this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; 970 } 971 getUseCipherSuitesOrder()972 public boolean getUseCipherSuitesOrder() { 973 return useCipherSuitesOrder; 974 } 975 setUseCipherSuitesOrder(boolean useCipherSuitesOrder)976 public void setUseCipherSuitesOrder(boolean useCipherSuitesOrder) { 977 this.useCipherSuitesOrder = useCipherSuitesOrder; 978 } 979 980 /** Key type: RSA certificate. */ 981 private static final String KEY_TYPE_RSA = "RSA"; 982 983 /** Key type: Diffie-Hellman certificate signed by issuer with RSA signature. */ 984 private static final String KEY_TYPE_DH_RSA = "DH_RSA"; 985 986 /** Key type: Elliptic Curve certificate. */ 987 private static final String KEY_TYPE_EC = "EC"; 988 989 /** Key type: Elliptic Curve certificate signed by issuer with ECDSA signature. */ 990 private static final String KEY_TYPE_EC_EC = "EC_EC"; 991 992 /** Key type: Elliptic Curve certificate signed by issuer with RSA signature. */ 993 private static final String KEY_TYPE_EC_RSA = "EC_RSA"; 994 995 /** 996 * Returns key type constant suitable for calling X509KeyManager.chooseServerAlias or 997 * X509ExtendedKeyManager.chooseEngineServerAlias. Returns {@code null} for key exchanges that 998 * do not use X.509 for server authentication. 999 */ getServerX509KeyType(long sslCipherNative)1000 private static String getServerX509KeyType(long sslCipherNative) throws SSLException { 1001 String kx_name = NativeCrypto.SSL_CIPHER_get_kx_name(sslCipherNative); 1002 if (kx_name.equals("RSA") || kx_name.equals("DHE_RSA") || kx_name.equals("ECDHE_RSA")) { 1003 return KEY_TYPE_RSA; 1004 } else if (kx_name.equals("ECDHE_ECDSA")) { 1005 return KEY_TYPE_EC; 1006 } else if (kx_name.equals("ECDH_RSA")) { 1007 return KEY_TYPE_EC_RSA; 1008 } else if (kx_name.equals("ECDH_ECDSA")) { 1009 return KEY_TYPE_EC_EC; 1010 } else if (kx_name.equals("DH_RSA")) { 1011 return KEY_TYPE_DH_RSA; 1012 } else { 1013 return null; 1014 } 1015 } 1016 1017 /** 1018 * Similar to getServerKeyType, but returns value given TLS 1019 * ClientCertificateType byte values from a CertificateRequest 1020 * message for use with X509KeyManager.chooseClientAlias or 1021 * X509ExtendedKeyManager.chooseEngineClientAlias. 1022 * <p> 1023 * Visible for testing. 1024 */ getClientKeyType(byte clientCertificateType)1025 public static String getClientKeyType(byte clientCertificateType) { 1026 // See also http://www.ietf.org/assignments/tls-parameters/tls-parameters.xml 1027 switch (clientCertificateType) { 1028 case NativeConstants.TLS_CT_RSA_SIGN: 1029 return KEY_TYPE_RSA; // RFC rsa_sign 1030 case NativeConstants.TLS_CT_RSA_FIXED_DH: 1031 return KEY_TYPE_DH_RSA; // RFC rsa_fixed_dh 1032 case NativeConstants.TLS_CT_ECDSA_SIGN: 1033 return KEY_TYPE_EC; // RFC ecdsa_sign 1034 case NativeConstants.TLS_CT_RSA_FIXED_ECDH: 1035 return KEY_TYPE_EC_RSA; // RFC rsa_fixed_ecdh 1036 case NativeConstants.TLS_CT_ECDSA_FIXED_ECDH: 1037 return KEY_TYPE_EC_EC; // RFC ecdsa_fixed_ecdh 1038 default: 1039 return null; 1040 } 1041 } 1042 1043 /** 1044 * Gets the supported key types for client certificates based on the 1045 * {@code ClientCertificateType} values provided by the server. 1046 * 1047 * @param clientCertificateTypes {@code ClientCertificateType} values provided by the server. 1048 * See https://www.ietf.org/assignments/tls-parameters/tls-parameters.xml. 1049 * @return supported key types that can be used in {@code X509KeyManager.chooseClientAlias} and 1050 * {@code X509ExtendedKeyManager.chooseEngineClientAlias}. 1051 * 1052 * Visible for testing. 1053 */ getSupportedClientKeyTypes(byte[] clientCertificateTypes)1054 public static Set<String> getSupportedClientKeyTypes(byte[] clientCertificateTypes) { 1055 Set<String> result = new HashSet<String>(clientCertificateTypes.length); 1056 for (byte keyTypeCode : clientCertificateTypes) { 1057 String keyType = getClientKeyType(keyTypeCode); 1058 if (keyType == null) { 1059 // Unsupported client key type -- ignore 1060 continue; 1061 } 1062 result.add(keyType); 1063 } 1064 return result; 1065 } 1066 getDefaultCipherSuites( boolean x509CipherSuitesNeeded, boolean pskCipherSuitesNeeded)1067 private static String[] getDefaultCipherSuites( 1068 boolean x509CipherSuitesNeeded, 1069 boolean pskCipherSuitesNeeded) { 1070 if (x509CipherSuitesNeeded) { 1071 // X.509 based cipher suites need to be listed. 1072 if (pskCipherSuitesNeeded) { 1073 // Both X.509 and PSK based cipher suites need to be listed. Because TLS-PSK is not 1074 // normally used, we assume that when PSK cipher suites are requested here they 1075 // should be preferred over other cipher suites. Thus, we give PSK cipher suites 1076 // higher priority than X.509 cipher suites. 1077 // NOTE: There are cipher suites that use both X.509 and PSK (e.g., those based on 1078 // RSA_PSK key exchange). However, these cipher suites are not currently supported. 1079 return concat( 1080 NativeCrypto.DEFAULT_PSK_CIPHER_SUITES, 1081 NativeCrypto.DEFAULT_X509_CIPHER_SUITES, 1082 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 1083 } else { 1084 // Only X.509 cipher suites need to be listed. 1085 return concat( 1086 NativeCrypto.DEFAULT_X509_CIPHER_SUITES, 1087 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 1088 } 1089 } else if (pskCipherSuitesNeeded) { 1090 // Only PSK cipher suites need to be listed. 1091 return concat( 1092 NativeCrypto.DEFAULT_PSK_CIPHER_SUITES, 1093 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 1094 } else { 1095 // Neither X.509 nor PSK cipher suites need to be listed. 1096 return new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}; 1097 } 1098 } 1099 concat(String[].... arrays)1100 private static String[] concat(String[]... arrays) { 1101 int resultLength = 0; 1102 for (String[] array : arrays) { 1103 resultLength += array.length; 1104 } 1105 String[] result = new String[resultLength]; 1106 int resultOffset = 0; 1107 for (String[] array : arrays) { 1108 System.arraycopy(array, 0, result, resultOffset, array.length); 1109 resultOffset += array.length; 1110 } 1111 return result; 1112 } 1113 1114 /** 1115 * Check if SCT verification is enforced for a given hostname. 1116 * 1117 * SCT Verification is enabled using {@code Security} properties. 1118 * The "conscrypt.ct.enable" property must be true, as well as a per domain property. 1119 * The reverse notation of the domain name, prefixed with "conscrypt.ct.enforce." 1120 * is used as the property name. 1121 * Basic globbing is also supported. 1122 * 1123 * For example, for the domain foo.bar.com, the following properties will be 1124 * looked up, in order of precedence. 1125 * - conscrypt.ct.enforce.com.bar.foo 1126 * - conscrypt.ct.enforce.com.bar.* 1127 * - conscrypt.ct.enforce.com.* 1128 * - conscrypt.ct.enforce.* 1129 */ isCTVerificationEnabled(String hostname)1130 public boolean isCTVerificationEnabled(String hostname) { 1131 if (hostname == null) { 1132 return false; 1133 } 1134 1135 // Bypass the normal property based check. This is used for testing only 1136 if (ctVerificationEnabled) { 1137 return true; 1138 } 1139 1140 String property = Security.getProperty("conscrypt.ct.enable"); 1141 if (property == null || Boolean.valueOf(property.toLowerCase()) == false) { 1142 return false; 1143 } 1144 1145 List<String> parts = Arrays.asList(hostname.split("\\.")); 1146 Collections.reverse(parts); 1147 1148 boolean enable = false; 1149 String propertyName = "conscrypt.ct.enforce"; 1150 // The loop keeps going on even once we've found a match 1151 // This allows for finer grained settings on subdomains 1152 for (String part: parts) { 1153 property = Security.getProperty(propertyName + ".*"); 1154 if (property != null) { 1155 enable = Boolean.valueOf(property.toLowerCase()); 1156 } 1157 1158 propertyName = propertyName + "." + part; 1159 } 1160 1161 property = Security.getProperty(propertyName); 1162 if (property != null) { 1163 enable = Boolean.valueOf(property.toLowerCase()); 1164 } 1165 1166 return enable; 1167 } 1168 } 1169