Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions .github/workflows/filtered-providers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ jobs:
"com/wolfssl/security/providers/FilteredSunEC.class" \
"com/wolfssl/security/providers/FilteredSunRsaSign.class" \
"com/wolfssl/security/providers/ProviderServiceCopier.class" \
"META-INF/services/java.security.Provider"; do
"META-INF/services/java.security.Provider" \
"module-info.class"; do
if jar tf "$JAR" | grep -qx "$entry"; then
echo "OK : present -> $entry"
else
Expand All @@ -80,6 +81,16 @@ jobs:
if jar tf "$JAR" | grep -qE '^com/wolfssl/wolfcrypt/.*\.class$'; then
echo "ERR: wolfCrypt classes leaked into ant jar"; fail=1
fi
# Explicit module com.wolfssl.security.providers
DESC=$(jar --describe-module --file="$JAR")
echo "$DESC"
if echo "$DESC" | grep -qE '^com\.wolfssl\.security\.providers jar:' && \
! echo "$DESC" | grep -q 'automatic'; then
echo "OK : explicit module com.wolfssl.security.providers"
else
echo "ERR: ant jar is not module com.wolfssl.security.providers"
fail=1
fi
[ "$fail" -eq 0 ] || { echo "FAILURE: ant jar verification"; exit 1; }
echo "SUCCESS: ant jar verification passed"

Expand All @@ -98,7 +109,8 @@ jobs:
"com/wolfssl/security/providers/FilteredSunEC.class" \
"com/wolfssl/security/providers/FilteredSunRsaSign.class" \
"com/wolfssl/security/providers/ProviderServiceCopier.class" \
"META-INF/services/java.security.Provider"; do
"META-INF/services/java.security.Provider" \
"module-info.class"; do
if jar tf "$JAR" | grep -qx "$entry"; then
echo "OK : present -> $entry"
else
Expand All @@ -108,6 +120,17 @@ jobs:
if jar tf "$JAR" | grep -qE '^com/wolfssl/wolfcrypt/.*\.class$'; then
echo "ERR: wolfCrypt classes leaked into Maven classified jar"; fail=1
fi
# Explicit module com.wolfssl.security.providers (Maven adds @version)
DESC=$(jar --describe-module --file="$JAR")
echo "$DESC"
if echo "$DESC" | \
grep -qE '^com\.wolfssl\.security\.providers(@[^ ]*)? jar:' && \
! echo "$DESC" | grep -q 'automatic'; then
echo "OK : explicit module com.wolfssl.security.providers"
else
echo "ERR: Maven jar is not module com.wolfssl.security.providers"
fail=1
fi
[ "$fail" -eq 0 ] || { echo "FAILURE: Maven jar verification"; exit 1; }
echo "SUCCESS: Maven jar verification passed"

Expand Down
53 changes: 50 additions & 3 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
<property name="examples.provider.dir" value="examples/provider" />
<property name="examples.provider.build.dir" value="examples/build/provider" />
<property name="examples.filtered.dir" value="examples/filtered-providers/src" />
<property name="examples.filtered.java9.dir" value="examples/filtered-providers/java9" />
<property name="filtered.module.name" value="com.wolfssl.security.providers" />
<property name="examples.filtered.build.dir" value="examples/build/filtered-providers" />
<property name="filtered.test.build.dir" value="build/test-filtered-providers" />
<!-- final filtered-providers.jar location; subdirectory of lib/ so the
Expand Down Expand Up @@ -393,13 +395,13 @@
</target>

<!-- Build filtered Sun/SunEC/SunRsaSign provider examples, package them
(plus their ServiceLoader registration) into filtered-providers.jar.
Java 9+ only, no-op on Java 8. -->
(plus their ServiceLoader registration and module-info.class) into
filtered-providers.jar. Java 9+ only, no-op on Java 8. -->
<target name="examples-filtered-providers" if="isJava9Plus"
description="Build filtered-providers examples + jar (Java 9+ only)">
<mkdir dir="${examples.filtered.build.dir}/classes" />
<javac
srcdir="${examples.filtered.dir}"
srcdir="${examples.filtered.dir}:${examples.filtered.java9.dir}"
destdir="${examples.filtered.build.dir}/classes"
source="9"
target="9"
Expand Down Expand Up @@ -428,6 +430,11 @@
value="--add-modules=jdk.crypto.ec --add-exports=jdk.crypto.ec/sun.security.ec=ALL-UNNAMED --add-opens=jdk.crypto.ec/sun.security.ec=ALL-UNNAMED" />
<property name="filtered.ec.flags" if:set="isJava22Plus"
value="--add-exports=java.base/sun.security.ec=ALL-UNNAMED --add-opens=java.base/sun.security.ec=ALL-UNNAMED" />
<!-- Same flags for the module path run, targeting the module name -->
<property name="filtered.ec.flags.module" unless:set="isJava22Plus"
value="--add-modules=jdk.crypto.ec --add-exports=jdk.crypto.ec/sun.security.ec=${filtered.module.name} --add-opens=jdk.crypto.ec/sun.security.ec=${filtered.module.name}" />
<property name="filtered.ec.flags.module" if:set="isJava22Plus"
value="--add-exports=java.base/sun.security.ec=${filtered.module.name} --add-opens=java.base/sun.security.ec=${filtered.module.name}" />

