Skip to content

Commit cabc6c2

Browse files
Initialize security providers at run time.
Add a test for security provider run time registration. Add entry to a CHANGELOG.md Parse java.security.properties file at run time.
1 parent 155b6f3 commit cabc6c2

File tree

9 files changed

+468
-289
lines changed

9 files changed

+468
-289
lines changed

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This changelog summarizes major changes to GraalVM Native Image.
1111
* (GR-61492) The experimental JDWP option is now present in standard GraalVM builds.
1212
* (GR-55222) Enabled lazy deoptimization of runtime-compiled code, which reduces memory used for deoptimization. Can be turned off with `-H:-LazyDeoptimization`.
1313
* (GR-54953) Add the experimental option `-H:Preserve` that makes the program work correctly without providing reachability metadata. Correctness is achieved by preserving all classes, resources, and reflection metadata in the image. Usage: `-H:Preserve=[all|none|module=<module>|package=<package>|package=<package-wildcard>|path=<cp-entry>][,...]`.
14+
* (GR-57827) Move the initialization of security providers from build time to runtime.
1415

1516
## GraalVM for JDK 24 (Internal Version 24.2.0)
1617
* (GR-59717) Added `DuringSetupAccess.registerObjectReachabilityHandler` to allow registering a callback that is executed when an object of a specified type is marked as reachable during heap scanning.

substratevm/mx.substratevm/suite.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,12 @@
329329
"sun.reflect.generics.reflectiveObjects",
330330
"sun.reflect.generics.repository",
331331
"sun.reflect.generics.tree",
332+
"sun.security.rsa",
332333
"sun.security.jca",
333334
"sun.security.ssl",
334335
"sun.security.util",
336+
"sun.security.provider",
337+
"com.sun.crypto.provider",
335338
"sun.text.spi",
336339
"sun.util",
337340
"sun.util.locale",
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/*
2+
* Copyright (c) 2024, 2024, 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 com.oracle.svm.core.jdk;
27+
28+
import java.lang.reflect.Constructor;
29+
import java.lang.reflect.InvocationTargetException;
30+
import java.security.Provider;
31+
import java.util.Collections;
32+
import java.util.HashMap;
33+
import java.util.HashSet;
34+
import java.util.List;
35+
import java.util.Map;
36+
import java.util.Properties;
37+
import java.util.Set;
38+
39+
import org.graalvm.nativeimage.ImageSingletons;
40+
import org.graalvm.nativeimage.Platform;
41+
import org.graalvm.nativeimage.Platforms;
42+
43+
import com.oracle.svm.core.util.VMError;
44+
45+
import jdk.graal.compiler.api.replacements.Fold;
46+
47+
/**
48+
* The class that holds various build-time and runtime structures necessary for security providers.
49+
*/
50+
public final class SecurityProvidersSupport {
51+
/**
52+
* A set of providers to be loaded using the service-loading technique at runtime, but not
53+
* discoverable at build-time when processing services in the feature (see
54+
* ServiceLoaderFeature#handleServiceClassIsReachable). This occurs when the user does not
55+
* explicitly request a provider, but the provider is discovered via static analysis from a
56+
* JCA-compliant security service used by the user's code (see
57+
* SecurityServicesFeature#registerServiceReachabilityHandlers).
58+
*/
59+
@Platforms(Platform.HOSTED_ONLY.class)//
60+
private final Set<String> markedAsNotLoaded = Collections.synchronizedSet(new HashSet<>());
61+
62+
/** Set of fully qualified provider names, required for runtime resource access. */
63+
private final Set<String> userRequestedSecurityProviders = Collections.synchronizedSet(new HashSet<>());
64+
65+
/**
66+
* A map of providers, identified by their names (see {@link Provider#getName()}), and the
67+
* results of their verification (see javax.crypto.JceSecurity#getVerificationResult). This
68+
* structure is used instead of the (see javax.crypto.JceSecurity#verifyingProviders) map to
69+
* avoid keeping provider objects in the image heap.
70+
*/
71+
private final Map<String, Object> verifiedSecurityProviders = Collections.synchronizedMap(new HashMap<>());
72+
73+
private Properties savedInitialSecurityProperties;
74+
75+
private Constructor<?> sunECConstructor;
76+
77+
@Platforms(Platform.HOSTED_ONLY.class)
78+
public SecurityProvidersSupport(List<String> userRequestedSecurityProviders) {
79+
this.userRequestedSecurityProviders.addAll(userRequestedSecurityProviders);
80+
}
81+
82+
@Fold
83+
public static SecurityProvidersSupport singleton() {
84+
return ImageSingletons.lookup(SecurityProvidersSupport.class);
85+
}
86+
87+
@Platforms(Platform.HOSTED_ONLY.class)
88+
public void addVerifiedSecurityProvider(String key, Object value) {
89+
verifiedSecurityProviders.put(key, value);
90+
}
91+
92+
public Object getSecurityProviderVerificationResult(String key) {
93+
return verifiedSecurityProviders.get(key);
94+
}
95+
96+
@Platforms(Platform.HOSTED_ONLY.class)
97+
public void markSecurityProviderAsNotLoaded(String provider) {
98+
markedAsNotLoaded.add(provider);
99+
}
100+
101+
@Platforms(Platform.HOSTED_ONLY.class)
102+
public boolean isSecurityProviderNotLoaded(String provider) {
103+
return markedAsNotLoaded.contains(provider);
104+
}
105+
106+
@Platforms(Platform.HOSTED_ONLY.class)
107+
public boolean isUserRequestedSecurityProvider(String provider) {
108+
return userRequestedSecurityProviders.contains(provider);
109+
}
110+
111+
/**
112+
* Returns {@code true} if the provider, identified by either its name (e.g., SUN) or fully
113+
* qualified name (e.g., sun.security.provider.Sun), is either user-requested or reachable via a
114+
* security service.
115+
*/
116+
public boolean isSecurityProviderExpected(String providerName, String providerFQName) {
117+
return verifiedSecurityProviders.containsKey(providerName) || userRequestedSecurityProviders.contains(providerFQName);
118+
}
119+
120+
@Platforms(Platform.HOSTED_ONLY.class)
121+
public void setSunECConstructor(Constructor<?> sunECConstructor) {
122+
this.sunECConstructor = sunECConstructor;
123+
}
124+
125+
public Provider allocateSunECProvider() {
126+
try {
127+
return (Provider) sunECConstructor.newInstance();
128+
} catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
129+
throw VMError.shouldNotReachHere("The SunEC constructor is not present.");
130+
}
131+
}
132+
133+
public void setSavedInitialSecurityProperties(Properties savedSecurityProperties) {
134+
this.savedInitialSecurityProperties = savedSecurityProperties;
135+
}
136+
137+
public Properties getSavedInitialSecurityProperties() {
138+
return savedInitialSecurityProperties;
139+
}
140+
}

0 commit comments

Comments
 (0)