1
1
package io .quarkus .security .runtime .graal ;
2
2
3
+ import java .security .Provider ;
3
4
import java .security .SecureRandom ;
5
+ import java .security .Security ;
4
6
import java .util .Arrays ;
5
7
import java .util .Set ;
6
8
import java .util .function .BooleanSupplier ;
9
11
import com .oracle .svm .core .annotate .Alias ;
10
12
import com .oracle .svm .core .annotate .RecomputeFieldValue ;
11
13
14
+ import io .quarkus .security .runtime .SecurityProviderUtils ;
15
+
12
16
final class BouncyCastlePackages {
13
17
static final String ORG_BOUNCYCASTLE_CRYPTO_PACKAGE = "org.bouncycastle.crypto" ;
14
18
static final String ORG_BOUNCYCASTLE_CRYPTO_FIPS_PACKAGE = "org.bouncycastle.crypto.fips" ;
15
19
static final String ORG_BOUNCYCASTLE_CRYPTO_INTERNAL_PACKAGE = "org.bouncycastle.crypto.internal" ;
16
20
static final String ORG_BOUNCYCASTLE_CRYPTO_GENERAL_PACKAGE = "org.bouncycastle.crypto.general" ;
21
+ static final String ORG_BOUNCYCASTLE_OPENSSL_PACKAGE = "org.bouncycastle.openssl" ;
17
22
static final Set <String > PACKAGES = Arrays .asList (Package .getPackages ()).stream ()
18
- .map (p -> p .getName ()).filter (p -> p .startsWith (ORG_BOUNCYCASTLE_CRYPTO_PACKAGE )).collect (Collectors .toSet ());
23
+ .map (Package ::getName )
24
+ .filter (p -> p .startsWith (ORG_BOUNCYCASTLE_CRYPTO_PACKAGE ) || p .startsWith (ORG_BOUNCYCASTLE_OPENSSL_PACKAGE ))
25
+ .collect (Collectors .toSet ());
19
26
}
20
27
21
28
@ com .oracle .svm .core .annotate .TargetClass (className = "org.bouncycastle.crypto.general.DSA$1" , onlyWith = BouncyCastleCryptoGeneral .class )
@@ -104,6 +111,59 @@ final class Target_org_bouncycastle_math_ec_ECPoint {
104
111
private static SecureRandom testRandom ;
105
112
}
106
113
114
+ // TODO: this should be removed when https://github.com/netty/netty/issues/14826 is addressed
115
+ // this substitution can be removed when io.quarkus.it.bouncycastle.BouncyCastleITCase#loadNettySslContext passes
116
+ @ com .oracle .svm .core .annotate .TargetClass (className = "io.netty.handler.ssl.BouncyCastlePemReader" , onlyWith = NettySslBountyCastleSupportRequired .class )
117
+ final class Target_io_netty_handler_ssl_BouncyCastlePemReader {
118
+ @ Alias
119
+ private static volatile Provider bcProvider ;
120
+ @ Alias
121
+ private static volatile boolean attemptedLoading ;
122
+ @ Alias
123
+ private static volatile Throwable unavailabilityCause ;
124
+
125
+ @ com .oracle .svm .core .annotate .Substitute
126
+ public static boolean isAvailable () {
127
+ if (!attemptedLoading ) {
128
+ // do what io.netty.handler.ssl.BouncyCastlePemReader.tryLoading does
129
+ // however Netty creates a new provider instance that doesn't have all the services
130
+ // while we take already created provider with all registered services
131
+ bcProvider = Security .getProvider (SecurityProviderUtils .BOUNCYCASTLE_PROVIDER_NAME );
132
+ if (bcProvider == null ) {
133
+ bcProvider = Security .getProvider (SecurityProviderUtils .BOUNCYCASTLE_FIPS_PROVIDER_NAME );
134
+ }
135
+ if (bcProvider == null ) {
136
+ tryLoading ();
137
+ } else {
138
+ attemptedLoading = true ;
139
+ }
140
+ }
141
+ return unavailabilityCause == null ;
142
+ }
143
+
144
+ @ Alias
145
+ private static void tryLoading () {
146
+
147
+ }
148
+ }
149
+
150
+ class NettySslBountyCastleSupportRequired implements BooleanSupplier {
151
+ @ Override
152
+ public boolean getAsBoolean () {
153
+ // this package is used by the BouncyCastlePemReader and present in 'org.bouncycastle:bcpkix-jdk18on'
154
+ if (BouncyCastlePackages .PACKAGES .contains (BouncyCastlePackages .ORG_BOUNCYCASTLE_OPENSSL_PACKAGE )) {
155
+ try {
156
+ Class .forName ("io.netty.handler.ssl.BouncyCastlePemReader" , false ,
157
+ Thread .currentThread ().getContextClassLoader ());
158
+ return true ;
159
+ } catch (Throwable e ) {
160
+ // class not available
161
+ }
162
+ }
163
+ return false ;
164
+ }
165
+ }
166
+
107
167
class BouncyCastleCryptoFips implements BooleanSupplier {
108
168
@ Override
109
169
public boolean getAsBoolean () {
@@ -123,4 +183,4 @@ class BouncyCastleCryptoInternal implements BooleanSupplier {
123
183
public boolean getAsBoolean () {
124
184
return BouncyCastlePackages .PACKAGES .contains (BouncyCastlePackages .ORG_BOUNCYCASTLE_CRYPTO_INTERNAL_PACKAGE );
125
185
}
126
- }
186
+ }
0 commit comments