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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * @author Alexander Y. Kleymenov
23 package org.apache.harmony.xnet.provider.jsse;
25 import java.security.KeyManagementException;
26 import java.security.KeyStore;
27 import java.security.KeyStoreException;
28 import java.security.NoSuchAlgorithmException;
29 import java.security.SecureRandom;
30 import java.security.UnrecoverableKeyException;
31 import javax.net.ssl.KeyManager;
32 import javax.net.ssl.KeyManagerFactory;
33 import javax.net.ssl.TrustManager;
34 import javax.net.ssl.TrustManagerFactory;
35 import javax.net.ssl.X509KeyManager;
36 import javax.net.ssl.X509TrustManager;
39 * The instances of this class incapsulate all the info
40 * about enabled cipher suites and protocols,
41 * as well as the information about client/server mode of
42 * ssl socket, whether it require/want client authentication or not,
43 * and controls whether new SSL sessions may be established by this
46 // BEGIN android-changed
47 public class SSLParameters implements Cloneable {
48 // END android-changed
50 // default source of authentication keys
51 private static X509KeyManager defaultKeyManager;
52 // default source of authentication trust decisions
53 private static X509TrustManager defaultTrustManager;
54 // default source of random numbers
55 private static SecureRandom defaultSecureRandom;
56 // default SSL parameters
57 private static SSLParameters defaultParameters;
59 // client session context contains the set of reusable
60 // client-side SSL sessions
61 // BEGIN android-changed
62 private final ClientSessionContext clientSessionContext;
63 // server session context contains the set of reusable
64 // server-side SSL sessions
65 private final ServerSessionContext serverSessionContext;
66 // END android-changed
67 // source of authentication keys
68 private X509KeyManager keyManager;
69 // source of authentication trust decisions
70 private X509TrustManager trustManager;
71 // source of random numbers
72 private SecureRandom secureRandom;
74 // cipher suites available for SSL connection
75 // BEGIN android-changed
76 private CipherSuite[] enabledCipherSuites;
77 // END android-changed
78 // string representations of available cipher suites
79 private String[] enabledCipherSuiteNames = null;
81 // protocols available for SSL connection
82 private String[] enabledProtocols = ProtocolVersion.supportedProtocols;
84 // if the peer with this parameters tuned to work in client mode
85 private boolean client_mode = true;
86 // if the peer with this parameters tuned to require client authentication
87 private boolean need_client_auth = false;
88 // if the peer with this parameters tuned to request client authentication
89 private boolean want_client_auth = false;
90 // if the peer with this parameters allowed to cteate new SSL session
91 private boolean enable_session_creation = true;
93 // BEGIN android-changed
94 protected CipherSuite[] getEnabledCipherSuitesMember() {
95 if (enabledCipherSuites == null) this.enabledCipherSuites = CipherSuite.defaultCipherSuites;
96 return enabledCipherSuites;
100 * Holds a pointer to our native SSL context.
102 private int ssl_ctx = 0;
105 * Initializes our native SSL context.
107 private native int nativeinitsslctx();
110 * Returns the native SSL context, creating it on-the-fly, if necessary.
112 protected synchronized int getSSLCTX() {
113 if (ssl_ctx == 0) ssl_ctx = nativeinitsslctx();
116 // END android-changed
119 * Initializes the parameters. Naturally this constructor is used
120 * in SSLContextImpl.engineInit method which dirrectly passes its
121 * parameters. In other words this constructor holds all
122 * the functionality provided by SSLContext.init method.
123 * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[],
124 * SecureRandom)} for more information
126 protected SSLParameters(KeyManager[] kms, TrustManager[] tms,
127 // BEGIN android-changed
128 SecureRandom sr, SSLClientSessionCache clientCache,
129 SSLServerSessionCache serverCache)
130 throws KeyManagementException {
131 this.serverSessionContext
132 = new ServerSessionContext(this, serverCache);
133 this.clientSessionContext
134 = new ClientSessionContext(this, clientCache);
135 // END android-changed
137 // initialize key manager
138 boolean initialize_default = false;
139 // It's not described by the spec of SSLContext what should happen
140 // if the arrays of length 0 are specified. This implementation
141 // behave as for null arrays (i.e. use installed security providers)
142 if ((kms == null) || (kms.length == 0)) {
143 if (defaultKeyManager == null) {
144 KeyManagerFactory kmf = KeyManagerFactory.getInstance(
145 KeyManagerFactory.getDefaultAlgorithm());
146 kmf.init(null, null);
147 kms = kmf.getKeyManagers();
148 // tell that we are trying to initialize defaultKeyManager
149 initialize_default = true;
151 keyManager = defaultKeyManager;
154 if (keyManager == null) { // was not initialized by default
155 for (int i = 0; i < kms.length; i++) {
156 if (kms[i] instanceof X509KeyManager) {
157 keyManager = (X509KeyManager)kms[i];
161 if (keyManager == null) {
162 throw new KeyManagementException("No X509KeyManager found");
164 if (initialize_default) {
165 // found keyManager is default key manager
166 defaultKeyManager = keyManager;
170 // initialize trust manager
171 initialize_default = false;
172 if ((tms == null) || (tms.length == 0)) {
173 if (defaultTrustManager == null) {
174 TrustManagerFactory tmf = TrustManagerFactory
175 .getInstance(TrustManagerFactory.getDefaultAlgorithm());
176 tmf.init((KeyStore)null);
177 tms = tmf.getTrustManagers();
178 initialize_default = true;
180 trustManager = defaultTrustManager;
183 if (trustManager == null) { // was not initialized by default
184 for (int i = 0; i < tms.length; i++) {
185 if (tms[i] instanceof X509TrustManager) {
186 trustManager = (X509TrustManager)tms[i];
190 if (trustManager == null) {
191 throw new KeyManagementException("No X509TrustManager found");
193 if (initialize_default) {
194 // found trustManager is default trust manager
195 defaultTrustManager = trustManager;
198 } catch (NoSuchAlgorithmException e) {
199 throw new KeyManagementException(e);
200 } catch (KeyStoreException e) {
201 throw new KeyManagementException(e);
202 } catch (UnrecoverableKeyException e) {
203 throw new KeyManagementException(e);
205 // initialize secure random
206 // BEGIN android-removed
208 // if (defaultSecureRandom == null) {
209 // defaultSecureRandom = new SecureRandom();
211 // secureRandom = defaultSecureRandom;
213 // secureRandom = sr;
215 // END android-removed
216 // BEGIN android-added
217 // We simply use the SecureRandom passed in by the caller. If it's
218 // null, we don't replace it by a new instance. The native code below
219 // then directly accesses /dev/urandom. Not the most elegant solution,
220 // but faster than going through the SecureRandom object.
225 protected static SSLParameters getDefault() throws KeyManagementException {
226 if (defaultParameters == null) {
227 // BEGIN android-changed
228 defaultParameters = new SSLParameters(null, null, null, null, null);
229 // END android-changed
231 return (SSLParameters) defaultParameters.clone();
235 * @return server session context
237 // BEGIN android-changed
238 protected ServerSessionContext getServerSessionContext() {
239 // END android-changed
240 return serverSessionContext;
244 * @return client session context
246 // BEGIN android-changed
247 protected ClientSessionContext getClientSessionContext() {
248 // END android-changed
249 return clientSessionContext;
253 * @return key manager
255 protected X509KeyManager getKeyManager() {
260 * @return trust manager
262 protected X509TrustManager getTrustManager() {
267 * @return secure random
269 protected SecureRandom getSecureRandom() {
270 // BEGIN android-removed
271 // return secureRandom;
272 // END android-removed
273 // BEGIN android-added
274 if (secureRandom != null) return secureRandom;
275 if (defaultSecureRandom == null)
277 defaultSecureRandom = new SecureRandom();
279 secureRandom = defaultSecureRandom;
284 // BEGIN android-added
286 * @return the secure random member reference, even it is null
288 protected SecureRandom getSecureRandomMember() {
294 * @return the names of enabled cipher suites
296 protected String[] getEnabledCipherSuites() {
297 if (enabledCipherSuiteNames == null) {
298 // BEGIN android-added
299 CipherSuite[] enabledCipherSuites = getEnabledCipherSuitesMember();
301 enabledCipherSuiteNames = new String[enabledCipherSuites.length];
302 for (int i = 0; i< enabledCipherSuites.length; i++) {
303 enabledCipherSuiteNames[i] = enabledCipherSuites[i].getName();
306 return (String[]) enabledCipherSuiteNames.clone();
310 * Sets the set of available cipher suites for use in SSL connection.
311 * @param suites: String[]
314 protected void setEnabledCipherSuites(String[] suites) {
315 if (suites == null) {
316 throw new IllegalArgumentException("Provided parameter is null");
318 CipherSuite[] cipherSuites = new CipherSuite[suites.length];
319 for (int i=0; i<suites.length; i++) {
320 cipherSuites[i] = CipherSuite.getByName(suites[i]);
321 if (cipherSuites[i] == null || !cipherSuites[i].supported) {
322 throw new IllegalArgumentException(suites[i] +
323 " is not supported.");
326 enabledCipherSuites = cipherSuites;
327 enabledCipherSuiteNames = suites;
331 * @return the set of enabled protocols
333 protected String[] getEnabledProtocols() {
334 return (String[]) enabledProtocols.clone();
338 * Sets the set of available protocols for use in SSL connection.
339 * @param protocols String[]
341 protected void setEnabledProtocols(String[] protocols) {
342 if (protocols == null) {
343 throw new IllegalArgumentException("Provided parameter is null");
345 for (int i=0; i<protocols.length; i++) {
346 if (!ProtocolVersion.isSupported(protocols[i])) {
347 throw new IllegalArgumentException("Protocol " + protocols[i] +
348 " is not supported.");
351 enabledProtocols = protocols;
355 * Tunes the peer holding this parameters to work in client mode.
356 * @param mode if the peer is configured to work in client mode
358 protected void setUseClientMode(boolean mode) {
363 * Returns the value indicating if the parameters configured to work
366 protected boolean getUseClientMode() {
371 * Tunes the peer holding this parameters to require client authentication
373 protected void setNeedClientAuth(boolean need) {
374 need_client_auth = need;
375 // reset the want_client_auth setting
376 want_client_auth = false;
380 * Returns the value indicating if the peer with this parameters tuned
381 * to require client authentication
383 protected boolean getNeedClientAuth() {
384 return need_client_auth;
388 * Tunes the peer holding this parameters to request client authentication
390 protected void setWantClientAuth(boolean want) {
391 want_client_auth = want;
392 // reset the need_client_auth setting
393 need_client_auth = false;
397 * Returns the value indicating if the peer with this parameters
398 * tuned to request client authentication
401 protected boolean getWantClientAuth() {
402 return want_client_auth;
406 * Allows/disallows the peer holding this parameters to
407 * create new SSL session
409 protected void setEnableSessionCreation(boolean flag) {
410 enable_session_creation = flag;
414 * Returns the value indicating if the peer with this parameters
415 * allowed to cteate new SSL session
417 protected boolean getEnableSessionCreation() {
418 return enable_session_creation;
422 * Returns the clone of this object.
425 protected Object clone() {
426 // BEGIN android-changed
428 return super.clone();
429 } catch (CloneNotSupportedException e) {
430 throw new AssertionError(e);
432 // END android-changed
436 * Gets the default trust manager.
438 * TODO: Move this to a published API under dalvik.system.
440 public static X509TrustManager getDefaultTrustManager() {
441 return defaultTrustManager;