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 private 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 */ 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 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 */ 171 public AbstractSessionContext getSessionContext() { 172 return client_mode ? clientSessionContext : serverSessionContext; 173 } 174 175 /** 176 * @return server session context 177 */ 178 protected ServerSessionContext getServerSessionContext() { 179 return serverSessionContext; 180 } 181 182 /** 183 * @return client session context 184 */ 185 protected ClientSessionContext getClientSessionContext() { 186 return clientSessionContext; 187 } 188 189 /** 190 * @return X.509 key manager or {@code null} for none. 191 */ 192 protected X509KeyManager getX509KeyManager() { 193 return x509KeyManager; 194 } 195 196 /** 197 * @return Pre-Shared Key (PSK) key manager or {@code null} for none. 198 */ 199 protected PSKKeyManager getPSKKeyManager() { 200 return pskKeyManager; 201 } 202 203 /** 204 * @return X.509 trust manager or {@code null} for none. 205 */ 206 protected X509TrustManager getX509TrustManager() { 207 return x509TrustManager; 208 } 209 210 /** 211 * @return secure random 212 */ 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 */ 229 protected SecureRandom getSecureRandomMember() { 230 return secureRandom; 231 } 232 233 /** 234 * @return the names of enabled cipher suites 235 */ 236 protected String[] getEnabledCipherSuites() { 237 return enabledCipherSuites.clone(); 238 } 239 240 /** 241 * Sets the enabled cipher suites after filtering through OpenSSL. 242 */ 243 protected void setEnabledCipherSuites(String[] cipherSuites) { 244 enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(cipherSuites).clone(); 245 } 246 247 /** 248 * @return the set of enabled protocols 249 */ 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 */ 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 */ 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 */ 274 protected boolean getUseClientMode() { 275 return client_mode; 276 } 277 278 /** 279 * Tunes the peer holding this parameters to require client authentication 280 */ 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 */ 291 protected boolean getNeedClientAuth() { 292 return need_client_auth; 293 } 294 295 /** 296 * Tunes the peer holding this parameters to request client authentication 297 */ 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 */ 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 */ 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 */ 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 */ 332 protected void setUseSni(boolean flag) { 333 useSni = Boolean.valueOf(flag); 334 } 335 336 /** 337 * Returns whether connections using this SSL connection should use the TLS 338 * extension Server Name Indication (SNI). 339 */ 340 protected boolean getUseSni() { 341 return useSni != null ? useSni.booleanValue() : isSniEnabledByDefault(); 342 } 343 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 */ 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 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 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 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 final OpenSSLKey key; 441 try { 442 key = OpenSSLKey.fromPrivateKey(privateKey); 443 NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getPkeyContext()); 444 } catch (InvalidKeyException e) { 445 throw new SSLException(e); 446 } 447 448 // We may not have access to all the information to check the private key 449 // if it's a wrapped platform key, so skip this check. 450 if (!key.isWrapped()) { 451 // Makes sure the set PrivateKey and X509Certificate refer to the same 452 // key by comparing the public values. 453 NativeCrypto.SSL_check_private_key(sslNativePointer); 454 } 455 } 456 457 void setSSLParameters(long sslCtxNativePointer, long sslNativePointer, AliasChooser chooser, 458 PSKCallbacks pskCallbacks, String sniHostname) throws SSLException, IOException { 459 if (npnProtocols != null) { 460 NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 461 } 462 463 if (client_mode && alpnProtocols != null) { 464 NativeCrypto.SSL_set_alpn_protos(sslNativePointer, alpnProtocols); 465 } 466 467 NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 468 NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 469 470 // setup server certificates and private keys. 471 // clients will receive a call back to request certificates. 472 if (!client_mode) { 473 Set<String> keyTypes = new HashSet<String>(); 474 for (long sslCipherNativePointer : NativeCrypto.SSL_get_ciphers(sslNativePointer)) { 475 String keyType = getServerX509KeyType(sslCipherNativePointer); 476 if (keyType != null) { 477 keyTypes.add(keyType); 478 } 479 } 480 X509KeyManager keyManager = getX509KeyManager(); 481 if (keyManager != null) { 482 for (String keyType : keyTypes) { 483 try { 484 setCertificate(sslNativePointer, 485 chooser.chooseServerAlias(x509KeyManager, keyType)); 486 } catch (CertificateEncodingException e) { 487 throw new IOException(e); 488 } 489 } 490 } 491 } 492 493 // Enable Pre-Shared Key (PSK) key exchange if requested 494 PSKKeyManager pskKeyManager = getPSKKeyManager(); 495 if (pskKeyManager != null) { 496 boolean pskEnabled = false; 497 for (String enabledCipherSuite : enabledCipherSuites) { 498 if ((enabledCipherSuite != null) && (enabledCipherSuite.contains("PSK"))) { 499 pskEnabled = true; 500 break; 501 } 502 } 503 if (pskEnabled) { 504 if (client_mode) { 505 NativeCrypto.set_SSL_psk_client_callback_enabled(sslNativePointer, true); 506 } else { 507 NativeCrypto.set_SSL_psk_server_callback_enabled(sslNativePointer, true); 508 String identityHint = pskCallbacks.chooseServerPSKIdentityHint(pskKeyManager); 509 NativeCrypto.SSL_use_psk_identity_hint(sslNativePointer, identityHint); 510 } 511 } 512 } 513 514 if (useSessionTickets) { 515 NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 516 } 517 if (getUseSni() && AddressUtils.isValidSniHostname(sniHostname)) { 518 NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, sniHostname); 519 } 520 521 // BEAST attack mitigation (1/n-1 record splitting for CBC cipher suites 522 // with TLSv1 and SSLv3). 523 NativeCrypto.SSL_set_mode(sslNativePointer, NativeCrypto.SSL_MODE_CBC_RECORD_SPLITTING); 524 525 boolean enableSessionCreation = getEnableSessionCreation(); 526 if (!enableSessionCreation) { 527 NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, enableSessionCreation); 528 } 529 } 530 531 /** 532 * Returns true when the supplied hostname is valid for SNI purposes. 533 */ 534 private static boolean isValidSniHostname(String sniHostname) { 535 if (sniHostname == null) { 536 return false; 537 } 538 539 // Must be a FQDN. 540 if (sniHostname.indexOf('.') == -1) { 541 return false; 542 } 543 544 if (Platform.isLiteralIpAddress(sniHostname)) { 545 return false; 546 } 547 548 return true; 549 } 550 551 /** 552 * Returns whether Server Name Indication (SNI) is enabled by default for 553 * sockets. For more information on SNI, see RFC 6066 section 3. 554 */ 555 private boolean isSniEnabledByDefault() { 556 String enableSNI = System.getProperty("jsse.enableSNIExtension", 557 Platform.isSniEnabledByDefault() ? "true" : "false"); 558 if ("true".equalsIgnoreCase(enableSNI)) { 559 return true; 560 } else if ("false".equalsIgnoreCase(enableSNI)) { 561 return false; 562 } else { 563 throw new RuntimeException( 564 "Can only set \"jsse.enableSNIExtension\" to \"true\" or \"false\""); 565 } 566 } 567 568 void setCertificateValidation(long sslNativePointer) throws IOException { 569 // setup peer certificate verification 570 if (!client_mode) { 571 // needing client auth takes priority... 572 boolean certRequested; 573 if (getNeedClientAuth()) { 574 NativeCrypto.SSL_set_verify(sslNativePointer, 575 NativeCrypto.SSL_VERIFY_PEER 576 | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 577 certRequested = true; 578 // ... over just wanting it... 579 } else if (getWantClientAuth()) { 580 NativeCrypto.SSL_set_verify(sslNativePointer, NativeCrypto.SSL_VERIFY_PEER); 581 certRequested = true; 582 // ... and we must disable verification if we don't want client auth. 583 } else { 584 NativeCrypto.SSL_set_verify(sslNativePointer, NativeCrypto.SSL_VERIFY_NONE); 585 certRequested = false; 586 } 587 588 if (certRequested) { 589 X509TrustManager trustManager = getX509TrustManager(); 590 X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 591 if (issuers != null && issuers.length != 0) { 592 byte[][] issuersBytes; 593 try { 594 issuersBytes = encodeIssuerX509Principals(issuers); 595 } catch (CertificateEncodingException e) { 596 throw new IOException("Problem encoding principals", e); 597 } 598 NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 599 } 600 } 601 } 602 } 603 604 OpenSSLSessionImpl setupSession(long sslSessionNativePointer, long sslNativePointer, 605 final OpenSSLSessionImpl sessionToReuse, String hostname, int port, 606 boolean handshakeCompleted) throws IOException { 607 OpenSSLSessionImpl sslSession = null; 608 byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 609 if (sessionToReuse != null && Arrays.equals(sessionToReuse.getId(), sessionId)) { 610 sslSession = sessionToReuse; 611 sslSession.lastAccessedTime = System.currentTimeMillis(); 612 NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 613 } else { 614 if (!getEnableSessionCreation()) { 615 // Should have been prevented by 616 // NativeCrypto.SSL_set_session_creation_enabled 617 throw new IllegalStateException("SSL Session may not be created"); 618 } 619 X509Certificate[] localCertificates = createCertChain(NativeCrypto 620 .SSL_get_certificate(sslNativePointer)); 621 X509Certificate[] peerCertificates = createCertChain(NativeCrypto 622 .SSL_get_peer_cert_chain(sslNativePointer)); 623 sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 624 peerCertificates, hostname, port, getSessionContext()); 625 // if not, putSession later in handshakeCompleted() callback 626 if (handshakeCompleted) { 627 getSessionContext().putSession(sslSession); 628 } 629 } 630 return sslSession; 631 } 632 633 void chooseClientCertificate(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals, 634 long sslNativePointer, AliasChooser chooser) throws SSLException, 635 CertificateEncodingException { 636 String[] keyTypes = new String[keyTypeBytes.length]; 637 for (int i = 0; i < keyTypeBytes.length; i++) { 638 keyTypes[i] = getClientKeyType(keyTypeBytes[i]); 639 } 640 641 X500Principal[] issuers; 642 if (asn1DerEncodedPrincipals == null) { 643 issuers = null; 644 } else { 645 issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 646 for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 647 issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 648 } 649 } 650 X509KeyManager keyManager = getX509KeyManager(); 651 String alias = (keyManager != null) ? chooser.chooseClientAlias(keyManager, issuers, 652 keyTypes) : null; 653 setCertificate(sslNativePointer, alias); 654 } 655 656 /** 657 * @see NativeCrypto.SSLHandshakeCallbacks#clientPSKKeyRequested(String, byte[], byte[]) 658 */ 659 int clientPSKKeyRequested( 660 String identityHint, byte[] identityBytesOut, byte[] key, PSKCallbacks pskCallbacks) { 661 PSKKeyManager pskKeyManager = getPSKKeyManager(); 662 if (pskKeyManager == null) { 663 return 0; 664 } 665 666 String identity = pskCallbacks.chooseClientPSKIdentity(pskKeyManager, identityHint); 667 // Store identity in NULL-terminated modified UTF-8 representation into ientityBytesOut 668 byte[] identityBytes; 669 if (identity == null) { 670 identity = ""; 671 identityBytes = EmptyArray.BYTE; 672 } else if (identity.isEmpty()) { 673 identityBytes = EmptyArray.BYTE; 674 } else { 675 try { 676 identityBytes = identity.getBytes("UTF-8"); 677 } catch (UnsupportedEncodingException e) { 678 throw new RuntimeException("UTF-8 encoding not supported", e); 679 } 680 } 681 if (identityBytes.length + 1 > identityBytesOut.length) { 682 // Insufficient space in the output buffer 683 return 0; 684 } 685 if (identityBytes.length > 0) { 686 System.arraycopy(identityBytes, 0, identityBytesOut, 0, identityBytes.length); 687 } 688 identityBytesOut[identityBytes.length] = 0; 689 690 SecretKey secretKey = pskCallbacks.getPSKKey(pskKeyManager, identityHint, identity); 691 byte[] secretKeyBytes = secretKey.getEncoded(); 692 if (secretKeyBytes == null) { 693 return 0; 694 } else if (secretKeyBytes.length > key.length) { 695 // Insufficient space in the output buffer 696 return 0; 697 } 698 System.arraycopy(secretKeyBytes, 0, key, 0, secretKeyBytes.length); 699 return secretKeyBytes.length; 700 } 701 702 /** 703 * @see NativeCrypto.SSLHandshakeCallbacks#serverPSKKeyRequested(String, String, byte[]) 704 */ 705 int serverPSKKeyRequested( 706 String identityHint, String identity, byte[] key, PSKCallbacks pskCallbacks) { 707 PSKKeyManager pskKeyManager = getPSKKeyManager(); 708 if (pskKeyManager == null) { 709 return 0; 710 } 711 SecretKey secretKey = pskCallbacks.getPSKKey(pskKeyManager, identityHint, identity); 712 byte[] secretKeyBytes = secretKey.getEncoded(); 713 if (secretKeyBytes == null) { 714 return 0; 715 } else if (secretKeyBytes.length > key.length) { 716 return 0; 717 } 718 System.arraycopy(secretKeyBytes, 0, key, 0, secretKeyBytes.length); 719 return secretKeyBytes.length; 720 } 721 722 /** 723 * Gets the suitable session reference from the session cache container. 724 */ 725 OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext, String hostName, 726 int port) { 727 if (hostName == null) { 728 return null; 729 } 730 OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 731 if (session == null) { 732 return null; 733 } 734 735 String protocol = session.getProtocol(); 736 boolean protocolFound = false; 737 for (String enabledProtocol : enabledProtocols) { 738 if (protocol.equals(enabledProtocol)) { 739 protocolFound = true; 740 break; 741 } 742 } 743 if (!protocolFound) { 744 return null; 745 } 746 747 String cipherSuite = session.getCipherSuite(); 748 boolean cipherSuiteFound = false; 749 for (String enabledCipherSuite : enabledCipherSuites) { 750 if (cipherSuite.equals(enabledCipherSuite)) { 751 cipherSuiteFound = true; 752 break; 753 } 754 } 755 if (!cipherSuiteFound) { 756 return null; 757 } 758 759 return session; 760 } 761 762 /** 763 * For abstracting the X509KeyManager calls between 764 * {@link X509KeyManager#chooseClientAlias(String[], java.security.Principal[], java.net.Socket)} 765 * and 766 * {@link X509ExtendedKeyManager#chooseEngineClientAlias(String[], java.security.Principal[], javax.net.ssl.SSLEngine)} 767 */ 768 public interface AliasChooser { 769 String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 770 String[] keyTypes); 771 772 String chooseServerAlias(X509KeyManager keyManager, String keyType); 773 } 774 775 /** 776 * For abstracting the {@code PSKKeyManager} calls between those taking an {@code SSLSocket} and 777 * those taking an {@code SSLEngine}. 778 */ 779 public interface PSKCallbacks { 780 String chooseServerPSKIdentityHint(PSKKeyManager keyManager); 781 String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint); 782 SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity); 783 } 784 785 /** 786 * Returns the clone of this object. 787 * @return the clone. 788 */ 789 @Override 790 protected Object clone() { 791 try { 792 return super.clone(); 793 } catch (CloneNotSupportedException e) { 794 throw new AssertionError(e); 795 } 796 } 797 798 private static X509KeyManager getDefaultX509KeyManager() throws KeyManagementException { 799 X509KeyManager result = defaultX509KeyManager; 800 if (result == null) { 801 // single-check idiom 802 defaultX509KeyManager = result = createDefaultX509KeyManager(); 803 } 804 return result; 805 } 806 private static X509KeyManager createDefaultX509KeyManager() throws KeyManagementException { 807 try { 808 String algorithm = KeyManagerFactory.getDefaultAlgorithm(); 809 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 810 kmf.init(null, null); 811 KeyManager[] kms = kmf.getKeyManagers(); 812 X509KeyManager result = findFirstX509KeyManager(kms); 813 if (result == null) { 814 throw new KeyManagementException("No X509KeyManager among default KeyManagers: " 815 + Arrays.toString(kms)); 816 } 817 return result; 818 } catch (NoSuchAlgorithmException e) { 819 throw new KeyManagementException(e); 820 } catch (KeyStoreException e) { 821 throw new KeyManagementException(e); 822 } catch (UnrecoverableKeyException e) { 823 throw new KeyManagementException(e); 824 } 825 } 826 827 /** 828 * Finds the first {@link X509KeyManager} element in the provided array. 829 * 830 * @return the first {@code X509KeyManager} or {@code null} if not found. 831 */ 832 private static X509KeyManager findFirstX509KeyManager(KeyManager[] kms) { 833 for (KeyManager km : kms) { 834 if (km instanceof X509KeyManager) { 835 return (X509KeyManager)km; 836 } 837 } 838 return null; 839 } 840 841 /** 842 * Finds the first {@link PSKKeyManager} element in the provided array. 843 * 844 * @return the first {@code PSKKeyManager} or {@code null} if not found. 845 */ 846 private static PSKKeyManager findFirstPSKKeyManager(KeyManager[] kms) { 847 for (KeyManager km : kms) { 848 if (km instanceof PSKKeyManager) { 849 return (PSKKeyManager)km; 850 } 851 } 852 return null; 853 } 854 855 /** 856 * Gets the default X.509 trust manager. 857 * 858 * TODO: Move this to a published API under dalvik.system. 859 */ 860 public static X509TrustManager getDefaultX509TrustManager() 861 throws KeyManagementException { 862 X509TrustManager result = defaultX509TrustManager; 863 if (result == null) { 864 // single-check idiom 865 defaultX509TrustManager = result = createDefaultX509TrustManager(); 866 } 867 return result; 868 } 869 870 private static X509TrustManager createDefaultX509TrustManager() 871 throws KeyManagementException { 872 try { 873 String algorithm = TrustManagerFactory.getDefaultAlgorithm(); 874 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 875 tmf.init((KeyStore) null); 876 TrustManager[] tms = tmf.getTrustManagers(); 877 X509TrustManager trustManager = findFirstX509TrustManager(tms); 878 if (trustManager == null) { 879 throw new KeyManagementException( 880 "No X509TrustManager in among default TrustManagers: " 881 + Arrays.toString(tms)); 882 } 883 return trustManager; 884 } catch (NoSuchAlgorithmException e) { 885 throw new KeyManagementException(e); 886 } catch (KeyStoreException e) { 887 throw new KeyManagementException(e); 888 } 889 } 890 891 /** 892 * Finds the first {@link X509TrustManager} element in the provided array. 893 * 894 * @return the first {@code X509TrustManager} or {@code null} if not found. 895 */ 896 private static X509TrustManager findFirstX509TrustManager(TrustManager[] tms) { 897 for (TrustManager tm : tms) { 898 if (tm instanceof X509TrustManager) { 899 return (X509TrustManager) tm; 900 } 901 } 902 return null; 903 } 904 905 public String getEndpointIdentificationAlgorithm() { 906 return endpointIdentificationAlgorithm; 907 } 908 909 public void setEndpointIdentificationAlgorithm(String endpointIdentificationAlgorithm) { 910 this.endpointIdentificationAlgorithm = endpointIdentificationAlgorithm; 911 } 912 913 /** Key type: RSA. */ 914 private static final String KEY_TYPE_RSA = "RSA"; 915 916 /** Key type: DSA. */ 917 private static final String KEY_TYPE_DSA = "DSA"; 918 919 /** Key type: Diffie-Hellman with RSA signature. */ 920 private static final String KEY_TYPE_DH_RSA = "DH_RSA"; 921 922 /** Key type: Diffie-Hellman with DSA signature. */ 923 private static final String KEY_TYPE_DH_DSA = "DH_DSA"; 924 925 /** Key type: Elliptic Curve. */ 926 private static final String KEY_TYPE_EC = "EC"; 927 928 /** Key type: Eliiptic Curve with ECDSA signature. */ 929 private static final String KEY_TYPE_EC_EC = "EC_EC"; 930 931 /** Key type: Eliiptic Curve with RSA signature. */ 932 private static final String KEY_TYPE_EC_RSA = "EC_RSA"; 933 934 /** 935 * Returns key type constant suitable for calling X509KeyManager.chooseServerAlias or 936 * X509ExtendedKeyManager.chooseEngineServerAlias. Returns {@code null} for key exchanges that 937 * do not use X.509 for server authentication. 938 */ 939 private static String getServerX509KeyType(long sslCipherNative) throws SSLException { 940 int algorithm_mkey = NativeCrypto.get_SSL_CIPHER_algorithm_mkey(sslCipherNative); 941 int algorithm_auth = NativeCrypto.get_SSL_CIPHER_algorithm_auth(sslCipherNative); 942 switch (algorithm_mkey) { 943 case NativeCrypto.SSL_kRSA: 944 return KEY_TYPE_RSA; 945 case NativeCrypto.SSL_kEDH: 946 switch (algorithm_auth) { 947 case NativeCrypto.SSL_aDSS: 948 return KEY_TYPE_DSA; 949 case NativeCrypto.SSL_aRSA: 950 return KEY_TYPE_RSA; 951 case NativeCrypto.SSL_aNULL: 952 return null; 953 } 954 break; 955 case NativeCrypto.SSL_kECDHr: 956 return KEY_TYPE_EC_RSA; 957 case NativeCrypto.SSL_kECDHe: 958 return KEY_TYPE_EC_EC; 959 case NativeCrypto.SSL_kEECDH: 960 switch (algorithm_auth) { 961 case NativeCrypto.SSL_aECDSA: 962 return KEY_TYPE_EC_EC; 963 case NativeCrypto.SSL_aRSA: 964 return KEY_TYPE_RSA; 965 case NativeCrypto.SSL_aPSK: 966 return null; 967 case NativeCrypto.SSL_aNULL: 968 return null; 969 } 970 break; 971 case NativeCrypto.SSL_kPSK: 972 return null; 973 } 974 975 throw new SSLException("Unsupported key exchange. " 976 + "mkey: 0x" + Long.toHexString(algorithm_mkey & 0xffffffffL) 977 + ", auth: 0x" + Long.toHexString(algorithm_auth & 0xffffffffL)); 978 } 979 980 /** 981 * Similar to getServerKeyType, but returns value given TLS 982 * ClientCertificateType byte values from a CertificateRequest 983 * message for use with X509KeyManager.chooseClientAlias or 984 * X509ExtendedKeyManager.chooseEngineClientAlias. 985 */ 986 public static String getClientKeyType(byte keyType) { 987 // See also http://www.ietf.org/assignments/tls-parameters/tls-parameters.xml 988 switch (keyType) { 989 case NativeCrypto.TLS_CT_RSA_SIGN: 990 return KEY_TYPE_RSA; // RFC rsa_sign 991 case NativeCrypto.TLS_CT_DSS_SIGN: 992 return KEY_TYPE_DSA; // RFC dss_sign 993 case NativeCrypto.TLS_CT_RSA_FIXED_DH: 994 return KEY_TYPE_DH_RSA; // RFC rsa_fixed_dh 995 case NativeCrypto.TLS_CT_DSS_FIXED_DH: 996 return KEY_TYPE_DH_DSA; // RFC dss_fixed_dh 997 case NativeCrypto.TLS_CT_ECDSA_SIGN: 998 return KEY_TYPE_EC; // RFC ecdsa_sign 999 case NativeCrypto.TLS_CT_RSA_FIXED_ECDH: 1000 return KEY_TYPE_EC_RSA; // RFC rsa_fixed_ecdh 1001 case NativeCrypto.TLS_CT_ECDSA_FIXED_ECDH: 1002 return KEY_TYPE_EC_EC; // RFC ecdsa_fixed_ecdh 1003 default: 1004 return null; 1005 } 1006 } 1007 1008 private static String[] getDefaultCipherSuites( 1009 boolean x509CipherSuitesNeeded, 1010 boolean pskCipherSuitesNeeded) { 1011 if (x509CipherSuitesNeeded) { 1012 // X.509 based cipher suites need to be listed. 1013 if (pskCipherSuitesNeeded) { 1014 // Both X.509 and PSK based cipher suites need to be listed. Because TLS-PSK is not 1015 // normally used, we assume that when PSK cipher suites are requested here they 1016 // should be preferred over other cipher suites. Thus, we give PSK cipher suites 1017 // higher priority than X.509 cipher suites. 1018 // NOTE: There are cipher suites that use both X.509 and PSK (e.g., those based on 1019 // RSA_PSK key exchange). However, these cipher suites are not currently supported. 1020 return concat( 1021 NativeCrypto.DEFAULT_PSK_CIPHER_SUITES, 1022 NativeCrypto.DEFAULT_X509_CIPHER_SUITES, 1023 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 1024 } else { 1025 // Only X.509 cipher suites need to be listed. 1026 return concat( 1027 NativeCrypto.DEFAULT_X509_CIPHER_SUITES, 1028 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 1029 } 1030 } else if (pskCipherSuitesNeeded) { 1031 // Only PSK cipher suites need to be listed. 1032 return concat( 1033 NativeCrypto.DEFAULT_PSK_CIPHER_SUITES, 1034 new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}); 1035 } else { 1036 // Neither X.509 nor PSK cipher suites need to be listed. 1037 return new String[] {NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV}; 1038 } 1039 } 1040 1041 private static String[] getDefaultProtocols() { 1042 return NativeCrypto.DEFAULT_PROTOCOLS.clone(); 1043 } 1044 1045 private static String[] concat(String[]... arrays) { 1046 int resultLength = 0; 1047 for (String[] array : arrays) { 1048 resultLength += array.length; 1049 } 1050 String[] result = new String[resultLength]; 1051 int resultOffset = 0; 1052 for (String[] array : arrays) { 1053 System.arraycopy(array, 0, result, resultOffset, array.length); 1054 resultOffset += array.length; 1055 } 1056 return result; 1057 } 1058 } 1059