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