• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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