<delete dir="${filtered.test.build.dir}" />
<mkdir dir="${filtered.test.build.dir}" />
Expand Down Expand Up @@ -487,6 +494,46 @@
</batchtest>

</junit>

<!-- Rerun the tests with filtered-providers.jar on the module path.
Adding the module by name also checks that the jar has its
module-info (otherwise the JVM fails to start). -->
<mkdir dir="${reports.dir}/filtered-providers-modulepath" />
<junit printsummary="yes"
showoutput="yes"
haltonfailure="yes"
fork="true">

<jvmarg value="--module-path=${filtered.lib.dir}/filtered-providers.jar"/>
<jvmarg value="--add-modules=${filtered.module.name}"/>
<!-- SunEC module flags (JDK-version specific) -->
<jvmarg line="${filtered.ec.flags.module}"/>
<!-- Stable java.base flags (all JDK majors) -->
<jvmarg value="--add-opens=java.base/java.security=${filtered.module.name}"/>
<jvmarg value="--add-opens=java.base/sun.security.provider=${filtered.module.name}"/>
<jvmarg value="--add-opens=java.base/sun.security.util=${filtered.module.name}"/>
<jvmarg value="--add-opens=java.base/sun.security.rsa=${filtered.module.name}"/>

<classpath>
<pathelement location="${filtered.test.build.dir}" />
<fileset dir="${env.JUNIT_HOME}">
<include name="${junit4}"/>
<include name="${hamcrest-core}"/>
<include name="${ant-junit4}"/>
</fileset>
</classpath>

<formatter type="plain" />
<formatter type="xml" />

<batchtest fork="yes"
todir="${reports.dir}/filtered-providers-modulepath">
<fileset dir="${test.dir}">
<include name="com/wolfssl/security/providers/test/*Test.java" />
</fileset>
</batchtest>

</junit>
</target>

<!-- compile JNI/JCE test classes, depending on how 'ant build' was run -->
Expand Down
28 changes: 28 additions & 0 deletions examples/filtered-providers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ Both jars are self-contained and include a
`META-INF/services/java.security.Provider` entry so the providers can also be
discovered via `ServiceLoader`.

Both jars are also the JPMS module `com.wolfssl.security.providers`, with a
module descriptor compiled from
[java9/module-info.java](java9/module-info.java). On the class path the module
descriptor is ignored.

## Pulling into your own Linux host, VM, or container

The build produces a single self-contained jar. Copy it out and drop it onto
Expand Down Expand Up @@ -102,6 +107,29 @@ your system:
For Docker/Kubernetes, set these via `JAVA_TOOL_OPTIONS`. See
[docs/add-opens.md](docs/add-opens.md) for the per-flag rationale.

**Module path alternative:** the jar can be placed on the module path
instead of the class path. By doing this, applications don't need to add it
to their own class path, and JDK tools like `keytool`, which ignore the
`CLASSPATH` environment variable, still load the providers. In the module
path case, resolve the module explicitly and target the flags at the module
name instead of `ALL-UNNAMED`. For JDK 22+:

```
--module-path=/usr/share/java/filtered-providers.jar
--add-modules=com.wolfssl.security.providers
--add-exports=java.base/sun.security.ec=com.wolfssl.security.providers
--add-opens=java.base/sun.security.ec=com.wolfssl.security.providers
--add-opens=java.base/java.security=com.wolfssl.security.providers
--add-opens=java.base/sun.security.provider=com.wolfssl.security.providers
--add-opens=java.base/sun.security.util=com.wolfssl.security.providers
--add-opens=java.base/sun.security.rsa=com.wolfssl.security.providers
```

For JDK 9-21, make the same substitution in the JDK 9-21 EC flags
(`jdk.crypto.ec/sun.security.ec=com.wolfssl.security.providers`). Flags
that still target `ALL-UNNAMED` do not reach a named module, and the
providers fail to initialize with `IllegalAccessException`.

4. Optional debug logging:

