Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/crypto/JceSecurity.java
38829 views
1
/*
2
* Copyright (c) 1997, 2017, 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
package javax.crypto;
27
28
import java.util.*;
29
import java.util.jar.*;
30
import java.io.*;
31
import java.net.URL;
32
import java.nio.file.*;
33
import java.security.*;
34
35
import java.security.Provider.Service;
36
37
import sun.security.jca.*;
38
import sun.security.jca.GetInstance.Instance;
39
import sun.security.util.Debug;
40
41
/**
42
* This class instantiates implementations of JCE engine classes from
43
* providers registered with the java.security.Security object.
44
*
45
* @author Jan Luehe
46
* @author Sharon Liu
47
* @since 1.4
48
*/
49
50
final class JceSecurity {
51
52
static final SecureRandom RANDOM = new SecureRandom();
53
54
// The defaultPolicy and exemptPolicy will be set up
55
// in the static initializer.
56
private static CryptoPermissions defaultPolicy = null;
57
private static CryptoPermissions exemptPolicy = null;
58
59
// Map<Provider,?> of the providers we already have verified
60
// value == PROVIDER_VERIFIED is successfully verified
61
// value is failure cause Exception in error case
62
private final static Map<Provider, Object> verificationResults =
63
new IdentityHashMap<>();
64
65
// Map<Provider,?> of the providers currently being verified
66
private final static Map<Provider, Object> verifyingProviders =
67
new IdentityHashMap<>();
68
69
private static final boolean isRestricted;
70
71
private static final Debug debug =
72
Debug.getInstance("jca", "Cipher");
73
74
/*
75
* Don't let anyone instantiate this.
76
*/
77
private JceSecurity() {
78
}
79
80
static {
81
try {
82
AccessController.doPrivileged(
83
new PrivilegedExceptionAction<Object>() {
84
public Object run() throws Exception {
85
setupJurisdictionPolicies();
86
return null;
87
}
88
});
89
90
isRestricted = defaultPolicy.implies(
91
CryptoAllPermission.INSTANCE) ? false : true;
92
} catch (Exception e) {
93
throw new SecurityException(
94
"Can not initialize cryptographic mechanism", e);
95
}
96
}
97
98
static Instance getInstance(String type, Class<?> clazz, String algorithm,
99
String provider) throws NoSuchAlgorithmException,
100
NoSuchProviderException {
101
Service s = GetInstance.getService(type, algorithm, provider);
102
Exception ve = getVerificationResult(s.getProvider());
103
if (ve != null) {
104
String msg = "JCE cannot authenticate the provider " + provider;
105
throw (NoSuchProviderException)
106
new NoSuchProviderException(msg).initCause(ve);
107
}
108
return GetInstance.getInstance(s, clazz);
109
}
110
111
static Instance getInstance(String type, Class<?> clazz, String algorithm,
112
Provider provider) throws NoSuchAlgorithmException {
113
Service s = GetInstance.getService(type, algorithm, provider);
114
Exception ve = JceSecurity.getVerificationResult(provider);
115
if (ve != null) {
116
String msg = "JCE cannot authenticate the provider "
117
+ provider.getName();
118
throw new SecurityException(msg, ve);
119
}
120
return GetInstance.getInstance(s, clazz);
121
}
122
123
static Instance getInstance(String type, Class<?> clazz, String algorithm)
124
throws NoSuchAlgorithmException {
125
List<Service> services = GetInstance.getServices(type, algorithm);
126
NoSuchAlgorithmException failure = null;
127
for (Service s : services) {
128
if (canUseProvider(s.getProvider()) == false) {
129
// allow only signed providers
130
continue;
131
}
132
try {
133
Instance instance = GetInstance.getInstance(s, clazz);
134
return instance;
135
} catch (NoSuchAlgorithmException e) {
136
failure = e;
137
}
138
}
139
throw new NoSuchAlgorithmException("Algorithm " + algorithm
140
+ " not available", failure);
141
}
142
143
/**
144
* Verify if the JAR at URL codeBase is a signed exempt application
145
* JAR file and returns the permissions bundled with the JAR.
146
*
147
* @throws Exception on error
148
*/
149
static CryptoPermissions verifyExemptJar(URL codeBase) throws Exception {
150
JarVerifier jv = new JarVerifier(codeBase, true);
151
jv.verify();
152
return jv.getPermissions();
153
}
154
155
/**
156
* Verify if the JAR at URL codeBase is a signed provider JAR file.
157
*
158
* @throws Exception on error
159
*/
160
static void verifyProviderJar(URL codeBase) throws Exception {
161
// Verify the provider JAR file and all
162
// supporting JAR files if there are any.
163
JarVerifier jv = new JarVerifier(codeBase, false);
164
jv.verify();
165
}
166
167
private final static Object PROVIDER_VERIFIED = Boolean.TRUE;
168
169
/*
170
* Verify that the provider JAR files are signed properly, which
171
* means the signer's certificate can be traced back to a
172
* JCE trusted CA.
173
* Return null if ok, failure Exception if verification failed.
174
*/
175
static synchronized Exception getVerificationResult(Provider p) {
176
Object o = verificationResults.get(p);
177
if (o == PROVIDER_VERIFIED) {
178
return null;
179
} else if (o != null) {
180
return (Exception)o;
181
}
182
if (verifyingProviders.get(p) != null) {
183
// this method is static synchronized, must be recursion
184
// return failure now but do not save the result
185
return new NoSuchProviderException("Recursion during verification");
186
}
187
try {
188
verifyingProviders.put(p, Boolean.FALSE);
189
URL providerURL = getCodeBase(p.getClass());
190
verifyProviderJar(providerURL);
191
// Verified ok, cache result
192
verificationResults.put(p, PROVIDER_VERIFIED);
193
return null;
194
} catch (Exception e) {
195
verificationResults.put(p, e);
196
return e;
197
} finally {
198
verifyingProviders.remove(p);
199
}
200
}
201
202
// return whether this provider is properly signed and can be used by JCE
203
static boolean canUseProvider(Provider p) {
204
return getVerificationResult(p) == null;
205
}
206
207
// dummy object to represent null
208
private static final URL NULL_URL;
209
210
static {
211
try {
212
NULL_URL = new URL("http://null.oracle.com/");
213
} catch (Exception e) {
214
throw new RuntimeException(e);
215
}
216
}
217
218
// reference to a Map we use as a cache for codebases
219
private static final Map<Class<?>, URL> codeBaseCacheRef =
220
new WeakHashMap<>();
221
222
/*
223
* Returns the CodeBase for the given class.
224
*/
225
static URL getCodeBase(final Class<?> clazz) {
226
synchronized (codeBaseCacheRef) {
227
URL url = codeBaseCacheRef.get(clazz);
228
if (url == null) {
229
url = AccessController.doPrivileged(new PrivilegedAction<URL>() {
230
public URL run() {
231
ProtectionDomain pd = clazz.getProtectionDomain();
232
if (pd != null) {
233
CodeSource cs = pd.getCodeSource();
234
if (cs != null) {
235
return cs.getLocation();
236
}
237
}
238
return NULL_URL;
239
}
240
});
241
codeBaseCacheRef.put(clazz, url);
242
}
243
return (url == NULL_URL) ? null : url;
244
}
245
}
246
247
/*
248
* This is called from within an doPrivileged block.
249
*
250
* Following logic is used to decide what policy files are selected.
251
*
252
* If the new Security property (crypto.policy) is set in the
253
* java.security file, or has been set dynamically using the
254
* Security.setProperty() call before the JCE framework has
255
* been initialized, that setting will be used.
256
* Remember - this property is not defined by default. A conscious
257
* user edit or an application call is required.
258
*
259
* Otherwise, if user has policy jar files installed in the legacy
260
* <java-home>/lib/security/ directory, the JDK will honor whatever
261
* setting is set by those policy files. (legacy/current behavior)
262
*
263
* If none of the above 2 conditions are met, the JDK will default
264
* to using the unlimited crypto policy files found in the
265
* <java-home>/lib/security/policy/unlimited/ directory
266
*/
267
private static void setupJurisdictionPolicies() throws Exception {
268
// Sanity check the crypto.policy Security property. Single
269
// directory entry, no pseudo-directories (".", "..", leading/trailing
270
// path separators). normalize()/getParent() will help later.
271
String javaHomeProperty = System.getProperty("java.home");
272
String cryptoPolicyProperty = Security.getProperty("crypto.policy");
273
Path cpPath = (cryptoPolicyProperty == null) ? null :
274
Paths.get(cryptoPolicyProperty);
275
276
if ((cpPath != null) && ((cpPath.getNameCount() != 1) ||
277
(cpPath.compareTo(cpPath.getFileName())) != 0)) {
278
throw new SecurityException(
279
"Invalid policy directory name format: " +
280
cryptoPolicyProperty);
281
}
282
283
if (cpPath == null) {
284
// Security property is not set, use default path
285
cpPath = Paths.get(javaHomeProperty, "lib", "security");
286
} else {
287
// populate with java.home
288
cpPath = Paths.get(javaHomeProperty, "lib", "security",
289
"policy", cryptoPolicyProperty);
290
}
291
292
if (debug != null) {
293
debug.println("crypto policy directory: " + cpPath);
294
}
295
296
File exportJar = new File(cpPath.toFile(),"US_export_policy.jar");
297
File importJar = new File(cpPath.toFile(),"local_policy.jar");
298
299
if (cryptoPolicyProperty == null && (!exportJar.exists() ||
300
!importJar.exists())) {
301
// Compatibility set up. If crypto.policy is not defined.
302
// check to see if legacy jars exist in lib directory. If
303
// they don't exist, we default to unlimited policy mode.
304
cpPath = Paths.get(
305
javaHomeProperty, "lib", "security", "policy", "unlimited");
306
// point to the new jar files in limited directory
307
exportJar = new File(cpPath.toFile(),"US_export_policy.jar");
308
importJar = new File(cpPath.toFile(),"local_policy.jar");
309
}
310
311
URL jceCipherURL = ClassLoader.getSystemResource
312
("javax/crypto/Cipher.class");
313
314
if ((jceCipherURL == null) ||
315
!exportJar.exists() || !importJar.exists()) {
316
throw new SecurityException
317
("Cannot locate policy or framework files!");
318
}
319
320
// Read jurisdiction policies.
321
CryptoPermissions defaultExport = new CryptoPermissions();
322
CryptoPermissions exemptExport = new CryptoPermissions();
323
loadPolicies(exportJar, defaultExport, exemptExport);
324
325
CryptoPermissions defaultImport = new CryptoPermissions();
326
CryptoPermissions exemptImport = new CryptoPermissions();
327
loadPolicies(importJar, defaultImport, exemptImport);
328
329
// Merge the export and import policies for default applications.
330
if (defaultExport.isEmpty() || defaultImport.isEmpty()) {
331
throw new SecurityException("Missing mandatory jurisdiction " +
332
"policy files");
333
}
334
defaultPolicy = defaultExport.getMinimum(defaultImport);
335
336
// Merge the export and import policies for exempt applications.
337
if (exemptExport.isEmpty()) {
338
exemptPolicy = exemptImport.isEmpty() ? null : exemptImport;
339
} else {
340
exemptPolicy = exemptExport.getMinimum(exemptImport);
341
}
342
}
343
344
/**
345
* Load the policies from the specified file. Also checks that the
346
* policies are correctly signed.
347
*/
348
private static void loadPolicies(File jarPathName,
349
CryptoPermissions defaultPolicy,
350
CryptoPermissions exemptPolicy)
351
throws Exception {
352
353
JarFile jf = new JarFile(jarPathName);
354
355
Enumeration<JarEntry> entries = jf.entries();
356
while (entries.hasMoreElements()) {
357
JarEntry je = entries.nextElement();
358
InputStream is = null;
359
try {
360
if (je.getName().startsWith("default_")) {
361
is = jf.getInputStream(je);
362
defaultPolicy.load(is);
363
} else if (je.getName().startsWith("exempt_")) {
364
is = jf.getInputStream(je);
365
exemptPolicy.load(is);
366
} else {
367
continue;
368
}
369
} finally {
370
if (is != null) {
371
is.close();
372
}
373
}
374
375
// Enforce the signer restraint, i.e. signer of JCE framework
376
// jar should also be the signer of the two jurisdiction policy
377
// jar files.
378
JarVerifier.verifyPolicySigned(je.getCertificates());
379
}
380
// Close and nullify the JarFile reference to help GC.
381
jf.close();
382
jf = null;
383
}
384
385
static CryptoPermissions getDefaultPolicy() {
386
return defaultPolicy;
387
}
388
389
static CryptoPermissions getExemptPolicy() {
390
return exemptPolicy;
391
}
392
393
static boolean isRestricted() {
394
return isRestricted;
395
}
396
}
397
398