1 /*
   2  * Copyright (c) 1999, 2014, 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 
  27 package sun.security.ssl;
  28 
  29 import 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  */
  58 public 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/PKIX key/trust factories, " +
  64         "SSLv3/TLSv1/TLSv1.1/TLSv1.2)";
  65 
  66     private static String fipsInfo =
  67         "Sun JSSE provider (FIPS mode, crypto provider ";
  68 
  69     // tri-valued flag:
  70     // null  := no final decision made
  71     // false := data structures initialized in non-FIPS mode
  72     // true  := data structures initialized in FIPS mode
  73     private static Boolean fips;
  74 
  75     // the FIPS certificate crypto provider that we use to perform all crypto
  76     // operations. null in non-FIPS mode
  77     static java.security.Provider cryptoProvider;
  78 
  79     protected static synchronized boolean isFIPS() {
  80         if (fips == null) {
  81             fips = false;
  82         }
  83         return fips;
  84     }
  85 
  86     // ensure we can use FIPS mode using the specified crypto provider.
  87     // enable FIPS mode if not already enabled.
  88     private static synchronized void ensureFIPS(java.security.Provider p) {
  89         if (fips == null) {
  90             fips = true;
  91             cryptoProvider = p;
  92         } else {
  93             if (fips == false) {
  94                 throw new ProviderException
  95                     ("SunJSSE already initialized in non-FIPS mode");
  96             }
  97             if (cryptoProvider != p) {
  98                 throw new ProviderException
  99                     ("SunJSSE already initialized with FIPS crypto provider "
 100                     + cryptoProvider);
 101             }
 102         }
 103     }
 104 
 105     // standard constructor
 106     protected SunJSSE() {
 107         super("SunJSSE", 1.9d, info);
 108         subclassCheck();
 109         if (Boolean.TRUE.equals(fips)) {
 110             throw new ProviderException
 111                 ("SunJSSE is already initialized in FIPS mode");
 112         }
 113         registerAlgorithms(false);
 114     }
 115 
 116     // preferred constructor to enable FIPS mode at runtime
 117     protected SunJSSE(java.security.Provider cryptoProvider){
 118         this(checkNull(cryptoProvider), cryptoProvider.getName());
 119     }
 120 
 121     // constructor to enable FIPS mode from java.security file
 122     protected SunJSSE(String cryptoProvider){
 123         this(null, checkNull(cryptoProvider));
 124     }
 125 
 126     private static <T> T checkNull(T t) {
 127         if (t == null) {
 128             throw new ProviderException("cryptoProvider must not be null");
 129         }
 130         return t;
 131     }
 132 
 133     private SunJSSE(java.security.Provider cryptoProvider,
 134             String providerName) {
 135         super("SunJSSE", 1.9d, fipsInfo + providerName + ")");
 136         subclassCheck();
 137         if (cryptoProvider == null) {
 138             // Calling Security.getProvider() will cause other providers to be
 139             // loaded. That is not good but unavoidable here.
 140             cryptoProvider = Security.getProvider(providerName);
 141             if (cryptoProvider == null) {
 142                 throw new ProviderException
 143                     ("Crypto provider not installed: " + providerName);
 144             }
 145         }
 146         ensureFIPS(cryptoProvider);
 147         registerAlgorithms(true);
 148     }
 149 
 150     private void registerAlgorithms(final boolean isfips) {
 151         AccessController.doPrivileged(new PrivilegedAction<Object>() {
 152             @Override
 153             public Object run() {
 154                 doRegister(isfips);
 155                 return null;
 156             }
 157         });
 158     }
 159 
 160     private void doRegister(boolean isfips) {
 161         if (isfips == false) {
 162             put("KeyFactory.RSA",
 163                 "sun.security.rsa.RSAKeyFactory");
 164             put("Alg.Alias.KeyFactory.1.2.840.113549.1.1", "RSA");
 165             put("Alg.Alias.KeyFactory.OID.1.2.840.113549.1.1", "RSA");
 166 
 167             put("KeyPairGenerator.RSA",
 168                 "sun.security.rsa.RSAKeyPairGenerator");
 169             put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
 170             put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
 171 
 172             put("Signature.MD2withRSA",
 173                 "sun.security.rsa.RSASignature$MD2withRSA");
 174             put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
 175             put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2",
 176                 "MD2withRSA");
 177 
 178             put("Signature.MD5withRSA",
 179                 "sun.security.rsa.RSASignature$MD5withRSA");
 180             put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
 181             put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4",
 182                 "MD5withRSA");
 183 
 184             put("Signature.SHA1withRSA",
 185                 "sun.security.rsa.RSASignature$SHA1withRSA");
 186             put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
 187             put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5",
 188                 "SHA1withRSA");
 189             put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
 190             put("Alg.Alias.Signature.OID.1.3.14.3.2.29", "SHA1withRSA");
 191 
 192         }
 193         put("Signature.MD5andSHA1withRSA",
 194             "sun.security.ssl.RSASignature");
 195 
 196         put("KeyManagerFactory.SunX509",
 197             "sun.security.ssl.KeyManagerFactoryImpl$SunX509");
 198         put("KeyManagerFactory.NewSunX509",
 199             "sun.security.ssl.KeyManagerFactoryImpl$X509");
 200         put("Alg.Alias.KeyManagerFactory.PKIX", "NewSunX509");
 201 
 202         put("TrustManagerFactory.SunX509",
 203             "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory");
 204         put("TrustManagerFactory.PKIX",
 205             "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory");
 206         put("Alg.Alias.TrustManagerFactory.SunPKIX", "PKIX");
 207         put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
 208         put("Alg.Alias.TrustManagerFactory.X.509", "PKIX");
 209 
 210         put("SSLContext.TLSv1",
 211             "sun.security.ssl.SSLContextImpl$TLS10Context");
 212         put("SSLContext.TLSv1.1",
 213             "sun.security.ssl.SSLContextImpl$TLS11Context");
 214         put("SSLContext.TLSv1.2",
 215             "sun.security.ssl.SSLContextImpl$TLS12Context");
 216         put("SSLContext.TLS",
 217             "sun.security.ssl.SSLContextImpl$TLSContext");
 218         if (isfips == false) {
 219             put("Alg.Alias.SSLContext.SSL", "TLS");
 220             put("Alg.Alias.SSLContext.SSLv3", "TLSv1");
 221         }
 222 
 223         put("SSLContext.Default",
 224             "sun.security.ssl.SSLContextImpl$DefaultSSLContext");
 225 
 226         /*
 227          * KeyStore
 228          */
 229         put("KeyStore.PKCS12",
 230             "sun.security.pkcs12.PKCS12KeyStore");
 231     }
 232 
 233     private void subclassCheck() {
 234         if (getClass() != com.sun.net.ssl.internal.ssl.Provider.class) {
 235             throw new AssertionError("Illegal subclass: " + getClass());
 236         }
 237     }
 238 
 239     @Override
 240     protected final void finalize() throws Throwable {
 241         // empty
 242         super.finalize();
 243     }
 244 
 245 }