```
Expand Down
18 changes: 18 additions & 0 deletions examples/filtered-providers/docs/add-opens.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,21 @@ The `ant test-filtered-providers` target and the Maven `filtered-providers`
profile select the correct EC flag set automatically based on the running
JDK.

## Flag target: class path vs module path

The flags above use `ALL-UNNAMED`, which covers the jar when it is on the
class path, where the providers run in the unnamed module.

When `filtered-providers.jar` is on the module path, the providers run in the
named module `com.wolfssl.security.providers`. `ALL-UNNAMED` does not include
named modules, so every flag above must target the module name instead, for
example:

```
--add-opens=java.base/java.security=com.wolfssl.security.providers
```

The module must also be resolved with
`--add-modules=com.wolfssl.security.providers`. `ant test-filtered-providers`
runs the tests in both modes.

42 changes: 42 additions & 0 deletions examples/filtered-providers/java9/module-info.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* module-info.java
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/

/**
* Filtered Sun security providers module (FilteredSun, FilteredSunEC,
* FilteredSunRsaSign).
*
* On the module path, --add-opens / --add-exports flags must target this
* module name (see docs/add-opens.md). Ignored on the class path.
*
* Kept outside src/ because the Maven filtered-providers profile compiles
* src/ into target/classes, which holds wolfcrypt-jni's own module-info.
*/
module com.wolfssl.security.providers {

/* Allows explicit use, ex: Security.addProvider(new FilteredSun()) */
exports com.wolfssl.security.providers;

/* Keep in sync with src/META-INF/services/java.security.Provider */
provides java.security.Provider with
com.wolfssl.security.providers.FilteredSun,
com.wolfssl.security.providers.FilteredSunEC,
com.wolfssl.security.providers.FilteredSunRsaSign;
Comment thread
cconlon marked this conversation as resolved.
Resolved
}
51 changes: 40 additions & 11 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
without a compiled wolfSSL/wolfCrypt library:
mvn test -Dmain.tests.skip=true -->
<main.tests.skip>false</main.tests.skip>
<maven-compiler-plugin.version>3.16.0</maven-compiler-plugin.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -49,7 +50,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
Expand Down Expand Up @@ -112,7 +113,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<excludes>
<exclude>com/wolfssl/provider/jce/WolfCryptMlKemKem.java</exclude>
Expand All @@ -132,7 +133,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>${maven-compiler-plugin.version}</version>
<executions>
<!-- Compile module-info.java with Java 9 release -->
<execution>
Expand Down Expand Up @@ -172,7 +173,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>${maven-compiler-plugin.version}</version>
<executions>
<execution>
<id>compile-java15-eddsa-overlay</id>
Expand Down Expand Up @@ -255,7 +256,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<testExcludes combine.self="override"/>
</configuration>
Expand All @@ -274,6 +275,28 @@
<multiReleaseOutput>false</multiReleaseOutput>
</configuration>
</execution>
<!-- Compile the filtered-providers module-info
into the classified jar directory, after the
provider classes are copied there
(process-classes). The compiler plugin warns
"Overwriting artifact's file" here. This is
expected: default-jar sets the main artifact
back to the main jar at package. -->
<execution>
<id>compile-filtered-providers-module-info</id>
<phase>prepare-package</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>9</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/examples/filtered-providers/java9</compileSourceRoot>
</compileSourceRoots>
<outputDirectory>${project.build.directory}/filtered-providers-classes</outputDirectory>
<multiReleaseOutput>false</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>

Expand All @@ -299,11 +322,17 @@
providers in module
com.wolfssl.wolfcrypt, where the
ALL-UNNAMED add-opens below would not
reach them. The providers ship as a
plain classpath jar in real
deployments, which this matches. -->
reach them. Module path use is tested
by ant test-filtered-providers. -->
<useModulePath>false</useModulePath>
<argLine>${filtered.ec.flags} --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/sun.security.provider=ALL-UNNAMED --add-opens=java.base/sun.security.util=ALL-UNNAMED --add-opens=java.base/sun.security.rsa=ALL-UNNAMED</argLine>
<!-- The assembled jar directory
(process-classes) holds the
providers' META-INF/services file,
for the ServiceLoader test -->
<additionalClasspathElements>
<additionalClasspathElement>${project.build.directory}/filtered-providers-classes</additionalClasspathElement>
</additionalClasspathElements>
<excludes combine.self="override"/>
<includes>
<include>com/wolfssl/security/providers/test/**</include>
Expand All @@ -327,7 +356,7 @@
<executions>
<execution>
<id>assemble-filtered-providers-jar-dir</id>
<phase>prepare-package</phase>
<phase>process-classes</phase>
<goals>
<goal>copy-resources</goal>
</goals>
Expand Down Expand Up @@ -355,8 +384,8 @@
<!-- Keep the default wolfcrypt-jni.jar free of the
providers (in target/classes under this profile)
and output a separate classified jar from the
assembled directory above (provider classes plus
ServiceLoader registration). -->
assembled directory above (provider classes,
ServiceLoader registration and module-info). -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
Expand Down
Loading
Loading