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