1/*
2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27package sun.security.ssl;
28
29import java.security.*;
30
31/**
32 * The JSSE provider.
33 *
34 * The RSA implementation has been removed from JSSE, but we still need to
35 * register the same algorithms for compatibility. We just point to the RSA
36 * implementation in the SunRsaSign provider. This works because all classes
37 * are in the bootclasspath and therefore loaded by the same classloader.
38 *
39 * SunJSSE now supports an experimental FIPS compliant mode when used with an
40 * appropriate FIPS certified crypto provider. In FIPS mode, we:
41 *  . allow only TLS 1.0 or later
42 *  . allow only FIPS approved ciphersuites
43 *  . perform all crypto in the FIPS crypto provider
44 *
45 * It is currently not possible to use both FIPS compliant SunJSSE and
46 * standard JSSE at the same time because of the various static data structures
47 * we use.
48 *
49 * However, we do want to allow FIPS mode to be enabled at runtime and without
50 * editing the java.security file. That means we need to allow
51 * Security.removeProvider("SunJSSE") to work, which creates an instance of
52 * this class in non-FIPS mode. That is why we delay the selection of the mode
53 * as long as possible. This is until we open an SSL/TLS connection and the
54 * data structures need to be initialized or until SunJSSE is initialized in
55 * FIPS mode.
56 *
57 */
58public abstract class SunJSSE extends java.security.Provider {
59
60    private static final long serialVersionUID = 3231825739635378733L;
61
62    private static String info = "Sun JSSE provider" +
63        "(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)";
64
65    private static String fipsInfo =
66        "Sun JSSE provider (FIPS mode, crypto provider ";
67
68    // tri-valued flag:
69    // null  := no final decision made
70    // false := data structures initialized in non-FIPS mode
71    // true  := data structures initialized in FIPS mode
72    private static Boolean fips;
73
74    // the FIPS certificate crypto provider that we use to perform all crypto
75    // operations. null in non-FIPS mode
76    static java.security.Provider cryptoProvider;
77
78    protected static synchronized boolean isFIPS() {
79        if (fips == null) {
80            fips = false;
81        }
82        return fips;
83    }
84
85    // ensure we can use FIPS mode using the specified crypto provider.
86    // enable FIPS mode if not already enabled.
87    private static synchronized void ensureFIPS(java.security.Provider p) {
88        if (fips == null) {
89            fips = true;
90            cryptoProvider = p;
91        } else {
92            if (fips == false) {
93                throw new ProviderException
94                    ("SunJSSE already initialized in non-FIPS mode");
95            }
96            if (cryptoProvider != p) {
97                throw new ProviderException
98                    ("SunJSSE already initialized with FIPS crypto provider "
99                    + cryptoProvider);
100            }
101        }
102    }
103
104    // standard constructor
105    protected SunJSSE() {
106        super("SunJSSE", 1.7d, info);
107        subclassCheck();
108        if (Boolean.TRUE.equals(fips)) {
109            throw new ProviderException
110                ("SunJSSE is already initialized in FIPS mode");
111        }
112        registerAlgorithms(false);
113    }
114
115    // prefered constructor to enable FIPS mode at runtime
116    protected SunJSSE(java.security.Provider cryptoProvider){
117        this(checkNull(cryptoProvider), cryptoProvider.getName());
118    }
119
120    // constructor to enable FIPS mode from java.security file
121    protected SunJSSE(String cryptoProvider){
122        this(null, checkNull(cryptoProvider));
123    }
124
125    private static <T> T checkNull(T t) {
126        if (t == null) {
127            throw new ProviderException("cryptoProvider must not be null");
128        }
129        return t;
130    }
131
132    private SunJSSE(java.security.Provider cryptoProvider,
133            String providerName) {
134        super("SunJSSE", 1.6d, fipsInfo + providerName + ")");
135        subclassCheck();
136        if (cryptoProvider == null) {
137            // Calling Security.getProvider() will cause other providers to be
138            // loaded. That is not good but unavoidable here.
139            cryptoProvider = Security.getProvider(providerName);
140            if (cryptoProvider == null) {
141                throw new ProviderException
142                    ("Crypto provider not installed: " + providerName);
143            }
144        }
145        ensureFIPS(cryptoProvider);
146        registerAlgorithms(true);
147    }
148
149    private void registerAlgorithms(final boolean isfips) {
150        AccessController.doPrivileged(new PrivilegedAction<Object>() {
151            public Object run() {
152                doRegister(isfips);
153                return null;
154            }
155        });
156    }
157
158    private void doRegister(boolean isfips) {
159        if (isfips == false) {
160            put("KeyFactory.RSA",
161                "sun.security.rsa.RSAKeyFactory");
162            put("Alg.Alias.KeyFactory.1.2.840.113549.1.1", "RSA");
163            put("Alg.Alias.KeyFactory.OID.1.2.840.113549.1.1", "RSA");
164
165            put("KeyPairGenerator.RSA",
166                "sun.security.rsa.RSAKeyPairGenerator");
167            put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
168            put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
169
170            put("Signature.MD2withRSA",
171                "sun.security.rsa.RSASignature$MD2withRSA");
172            put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
173            put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2",
174                "MD2withRSA");
175
176            put("Signature.MD5withRSA",
177                "sun.security.rsa.RSASignature$MD5withRSA");
178            put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
179            put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4",
180                "MD5withRSA");
181
182            put("Signature.SHA1withRSA",
183                "sun.security.rsa.RSASignature$SHA1withRSA");
184            put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
185            put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5",
186                "SHA1withRSA");
187            put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
188            put("Alg.Alias.Signature.OID.1.3.14.3.2.29", "SHA1withRSA");
189
190        }
191        put("Signature.MD5andSHA1withRSA",
192            "sun.security.ssl.RSASignature");
193
194        put("KeyManagerFactory.SunX509",
195            "sun.security.ssl.KeyManagerFactoryImpl$SunX509");
196        put("KeyManagerFactory.NewSunX509",
197            "sun.security.ssl.KeyManagerFactoryImpl$X509");
198        put("Alg.Alias.KeyManagerFactory.PKIX", "NewSunX509");
199
200        put("TrustManagerFactory.SunX509",
201            "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory");
202        put("TrustManagerFactory.PKIX",
203            "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory");
204        put("Alg.Alias.TrustManagerFactory.SunPKIX", "PKIX");
205        put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
206        put("Alg.Alias.TrustManagerFactory.X.509", "PKIX");
207
208        put("SSLContext.TLSv1",
209            "sun.security.ssl.SSLContextImpl$TLS10Context");
210        put("Alg.Alias.SSLContext.TLS", "TLSv1");
211        if (isfips == false) {
212            put("Alg.Alias.SSLContext.SSL", "TLSv1");
213            put("Alg.Alias.SSLContext.SSLv3", "TLSv1");
214        }
215
216        put("SSLContext.TLSv1.1",
217            "sun.security.ssl.SSLContextImpl$TLS11Context");
218        put("SSLContext.TLSv1.2",
219            "sun.security.ssl.SSLContextImpl$TLS12Context");
220        put("SSLContext.Default",
221            "sun.security.ssl.SSLContextImpl$DefaultSSLContext");
222
223        /*
224         * KeyStore
225         */
226        put("KeyStore.PKCS12",
227            "sun.security.pkcs12.PKCS12KeyStore");
228    }
229
230    private void subclassCheck() {
231        if (getClass() != com.sun.net.ssl.internal.ssl.Provider.class) {
232            throw new AssertionError("Illegal subclass: " + getClass());
233        }
234    }
235
236    @Override
237    protected final void finalize() throws Throwable {
238        // empty
239        super.finalize();
240    }
241
242}
243