Home | History | Annotate | Download | only in jca
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package sun.security.jca;
     28 
     29 import java.security.Provider;
     30 
     31 /**
     32  * Collection of methods to get and set provider list. Also includes
     33  * special code for the provider list during JAR verification.
     34  *
     35  * @author  Andreas Sterbenz
     36  * @since   1.5
     37  */
     38 public class Providers {
     39 
     40     private static final ThreadLocal<ProviderList> threadLists =
     41         new InheritableThreadLocal<>();
     42 
     43     // number of threads currently using thread-local provider lists
     44     // tracked to allow an optimization if == 0
     45     private static volatile int threadListsUsed;
     46 
     47     // current system-wide provider list
     48     // Note volatile immutable object, so no synchronization needed.
     49     private static volatile ProviderList providerList;
     50 
     51     static {
     52         // set providerList to empty list first in case initialization somehow
     53         // triggers a getInstance() call (although that should not happen)
     54         providerList = ProviderList.EMPTY;
     55         providerList = ProviderList.fromSecurityProperties();
     56 
     57         // BEGIN Android-added: Initialize all providers and assert that this succeeds.
     58         // removeInvalid is specified to try initializing all configured providers
     59         // and removing those that aren't instantiable. This has the side effect
     60         // of eagerly initializing all providers.
     61         final int numConfiguredProviders = providerList.size();
     62         providerList = providerList.removeInvalid();
     63         if (numConfiguredProviders != providerList.size()) {
     64             throw new AssertionError("Unable to configure default providers");
     65         }
     66         // END Android-added: Initialize all providers and assert that this succeeds.
     67     }
     68 
     69     private Providers() {
     70         // empty
     71     }
     72 
     73     // we need special handling to resolve circularities when loading
     74     // signed JAR files during startup. The code below is part of that.
     75 
     76     // Basically, before we load data from a signed JAR file, we parse
     77     // the PKCS#7 file and verify the signature. We need a
     78     // CertificateFactory, Signatures, etc. to do that. We have to make
     79     // sure that we do not try to load the implementation from the JAR
     80     // file we are just verifying.
     81     //
     82     // To avoid that, we use different provider settings during JAR
     83     // verification.  However, we do not want those provider settings to
     84     // interfere with other parts of the system. Therefore, we make them local
     85     // to the Thread executing the JAR verification code.
     86     //
     87     // The code here is used by sun.security.util.SignatureFileVerifier.
     88     // See there for details.
     89 
     90     private static final String BACKUP_PROVIDER_CLASSNAME =
     91         "sun.security.provider.VerificationProvider";
     92 
     93     // Hardcoded classnames of providers to use for JAR verification.
     94     // MUST NOT be on the bootclasspath and not in signed JAR files.
     95     private static final String[] jarVerificationProviders = {
     96         // BEGIN Android-changed: Use Conscrypt and BC, not the sun.security providers.
     97         /*
     98         "sun.security.provider.Sun",
     99         "sun.security.rsa.SunRsaSign",
    100         // Note: SunEC *is* in a signed JAR file, but it's not signed
    101         // by EC itself. So it's still safe to be listed here.
    102         "sun.security.ec.SunEC",
    103         */
    104         "com.android.org.conscrypt.OpenSSLProvider",
    105         "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider",
    106         "com.android.org.conscrypt.JSSEProvider",
    107         // END Android-changed: Use Conscrypt and BC, not the sun.security providers.
    108         BACKUP_PROVIDER_CLASSNAME,
    109     };
    110 
    111     // Return to Sun provider or its backup.
    112     // This method should only be called by
    113     // sun.security.util.ManifestEntryVerifier and java.security.SecureRandom.
    114     public static Provider getSunProvider() {
    115         try {
    116             Class<?> clazz = Class.forName(jarVerificationProviders[0]);
    117             return (Provider)clazz.newInstance();
    118         } catch (Exception e) {
    119             try {
    120                 Class<?> clazz = Class.forName(BACKUP_PROVIDER_CLASSNAME);
    121                 return (Provider)clazz.newInstance();
    122             } catch (Exception ee) {
    123                 throw new RuntimeException("Sun provider not found", e);
    124             }
    125         }
    126     }
    127 
    128     /**
    129      * Start JAR verification. This sets a special provider list for
    130      * the current thread. You MUST save the return value from this
    131      * method and you MUST call stopJarVerification() with that object
    132      * once you are done.
    133      */
    134     public static Object startJarVerification() {
    135         ProviderList currentList = getProviderList();
    136         ProviderList jarList = currentList.getJarList(jarVerificationProviders);
    137         // return the old thread-local provider list, usually null
    138         return beginThreadProviderList(jarList);
    139     }
    140 
    141     /**
    142      * Stop JAR verification. Call once you have completed JAR verification.
    143      */
    144     public static void stopJarVerification(Object obj) {
    145         // restore old thread-local provider list
    146         endThreadProviderList((ProviderList)obj);
    147     }
    148 
    149     /**
    150      * Return the current ProviderList. If the thread-local list is set,
    151      * it is returned. Otherwise, the system wide list is returned.
    152      */
    153     public static ProviderList getProviderList() {
    154         ProviderList list = getThreadProviderList();
    155         if (list == null) {
    156             list = getSystemProviderList();
    157         }
    158         return list;
    159     }
    160 
    161     /**
    162      * Set the current ProviderList. Affects the thread-local list if set,
    163      * otherwise the system wide list.
    164      */
    165     public static void setProviderList(ProviderList newList) {
    166         if (getThreadProviderList() == null) {
    167             setSystemProviderList(newList);
    168         } else {
    169             changeThreadProviderList(newList);
    170         }
    171     }
    172 
    173     /**
    174      * Get the full provider list with invalid providers (those that
    175      * could not be loaded) removed. This is the list we need to
    176      * present to applications.
    177      */
    178     public static ProviderList getFullProviderList() {
    179         ProviderList list;
    180         synchronized (Providers.class) {
    181             list = getThreadProviderList();
    182             if (list != null) {
    183                 ProviderList newList = list.removeInvalid();
    184                 if (newList != list) {
    185                     changeThreadProviderList(newList);
    186                     list = newList;
    187                 }
    188                 return list;
    189             }
    190         }
    191         list = getSystemProviderList();
    192         ProviderList newList = list.removeInvalid();
    193         if (newList != list) {
    194             setSystemProviderList(newList);
    195             list = newList;
    196         }
    197         return list;
    198     }
    199 
    200     private static ProviderList getSystemProviderList() {
    201         return providerList;
    202     }
    203 
    204     private static void setSystemProviderList(ProviderList list) {
    205         providerList = list;
    206     }
    207 
    208     public static ProviderList getThreadProviderList() {
    209         // avoid accessing the threadlocal if none are currently in use
    210         // (first use of ThreadLocal.get() for a Thread allocates a Map)
    211         if (threadListsUsed == 0) {
    212             return null;
    213         }
    214         return threadLists.get();
    215     }
    216 
    217     // Change the thread local provider list. Use only if the current thread
    218     // is already using a thread local list and you want to change it in place.
    219     // In other cases, use the begin/endThreadProviderList() methods.
    220     private static void changeThreadProviderList(ProviderList list) {
    221         threadLists.set(list);
    222     }
    223 
    224     /**
    225      * Methods to manipulate the thread local provider list. It is for use by
    226      * JAR verification (see above) and the SunJSSE FIPS mode only.
    227      *
    228      * It should be used as follows:
    229      *
    230      *   ProviderList list = ...;
    231      *   ProviderList oldList = Providers.beginThreadProviderList(list);
    232      *   try {
    233      *     // code that needs thread local provider list
    234      *   } finally {
    235      *     Providers.endThreadProviderList(oldList);
    236      *   }
    237      *
    238      */
    239 
    240     public static synchronized ProviderList beginThreadProviderList(ProviderList list) {
    241         if (ProviderList.debug != null) {
    242             ProviderList.debug.println("ThreadLocal providers: " + list);
    243         }
    244         ProviderList oldList = threadLists.get();
    245         threadListsUsed++;
    246         threadLists.set(list);
    247         return oldList;
    248     }
    249 
    250     public static synchronized void endThreadProviderList(ProviderList list) {
    251         if (list == null) {
    252             if (ProviderList.debug != null) {
    253                 ProviderList.debug.println("Disabling ThreadLocal providers");
    254             }
    255             threadLists.remove();
    256         } else {
    257             if (ProviderList.debug != null) {
    258                 ProviderList.debug.println
    259                     ("Restoring previous ThreadLocal providers: " + list);
    260             }
    261             threadLists.set(list);
    262         }
    263         threadListsUsed--;
    264     }
    265 
    266 }
    267