Skip to content

Commit 5e20e93

Browse files
Changes according to commits.
1 parent f5abe53 commit 5e20e93

File tree

11 files changed

+56
-81
lines changed

11 files changed

+56
-81
lines changed

docs/reference-manual/native-image/JCASecurityServices.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,20 @@ The report will detail all registered service classes, the API methods that trig
3636

3737
> Note: The `--enable-all-security-services` option is now deprecated and it will be removed in a future release.
3838
39-
## Provider initialization
39+
## Provider Initialization
4040

41-
Security providers are initialized at build time by default.
41+
Currently security providers are initialized at build time.
42+
To move their initialization to run time, use the option `--future-defaults=all` or `--future-defaults=run-time-initialized-jdk`.
43+
Provider verification will still occur at build time.
44+
Run-time initialization of security providers helps reduce image heap size.
4245
To move their initialization to run time, you can use the flag `--future-defaults=all` or `--future-defaults=run-time-initialized-jdk`.
4346

4447
## Provider Registration
4548

4649
The `native-image` builder captures the list of providers and their preference order from the underlying JVM.
4750
The provider order is specified in the `java.security` file under `<java-home>/conf/security/java.security`.
4851
New security providers cannot be registered at run time by default (see the section above); all providers must be statically configured at executable build time.
49-
If the user specifies `--future-defaults=all` or `--future-defaults=run-time-initialized-jdk` (to move initialization to run time), then a specific properties file can be used via the command line flag `-Djava.security.properties=<path>`.
52+
If the user specifies `--future-defaults=all` or `--future-defaults=run-time-initialized-jdk` to move providers initialization to run time, then a specific properties file can be used via the command line option `-Djava.security.properties=<path>`.
5053

5154
## Providers Reordering at Run Time
5255

substratevm/CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ This changelog summarizes major changes to GraalVM Native Image.
2727
* (GR-64787) Enable `--install-exit-handlers` by default for executables and deprecate the option. If shared libraries were using this flag, the same functionality can be restored by using `-H:+InstallExitHandlers`.
2828
* (GR-47881) Remove the total number of loaded types, fields, and methods from the build output, deprecated these metrics in the build output schema, and removed already deprecated build output metrics.
2929
* (GR-64619) Missing registration errors are now subclasses of `LinkageError`
30-
* (GR-57827) Move the initialization of security providers from build time to runtime.
30+
* (GR-57827) Security providers can now be initialized at run time (instead of build time) when using the option `--future-defaults=all` or `--future-defaults=run-time-initialized-jdk`.
31+
Run-time initialization of security providers helps reduce image heap size by avoiding unnecessary objects inclusion.
3132

