Skip to content

Commit fa3b162

Browse files
committed
[GR-23808] Remove --enable-all-security-services option.
PullRequest: graal/8377
2 parents 3757a6b + a0ea2cd commit fa3b162

File tree

10 files changed

+305
-271
lines changed

10 files changed

+305
-271
lines changed

substratevm/JCASecurityServices.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
11
# JCA Security Services in Native Image
22

3-
This section refers to the use of the services provided by the [Java Cryptography Architecture (JCA)](https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html) framework.
4-
The JCA framework relies on reflection to achieve algorithm independence and extensibility, therefore it requires a custom configuration in Native Image.
5-
Additionally, seed generators that use system files like `/dev/random` or `/dev/urandom` need to be reinitialized at run time.
3+
This section refers to the use of the services provided by the Java Cryptography Architecture (JCA) framework.
4+
For more details see the following guides: [JDK8](https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html), [JDK11](https://docs.oracle.com/en/java/javase/11/security/java-cryptography-architecture-jca-reference-guide.html).
65

7-
By default a native image is built with support for the `SecureRandom` and `MessageDigest` engines from the `SUN` provider.
6+
The JCA framework uses a provider architecture to access security services such as digital signatures, message digests, certificates and certificate validation, encryption (symmetric/asymmetric block/stream ciphers), key generation and management, and secure random number generation, etc.
7+
To achieve algorithm independence and extensibility it relies on reflection, therefore it requires a custom configuration in Native Image.
8+
The Native Image builder uses static analysis to discover which of these services are used.
9+
10+
Each provider registers concrete implementation classes for the algorithms it supports.
11+
Each of the service classes (`Signature`, `Cipher`, `Mac`, `KeyPair`, `KeyGenerator`, `KeyFactory`, `KeyStore`, etc.,) declares a series of `getInstance(<algorithm>, <provider>)` factory methods which provide a concrete service implementation.
12+
When a specific algorithm is requested the framework searches the registered providers for the corresponding implementation classes and it dynamically allocates objects for concrete service implementations.
13+
The Native Image builder uses static analysis to discover which of these services are used.
14+
It does so by registering reachability handlers for each of the `getInstance()` factory methods.
15+
When it determines that a `getInstance()` method is reachable at run time it automatically performs the reflection registration for all the concrete implementations of the corresponding service type.
16+
This mechanism is implemented in the `com.oracle.svm.hosted.SecurityServicesFeature` class.
17+
18+
The simplest images contain support for the `SecureRandom` and `MessageDigest` engines from the `SUN` provider.
819
These are core security services needed by the VM itself.
9-
All the other Java security services (`Signature`, `Cipher`, `Mac`, `KeyPair`, `KeyGenerator`, `KeyFactory`, `KeyStore`, etc.,) must be enabled by adding the `--enable-all-security-services` option to the `native-image` command.
10-
The reason behind enabling only core security services by default is that you can start with a basic image and add more security services as you need them.
11-
This helps keep the overall image size small.
1220

13-
Note: the `--enable-all-security-services` option is enabled by default when `https` support is enabled.
14-
See the [URL Protocols in Native Image](URLProtocols.md) guide for more details.
21+
Note: The `--enable-all-security-services` option is now deprecated and it will be removed in a future release.
1522

1623
## Provider Registration
1724
The native image builder captures the list of providers and their preference order from the underlying JVM.
1825
The provider order is specified in the `java.security` file under `<java-home>/lib/security/java.security`.
1926
New security providers cannot be registered at run time; all providers must be statically configured during a native image building.
2027

21-
### Alternative to `--enable-all-security-services`
22-
Registering *all* security services does not come for free.
23-
The additional code increases the native image size.
24-
If your application only requires a subset of the security services, you can manually register the corresponding classes for reflection and push the initialization of some seed generators to run time.
25-
However this requires deep knowledge of the JCA architecture.
26-
We are investigating the possibility of providing a finer-grain declarative configuration of security services for future releases.
27-
If you want to take on this task yourself, you can start by reading the `com.oracle.svm.hosted.SecurityServicesFeature` class.
28-
This is where most of the code behind the `--enable-all-security-services` option is implemented.
28+
## SecureRandom
29+
30+
The SecureRandom implementations open the `/dev/random` and `/dev/urandom` files which are used as sources for entropy.
31+
These files are usually opened in class initializers.
32+
To avoid capturing state from the machine that runs the Native Image builder these classes need to be initialized at run time.

substratevm/Limitations.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ Native Image employs a simple static analysis that intercepts calls to `java.lan
3939
Where the analysis fails the lists of interfaces can be specified in a [configuration file](BuildConfiguration.md).
4040
For more details, read the [Dynamic Proxies support](DynamicProxy.md) guide.
4141

42-
### JCA (Java Cryptography Architecture)
43-
The JCA security services must be enabled using the option `--enable-all-security-services`.
44-
They require a custom configuration in Native Image since the JCA framework relies on reflection to achieve algorithm extensibility. For more details, read the [Security Services](JCASecurityServices.md) guide.
45-
4642
### JNI (Java Native Interface)
4743
Native code may access Java objects, classes, methods and fields by name, in a similar way to using the reflection API in Java code.
4844
For the same reasons, any Java artifacts accessed by name via JNI must be specified during a native image generation in a [configuration file](BuildConfiguration.md). For more details, read the [JNI Implementation](JNI.md) guide.

substratevm/Options.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ The following options are equally supported with both GraalVM Communty and Enter
3939
* `--help-extra`: print help on non-standard options.
4040
* `--allow-incomplete-classpath`: allow the image build with an incomplete class path. Report type resolution errors at runtime when they are accessed the first time, instead of during the image build.
4141
* `--auto-fallback`: build a standalone image if possible.
42-
* `--enable-all-security-services`: add all security service classes to a generated image.
4342
* `--enable-http`: enable http support in a generated image.
4443
* `--enable-https`: enable https support in a generated image.
4544
* `--enable-url-protocols`: list comma-separated URL protocols to enable.

substratevm/URLProtocols.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ They can be enabled using the `--enable-http` and `--enable-https` options.
2222

2323
### HTTPS Support
2424
Support for the `https` URL protocol relies on the Java Cryptography Architecture (JCA) framework.
25-
Thus when `https` is enabled, `--enable-all-security-services` is set by default.
26-
This adds to the generated image the code required by the JCA, including statically linking native libraries that the JCA may depend on.
25+
Thus enabling `https` will add to the generated image the code required by the JCA, including statically linking native libraries that the JCA may depend on.
2726
See the [documentation on security services](JCASecurityServices.md) for more details.
2827

2928
## Not Tested

substratevm/mx.substratevm/mx_substratevm.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,8 +481,7 @@ def native_unittests_task():
481481
# GR-24075
482482
mx_unittest.add_global_ignore_glob('com.oracle.svm.test.ProcessPropertiesTest')
483483

484-
# We need the -H:+EnableAllSecurityServices for com.oracle.svm.test.SecurityServiceTest
485-
native_unittest(['--build-args', _native_unittest_features, '-H:+EnableAllSecurityServices'])
484+
native_unittest(['--build-args', _native_unittest_features])
486485

487486

488487
def javac_image_command(javac_path):

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,10 @@
4646
import org.graalvm.compiler.options.OptionValues;
4747
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
4848

49-
import com.oracle.svm.core.jdk.JavaNetSubstitutions;
5049
import com.oracle.svm.core.option.APIOption;
5150
import com.oracle.svm.core.option.APIOptionGroup;
5251
import com.oracle.svm.core.option.HostedOptionKey;
5352
import com.oracle.svm.core.option.LocatableMultiOptionValue;
54-
import com.oracle.svm.core.option.OptionUtils;
5553
import com.oracle.svm.core.option.RuntimeOptionKey;
5654
import com.oracle.svm.core.option.XOptions;
5755
import com.oracle.svm.core.util.UserError;
@@ -243,32 +241,12 @@ public Boolean getValue(OptionValues values) {
243241
@APIOption(name = "enable-https", fixedValue = "https", customHelp = "enable https support in the generated image")//
244242
@APIOption(name = "enable-url-protocols")//
245243
@Option(help = "List of comma separated URL protocols to enable.")//
246-
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> EnableURLProtocols = new HostedOptionKey<LocatableMultiOptionValue.Strings>(new LocatableMultiOptionValue.Strings()) {
247-
@Override
248-
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, LocatableMultiOptionValue.Strings oldValue, LocatableMultiOptionValue.Strings newValue) {
249-
for (String protocol : OptionUtils.flatten(",", newValue)) {
250-
if (protocol.equals(JavaNetSubstitutions.HTTPS_PROTOCOL)) {
251-
EnableAllSecurityServices.update(values, true);
252-
}
253-
}
254-
}
255-
};
244+
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> EnableURLProtocols = new HostedOptionKey<>(new LocatableMultiOptionValue.Strings());
256245

246+
@SuppressWarnings("unused") //
257247
@APIOption(name = "enable-all-security-services")//
258-
@Option(help = "Add all security service classes to the generated image.")//
259-
public static final HostedOptionKey<Boolean> EnableAllSecurityServices = new HostedOptionKey<Boolean>(false) {
260-
@Override
261-
protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, Boolean oldValue, Boolean newValue) {
262-
if (newValue) {
263-
/*
264-
* Some providers like SunEC and SunSASL are implemented in native libs. These
265-
* providers are added to the image when EnableAllSecurityServices is set. If they
266-
* are actually used at runtime the user must provide and load the native libs.
267-
*/
268-
JNI.update(values, true);
269-
}
270-
}
271-
};
248+
@Option(help = "Add all security service classes to the generated image.", deprecated = true)//
249+
public static final HostedOptionKey<Boolean> EnableAllSecurityServices = new HostedOptionKey<>(false);
272250

273251
@Option(help = "Enable Java Native Interface (JNI) support.")//
274252
public static final HostedOptionKey<Boolean> JNI = new HostedOptionKey<>(true);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/TypeResult.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.core;
2626

27+
import java.util.function.Consumer;
28+
2729
import com.oracle.svm.core.util.VMError;
2830

2931
/**
@@ -62,6 +64,12 @@ public boolean isPresent() {
6264
return type != null;
6365
}
6466

67+
public void ifPresent(Consumer<? super T> consumer) {
68+
if (type != null) {
69+
consumer.accept(type);
70+
}
71+
}
72+
6573
public T get() {
6674
return type;
6775
}

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

Lines changed: 1 addition & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,11 @@
4444
import java.util.List;
4545
import java.util.Map;
4646
import java.util.concurrent.atomic.AtomicReference;
47-
import java.util.function.BooleanSupplier;
4847
import java.util.function.Predicate;
4948

5049
import org.graalvm.nativeimage.hosted.Feature;
5150
import org.graalvm.word.Pointer;
5251

53-
import com.oracle.svm.core.SubstrateOptions;
5452
import com.oracle.svm.core.annotate.Alias;
5553
import com.oracle.svm.core.annotate.AutomaticFeature;
5654
import com.oracle.svm.core.annotate.Delete;
@@ -60,8 +58,6 @@
6058
import com.oracle.svm.core.annotate.Substitute;
6159
import com.oracle.svm.core.annotate.TargetClass;
6260
import com.oracle.svm.core.annotate.TargetElement;
63-
import com.oracle.svm.core.log.Log;
64-
import com.oracle.svm.core.option.SubstrateOptionsParser;
6561
import com.oracle.svm.core.util.VMError;
6662
import com.oracle.svm.util.ReflectionUtil;
6763

@@ -235,76 +231,6 @@ final class Target_javax_crypto_CryptoAllPermission {
235231
static Target_javax_crypto_CryptoAllPermission INSTANCE;
236232
}
237233

238-
final class EnableAllSecurityServicesIsSet implements BooleanSupplier {
239-
@Override
240-
public boolean getAsBoolean() {
241-
return SubstrateOptions.EnableAllSecurityServices.getValue();
242-
}
243-
}
244-
245-
/**
246-
* This substitution is enabled only when EnableAllSecurityServices is set since the functionality
247-
* that it currently provides, i.e., loading security native libraries, is not needed by default.
248-
*/
249-
@TargetClass(value = java.security.Provider.class, onlyWith = EnableAllSecurityServicesIsSet.class)
250-
final class Target_java_security_Provider {
251-
252-
@Alias //
253-
private transient boolean initialized;
254-
255-
@Alias//
256-
private String name;
257-
258-
/*
259-
* Provider.checkInitialized() is called from the other Provider API methods, before any
260-
* computation, thus is a convenient location to do our own initialization, i.e., make sure that
261-
* the required libraries are loaded.
262-
*/
263-
@Substitute
264-
private void checkInitialized() {
265-
if (this.name.equals("SunEC")) {
266-
ProviderUtil.initSunEC();
267-
}
268-
269-
if (!initialized) {
270-
throw new IllegalStateException();
271-
}
272-
}
273-
274-
}
275-
276-
final class ProviderUtil {
277-
private static volatile boolean initialized = false;
278-
279-
static void initSunEC() {
280-
if (initialized) {
281-
return;
282-
}
283-
/* Lazy initialization. */
284-
initOnce();
285-
}
286-
287-
// Checkstyle: stop
288-
private static synchronized void initOnce() {
289-
// Checkstyle: resume
290-
if (!initialized) {
291-
try {
292-
System.loadLibrary("sunec");
293-
} catch (UnsatisfiedLinkError e) {
294-
/*
295-
* SunEC has a mode where it can function without the full ECC implementation when
296-
* native library is absent, however, then fewer EC algorithms are available). If
297-
* those algorithms are actually used an java.lang.UnsatisfiedLinkError will be
298-
* thrown. Just warn the user that the library could not be loaded.
299-
*/
300-
Log.log().string("WARNING: The sunec native library, required by the SunEC provider, could not be loaded.").newline();
301-
}
302-
initialized = true;
303-
}
304-
}
305-
306-
}
307-
308234
@TargetClass(className = "javax.crypto.ProviderVerifier", onlyWith = JDK11OrLater.class)
309235
@SuppressWarnings({"unused"})
310236
final class Target_javax_crypto_ProviderVerifier {
@@ -386,10 +312,7 @@ static Exception getVerificationResult(Provider p) {
386312
* getVerificationResult() allows for a better error message.
387313
*/
388314
throw VMError.unsupportedFeature("Trying to verify a provider that was not registered at build time: " + p + ". " +
389-
"All providers must be registered and verified in the Native Image builder. " +
390-
"Only the SUN provider is registered and verified by default. " +
391-
"All other built-in providers are processed when all security services are enabled using the " + JceSecurityUtil.enableAllSecurityServices + " option. " +
392-
"Third party providers must be configured in the Native Image builder VM. ");
315+
"All providers must be registered and verified in the Native Image builder. ");
393316
}
394317

395318
}
@@ -423,8 +346,6 @@ private static synchronized SecureRandom initializeOnce() {
423346
}
424347

425348
final class JceSecurityUtil {
426-
static final String enableAllSecurityServices = SubstrateOptionsParser.commandArgument(SubstrateOptions.EnableAllSecurityServices, "+");
427-
428349
static RuntimeException shouldNotReach(String method) {
429350
throw VMError.shouldNotReachHere(method + " is reached at runtime. " +
430351
"This should not happen. The contents of JceSecurity.verificationResults " +

0 commit comments

Comments
 (0)