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 java.security.InvalidAlgorithmParameterException;
32 import java.security.cert.CertificateEncodingException;
34 import javax.net.ssl.KeyManager;
35 import javax.net.ssl.KeyManagerFactory;
36 import javax.net.ssl.TrustManager;
37 import javax.net.ssl.TrustManagerFactory;
38 import javax.net.ssl.X509KeyManager;
39 import javax.net.ssl.X509TrustManager;
42 * The instances of this class incapsulate all the info
43 * about enabled cipher suites and protocols,
44 * as well as the information about client/server mode of
45 * ssl socket, whether it require/want client authentication or not,
46 * and controls whether new SSL sessions may be established by this
49 // BEGIN android-changed
50 public class SSLParameters implements Cloneable {
51 // END android-changed
53 // default source of authentication keys
54 private static X509KeyManager defaultKeyManager;
55 // default source of authentication trust decisions
56 private static X509TrustManager defaultTrustManager;
57 // default source of random numbers
58 private static SecureRandom defaultSecureRandom;
59 // default SSL parameters
60 private static SSLParameters defaultParameters;
62 // client session context contains the set of reusable
63 // client-side SSL sessions
64 // BEGIN android-changed
65 private final ClientSessionContext clientSessionContext;
66 // server session context contains the set of reusable
67 // server-side SSL sessions
68 private final ServerSessionContext serverSessionContext;
69 // END android-changed
70 // source of authentication keys
71 private X509KeyManager keyManager;
72 // source of authentication trust decisions
73 private X509TrustManager trustManager;
74 // source of random numbers
75 private SecureRandom secureRandom;
77 // cipher suites available for SSL connection
78 // BEGIN android-changed
79 private CipherSuite[] enabledCipherSuites;
80 // END android-changed
81 // string representations of available cipher suites
82 private String[] enabledCipherSuiteNames = null;
84 // protocols available for SSL connection
85 private String[] enabledProtocols = ProtocolVersion.supportedProtocols;
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;
96 // BEGIN android-changed
97 protected CipherSuite[] getEnabledCipherSuitesMember() {
98 if (enabledCipherSuites == null) this.enabledCipherSuites = CipherSuite.defaultCipherSuites;
99 return enabledCipherSuites;
103 * Holds a pointer to our native SSL context.
105 private int ssl_ctx = 0;
108 * Initializes our native SSL context.
110 private native int nativeinitsslctx();
113 * Returns the native SSL context, creating it on-the-fly, if necessary.
115 protected synchronized int getSSLCTX() {
116 if (ssl_ctx == 0) ssl_ctx = nativeinitsslctx();
119 // END android-changed
122 * Initializes the parameters. Naturally this constructor is used
123 * in SSLContextImpl.engineInit method which dirrectly passes its
124 * parameters. In other words this constructor holds all
125 * the functionality provided by SSLContext.init method.
126 * See {@link javax.net.ssl.SSLContext#init(KeyManager[],TrustManager[],
127 * SecureRandom)} for more information
129 protected SSLParameters(KeyManager[] kms, TrustManager[] tms,
130 // BEGIN android-changed
131 SecureRandom sr, SSLClientSessionCache clientCache,
132 SSLServerSessionCache serverCache)
133 throws KeyManagementException {
134 this.serverSessionContext
135 = new ServerSessionContext(this, serverCache);
136 this.clientSessionContext
137 = new ClientSessionContext(this, clientCache);
138 // END android-changed
140 // initialize key manager
141 boolean initialize_default = false;
142 // It's not described by the spec of SSLContext what should happen
143 // if the arrays of length 0 are specified. This implementation
144 // behave as for null arrays (i.e. use installed security providers)
145 if ((kms == null) || (kms.length == 0)) {
146 if (defaultKeyManager == null) {
147 KeyManagerFactory kmf = KeyManagerFactory.getInstance(
148 KeyManagerFactory.getDefaultAlgorithm());
149 kmf.init(null, null);
150 kms = kmf.getKeyManagers();
151 // tell that we are trying to initialize defaultKeyManager
152 initialize_default = true;
154 keyManager = defaultKeyManager;
157 if (keyManager == null) { // was not initialized by default
158 for (int i = 0; i < kms.length; i++) {
159 if (kms[i] instanceof X509KeyManager) {
160 keyManager = (X509KeyManager)kms[i];
164 if (keyManager == null) {
165 throw new KeyManagementException("No X509KeyManager found");
167 if (initialize_default) {
168 // found keyManager is default key manager
169 defaultKeyManager = keyManager;
173 // initialize trust manager
174 initialize_default = false;
175 if ((tms == null) || (tms.length == 0)) {
176 if (defaultTrustManager == null) {
177 TrustManagerFactory tmf = TrustManagerFactory
178 .getInstance(TrustManagerFactory.getDefaultAlgorithm());
179 tmf.init((KeyStore)null);
180 tms = tmf.getTrustManagers();
181 initialize_default = true;
183 trustManager = defaultTrustManager;
186 if (trustManager == null) { // was not initialized by default
187 for (int i = 0; i < tms.length; i++) {
188 if (tms[i] instanceof X509TrustManager) {
189 trustManager = (X509TrustManager)tms[i];
193 if (trustManager == null) {
194 throw new KeyManagementException("No X509TrustManager found");
196 if (initialize_default) {
197 // found trustManager is default trust manager
198 defaultTrustManager = trustManager;
199 // BEGIN android-added
200 if (trustManager instanceof TrustManagerImpl) {
201 ((TrustManagerImpl) trustManager).indexTrustAnchors();
206 } catch (NoSuchAlgorithmException e) {
207 throw new KeyManagementException(e);
208 } catch (KeyStoreException e) {
209 throw new KeyManagementException(e);
210 } catch (UnrecoverableKeyException e) {
211 throw new KeyManagementException(e);
212 // BEGIN android-added
213 } catch (CertificateEncodingException e) {
214 throw new KeyManagementException(e);
215 } catch (InvalidAlgorithmParameterException e) {
216 throw new KeyManagementException(e);
219 // initialize secure random
220 // BEGIN android-removed
222 // if (defaultSecureRandom == null) {
223 // defaultSecureRandom = new SecureRandom();
225 // secureRandom = defaultSecureRandom;
227 // secureRandom = sr;
229 // END android-removed
230 // BEGIN android-added
231 // We simply use the SecureRandom passed in by the caller. If it's
232 // null, we don't replace it by a new instance. The native code below
233 // then directly accesses /dev/urandom. Not the most elegant solution,
234 // but faster than going through the SecureRandom object.
239 protected static SSLParameters getDefault() throws KeyManagementException {
240 if (defaultParameters == null) {
241 // BEGIN android-changed
242 defaultParameters = new SSLParameters(null, null, null, null, null);
243 // END android-changed
245 return (SSLParameters) defaultParameters.clone();
249 * @return server session context
251 // BEGIN android-changed
252 protected ServerSessionContext getServerSessionContext() {
253 // END android-changed
254 return serverSessionContext;
258 * @return client session context
260 // BEGIN android-changed
261 protected ClientSessionContext getClientSessionContext() {
262 // END android-changed
263 return clientSessionContext;
267 * @return key manager
269 protected X509KeyManager getKeyManager() {
274 * @return trust manager
276 protected X509TrustManager getTrustManager() {
281 * @return secure random
283 protected SecureRandom getSecureRandom() {
284 // BEGIN android-removed
285 // return secureRandom;
286 // END android-removed
287 // BEGIN android-added
288 if (secureRandom != null) return secureRandom;
289 if (defaultSecureRandom == null)
291 defaultSecureRandom = new SecureRandom();
293 secureRandom = defaultSecureRandom;
298 // BEGIN android-added
300 * @return the secure random member reference, even it is null
302 protected SecureRandom getSecureRandomMember() {
308 * @return the names of enabled cipher suites
310 protected String[] getEnabledCipherSuites() {
311 if (enabledCipherSuiteNames == null) {
312 // BEGIN android-added
313 CipherSuite[] enabledCipherSuites = getEnabledCipherSuitesMember();
315 enabledCipherSuiteNames = new String[enabledCipherSuites.length];
316 for (int i = 0; i< enabledCipherSuites.length; i++) {
317 enabledCipherSuiteNames[i] = enabledCipherSuites[i].getName();
320 return (String[]) enabledCipherSuiteNames.clone();
324 * Sets the set of available cipher suites for use in SSL connection.
325 * @param suites: String[]
328 protected void setEnabledCipherSuites(String[] suites) {
329 if (suites == null) {
330 throw new IllegalArgumentException("Provided parameter is null");
332 CipherSuite[] cipherSuites = new CipherSuite[suites.length];
333 for (int i=0; i<suites.length; i++) {
334 cipherSuites[i] = CipherSuite.getByName(suites[i]);
335 if (cipherSuites[i] == null || !cipherSuites[i].supported) {
336 throw new IllegalArgumentException(suites[i] +
337 " is not supported.");
340 enabledCipherSuites = cipherSuites;
341 enabledCipherSuiteNames = suites;
345 * @return the set of enabled protocols
347 protected String[] getEnabledProtocols() {
348 return (String[]) enabledProtocols.clone();
352 * Sets the set of available protocols for use in SSL connection.
353 * @param protocols String[]
355 protected void setEnabledProtocols(String[] protocols) {
356 if (protocols == null) {
357 throw new IllegalArgumentException("Provided parameter is null");
359 for (int i=0; i<protocols.length; i++) {
360 if (!ProtocolVersion.isSupported(protocols[i])) {
361 throw new IllegalArgumentException("Protocol " + protocols[i] +
362 " is not supported.");
365 enabledProtocols = protocols;
369 * Tunes the peer holding this parameters to work in client mode.
370 * @param mode if the peer is configured to work in client mode
372 protected void setUseClientMode(boolean mode) {
377 * Returns the value indicating if the parameters configured to work
380 protected boolean getUseClientMode() {
385 * Tunes the peer holding this parameters to require client authentication
387 protected void setNeedClientAuth(boolean need) {
388 need_client_auth = need;
389 // reset the want_client_auth setting
390 want_client_auth = false;
394 * Returns the value indicating if the peer with this parameters tuned
395 * to require client authentication
397 protected boolean getNeedClientAuth() {
398 return need_client_auth;
402 * Tunes the peer holding this parameters to request client authentication
404 protected void setWantClientAuth(boolean want) {
405 want_client_auth = want;
406 // reset the need_client_auth setting
407 need_client_auth = false;
411 * Returns the value indicating if the peer with this parameters
412 * tuned to request client authentication
415 protected boolean getWantClientAuth() {
416 return want_client_auth;
420 * Allows/disallows the peer holding this parameters to
421 * create new SSL session
423 protected void setEnableSessionCreation(boolean flag) {
424 enable_session_creation = flag;
428 * Returns the value indicating if the peer with this parameters
429 * allowed to cteate new SSL session
431 protected boolean getEnableSessionCreation() {
432 return enable_session_creation;
436 * Returns the clone of this object.
439 protected Object clone() {
440 // BEGIN android-changed
442 return super.clone();
443 } catch (CloneNotSupportedException e) {
444 throw new AssertionError(e);
446 // END android-changed
450 * Gets the default trust manager.
452 * TODO: Move this to a published API under dalvik.system.
454 public static X509TrustManager getDefaultTrustManager() {
455 return defaultTrustManager;