3233
## GraalVM for JDK 24 (Internal Version 24.2.0)
3334
* (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 & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@
352352
],
353353
"requiresConcealed" : {
354354
"java.base" : [
355+
"com.sun.crypto.provider",
355356
"sun.invoke.util",
356357
"sun.net",
357358
"sun.net.www",
@@ -361,12 +362,11 @@
361362
"sun.reflect.generics.reflectiveObjects",
362363
"sun.reflect.generics.repository",
363364
"sun.reflect.generics.tree",
364-
"sun.security.rsa",
365365
"sun.security.jca",
366+
"sun.security.provider",
367+
"sun.security.rsa",
366368
"sun.security.ssl",
367369
"sun.security.util",
368-
"sun.security.provider",
369-
"com.sun.crypto.provider",
370370
"sun.text.spi",
371371
"sun.util",
372372
"sun.util.locale",

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecurityProvidersSupport.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ public static SecurityProvidersSupport singleton() {
8585
}
8686

8787
@Platforms(Platform.HOSTED_ONLY.class)
88-
public void addVerifiedSecurityProvider(String key, Object value) {
89-
verifiedSecurityProviders.put(key, value);
88+
public void addVerifiedSecurityProvider(String key, Object verificationResult) {
89+
verifiedSecurityProviders.put(key, verificationResult);
9090
}
9191

9292
public Object getSecurityProviderVerificationResult(String key) {
@@ -113,7 +113,7 @@ public boolean isUserRequestedSecurityProvider(String provider) {
113113
* qualified name (e.g., sun.security.provider.Sun), is either user-requested or reachable via a
114114
* security service.
115115
*/
116-
public boolean isSecurityProviderExpected(String providerName, String providerFQName) {
116+
public boolean isSecurityProviderRequested(String providerName, String providerFQName) {
117117
return verifiedSecurityProviders.containsKey(providerName) || userRequestedSecurityProviders.contains(providerFQName);
118118
}
119119

@@ -130,6 +130,7 @@ public Provider allocateSunECProvider() {
130130
}
131131
}
132132

133+
@Platforms(Platform.HOSTED_ONLY.class)
133134
public void setSavedInitialSecurityProperties(Properties savedSecurityProperties) {
134135
this.savedInitialSecurityProperties = savedSecurityProperties;
135136
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SecuritySubstitutions.java

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import java.security.Policy;
3737
import java.security.ProtectionDomain;
3838
import java.security.Provider;
39-
import java.security.SecureRandom;
4039
import java.util.List;
4140
import java.util.Map;
4241
import java.util.Objects;
@@ -244,26 +243,28 @@ private static void setJavaHome(String newJavaHome) {
244243
}
245244
}
246245

246+
/**
247+
* The {@link javax.crypto.JceSecurity#verificationResults} cache is initialized by the
248+
* SecurityServicesFeature at build time, for all registered providers. The cache is used by
249+
* {@link javax.crypto.JceSecurity#canUseProvider} at run time to check whether a provider is
250+
* properly signed and can be used by JCE. It does that via jar verification which we cannot
251+
* support.
252+
*/
247253
@TargetClass(className = "javax.crypto.JceSecurity", onlyWith = JDKInitializedAtBuildTime.class)
248254
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+27/src/java.base/share/classes/javax/crypto/JceSecurity.java.template")
249255
@SuppressWarnings({"unused"})
250256
final class Target_javax_crypto_JceSecurity {
251257

252-
/*
253-
* The JceSecurity.verificationResults cache is initialized by the SecurityServicesFeature at
254-
* build time, for all registered providers. The cache is used by JceSecurity.canUseProvider()
255-
* at runtime to check whether a provider is properly signed and can be used by JCE. It does
256-
* that via jar verification which we cannot support.
257-
*/
258-
259258
// Checkstyle: stop
260259
@Alias //
261260
private static Object PROVIDER_VERIFIED;
262261
// Checkstyle: resume
263262

264-
// Map<Provider,?> of the providers we already have verified
265-
// value == PROVIDER_VERIFIED is successfully verified
266-
// value is failure cause Exception in error case
263+
/*
264+
* Map<Provider, ?> of providers that have already been verified. A value of PROVIDER_VERIFIED
265+
* indicates successful verification. Otherwise, the value is the Exception that caused the
266+
* verification to fail.
267+
*/
267268
@Alias //
268269
private static Map<Object, Object> verificationResults;
269270

@@ -281,7 +282,6 @@ final class Target_javax_crypto_JceSecurity {
281282

282283
@Substitute
283284
static Exception getVerificationResult(Provider p) {
284-
/* Start code block copied from original method. */
285285
/* The verification results map key is an identity wrapper object. */
286286
Object key = new Target_javax_crypto_JceSecurity_WeakIdentityWrapper(p, queue);
287287
Object o = verificationResults.get(key);
@@ -290,7 +290,6 @@ static Exception getVerificationResult(Provider p) {
290290
} else if (o != null) {
291291
return (Exception) o;
292292
}
293-
/* End code block copied from original method. */
294293
/*
295294
* If the verification result is not found in the verificationResults map JDK proceeds to
296295
* verify it. That requires accessing the code base which we don't support. The substitution
@@ -311,31 +310,6 @@ final class Target_javax_crypto_JceSecurity_WeakIdentityWrapper {
311310
}
312311
}
313312

314-
class JceSecurityAccessor {
315-
private static volatile SecureRandom RANDOM;
316-
317-
static SecureRandom get() {
318-
SecureRandom result = RANDOM;
319-
if (result == null) {
320-
/* Lazy initialization on first access. */
321-
result = initializeOnce();
322-
}
323-
return result;
324-
}
325-
326-
private static synchronized SecureRandom initializeOnce() {
327-
SecureRandom result = RANDOM;
328-
if (result != null) {
329-
/* Double-checked locking is OK because INSTANCE is volatile. */
330-
return result;
331-
}
332-
333-
result = new SecureRandom();
334-
RANDOM = result;
335-
return result;
336-
}
337-
}
338-
339313
/**
340314
* JDK 8 has the class `javax.crypto.JarVerifier`, but in JDK 11 and later that class is only
341315
* available in Oracle builds, and not in OpenJDK builds.

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_sun_security_ssl_TrustStoreManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public void afterRegistration(AfterRegistrationAccess access) {
9090
*/
9191
RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
9292
rci.initializeAtBuildTime("sun.security.util.UntrustedCertificates", "Required for TrustStoreManager");
93-
if (FutureDefaultsOptions.isJDKInitializedAtBuildTime()) {
93+
if (!FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
9494
/*
9595
* All security providers must be registered (and initialized) at buildtime (see
9696
* SecuritySubstitutions.java). XMLDSigRI is used for validating XML Signatures from

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/runtimeinit/SecuritySubstitutionRuntimeInit.java

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,26 +58,23 @@ private static void loadMaster() {
5858
}
5959
}
6060

61+
/**
62+
* The {@link javax.crypto.JceSecurity#verificationResults} cache is initialized by the
63+
* SecurityServicesFeature at build time, for all registered providers. The cache is used by
64+
* {@link javax.crypto.JceSecurity#canUseProvider} at run time to check whether a provider is
65+
* properly signed and can be used by JCE. It does that via jar verification which we cannot
66+
* support.
67+
*/
6168
@TargetClass(className = "javax.crypto.JceSecurity", onlyWith = JDKInitializedAtRunTime.class)
6269
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+27/src/java.base/share/classes/javax/crypto/JceSecurity.java.template")
6370
@SuppressWarnings({"unused"})
6471
final class Target_javax_crypto_JceSecurity {
6572

6673
/*
67-
* The JceSecurity.verificationResults cache is initialized by the SecurityServicesFeature at
68-
* build time, for all registered providers. The cache is used by JceSecurity.canUseProvider()
69-
* at runtime to check whether a provider is properly signed and can be used by JCE. It does
70-
* that via jar verification which we cannot support.
74+
* Map<Provider, ?> of providers that have already been verified. A value of PROVIDER_VERIFIED
75+
* indicates successful verification. Otherwise, the value is the Exception that caused the
76+
* verification to fail.
7177
*/
72-
73-
// Checkstyle: stop
74-
@Alias //
75-
private static Object PROVIDER_VERIFIED;
76-
// Checkstyle: resume
77-
78-
// Map<Provider,?> of the providers we already have verified
79-
// value == PROVIDER_VERIFIED is successfully verified
80-
// value is failure cause Exception in error case
8178
@Alias //
8279
@RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) //
8380
private static Map<Object, Object> verificationResults;
@@ -92,15 +89,13 @@ final class Target_javax_crypto_JceSecurity {
9289

9390
@Substitute
9491
static Exception getVerificationResult(Provider p) {
95-
/* Start code block copied from original method. */
9692
/* The verification results map key is an identity wrapper object. */
9793
Object o = SecurityProvidersSupport.singleton().getSecurityProviderVerificationResult(p.getName());
98-
if (o == PROVIDER_VERIFIED) {
94+
if (o == Boolean.TRUE) {
9995
return null;
10096
} else if (o != null) {
10197
return (Exception) o;
10298
}
103-
/* End code block copied from original method. */
10499
/*
105100
* If the verification result is not found in the verificationResults map JDK proceeds to
106101
* verify it. That requires accessing the code base which we don't support. The substitution
@@ -164,24 +159,24 @@ Provider getProvider() {
164159
SecurityProvidersSupport support = SecurityProvidersSupport.singleton();
165160
switch (provName) {
166161
case "SUN", "sun.security.provider.Sun": {
167-
p = support.isSecurityProviderExpected("SUN", "sun.security.provider.Sun") ? new sun.security.provider.Sun() : null;
162+
p = support.isSecurityProviderRequested("SUN", "sun.security.provider.Sun") ? new sun.security.provider.Sun() : null;
168163
break;
169164
}
170165
case "SunRsaSign", "sun.security.rsa.SunRsaSign": {
171-
p = support.isSecurityProviderExpected("SunRsaSign", "sun.security.rsa.SunRsaSign") ? new sun.security.rsa.SunRsaSign() : null;
166+
p = support.isSecurityProviderRequested("SunRsaSign", "sun.security.rsa.SunRsaSign") ? new sun.security.rsa.SunRsaSign() : null;
172167
break;
173168
}
174169
case "SunJCE", "com.sun.crypto.provider.SunJCE": {
175-
p = support.isSecurityProviderExpected("SunJCE", "com.sun.crypto.provider.SunJCE") ? new com.sun.crypto.provider.SunJCE() : null;
170+
p = support.isSecurityProviderRequested("SunJCE", "com.sun.crypto.provider.SunJCE") ? new com.sun.crypto.provider.SunJCE() : null;
176171
break;
177172
}
178173
case "SunJSSE": {
179-
p = support.isSecurityProviderExpected("SunJSSE", "sun.security.ssl.SunJSSE") ? new sun.security.ssl.SunJSSE() : null;
174+
p = support.isSecurityProviderRequested("SunJSSE", "sun.security.ssl.SunJSSE") ? new sun.security.ssl.SunJSSE() : null;
180175
break;
181176
}
182177
case "SunEC": {
183178
// Constructor inside method and then allocate. ModuleSupport to open.
184-
p = support.isSecurityProviderExpected("SunEC", "sun.security.ec.SunEC") ? support.allocateSunECProvider() : null;
179+
p = support.isSecurityProviderRequested("SunEC", "sun.security.ec.SunEC") ? support.allocateSunECProvider() : null;
185180
break;
186181
}
187182
case "Apple", "apple.security.AppleProvider": {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ public void afterRegistration(AfterRegistrationAccess a) {
238238
@Override
239239
public void duringSetup(DuringSetupAccess a) {
240240
DuringSetupAccessImpl access = (DuringSetupAccessImpl) a;
241-
if (FutureDefaultsOptions.isJDKInitializedAtBuildTime()) {
241+
if (!FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
242242
addManuallyConfiguredUsedProviders(a);
243243

244244
verificationResultsField = access.findField("javax.crypto.JceSecurity", "verificationResults");
@@ -251,22 +251,23 @@ public void duringSetup(DuringSetupAccess a) {
251251

252252
RuntimeClassInitializationSupport rci = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
253253
if (FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
254+
SecurityProvidersSupport support = SecurityProvidersSupport.singleton();
254255
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, SecuritySubstitutions.class, false, "java.base", "sun.security.ec");
255256
Constructor<?> sunECConstructor = constructor(a, "sun.security.ec.SunEC");
256-
SecurityProvidersSupport.singleton().setSunECConstructor(sunECConstructor);
257+
support.setSunECConstructor(sunECConstructor);
257258

258259
Properties securityProperties = SharedSecrets.getJavaSecurityPropertiesAccess().getInitialProperties();
259-
SecurityProvidersSupport.singleton().setSavedInitialSecurityProperties(securityProperties);
260+
support.setSavedInitialSecurityProperties(securityProperties);
260261

261262
/*
262263
* Security providers will be initialized at run time because the class initialization
263264
* simulation will determine that automatically. For the three classes below, however,
264265
* we need to handle this explicitly because their packages are already marked for
265266
* initialization at build time by JdkInitializationFeature#afterRegistration.
266267
*/
267-
rci.initializeAtRunTime("java.security.Security", SECURITY_PROVIDERS_INITIALIZATION);
268-
rci.initializeAtRunTime("sun.security.jca.Providers", SECURITY_PROVIDERS_INITIALIZATION);
269-
rci.initializeAtRunTime("sun.security.provider.certpath.ldap.JdkLDAP", SECURITY_PROVIDERS_INITIALIZATION);
268+
rci.initializeAtRunTime("java.security.Security", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
269+
rci.initializeAtRunTime("sun.security.jca.Providers", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
270+
rci.initializeAtRunTime("sun.security.provider.certpath.ldap.JdkLDAP", FutureDefaultsOptions.RUN_TIME_INITIALIZE_JDK_REASON);
270271
}
271272

272273
/*
@@ -366,7 +367,7 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
366367
PlatformNativeLibrarySupport.singleton().addBuiltinPkgNativePrefix("sun_security_mscapi");
367368
}
368369

369-
if (FutureDefaultsOptions.isJDKInitializedAtBuildTime()) {
370+
if (!FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
370371
substitutionProcessor = ((Inflation) access.getBigBang()).getAnnotationSubstitutionProcessor();
371372

372373
access.registerFieldValueTransformer(providerListField, new FieldValueTransformerWithAvailability() {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ServiceLoaderFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {
149149

150150
@Override
151151
public void afterRegistration(AfterRegistrationAccess access) {
152-
if (FutureDefaultsOptions.isJDKInitializedAtBuildTime()) {
152+
if (!FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
153153
servicesToSkip.add(java.security.Provider.class.getName());
154154
}
155155
servicesToSkip.addAll(Options.ServiceLoaderFeatureExcludeServices.getValue().values());

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JDKInitializationFeature.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ public void afterRegistration(AfterRegistrationAccess access) {
227227
rci.initializeAtBuildTime("sun.security.validator", JDK_CLASS_REASON);
228228
rci.initializeAtBuildTime("sun.security.x509", JDK_CLASS_REASON);
229229
rci.initializeAtBuildTime("com.sun.jndi", JDK_CLASS_REASON);
230-
if (FutureDefaultsOptions.isJDKInitializedAtBuildTime()) {
230+
if (!FutureDefaultsOptions.isJDKInitializedAtRunTime()) {
231231
rci.initializeAtBuildTime("sun.security.pkcs11", JDK_CLASS_REASON);
232232
rci.initializeAtBuildTime("sun.security.smartcardio", JDK_CLASS_REASON);
233233
rci.initializeAtBuildTime("com.sun.security.sasl", JDK_CLASS_REASON);

0 commit comments

Comments
 (0)