-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
1,348 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
core/src/main/java/jayo/internal/platform/BouncyCastleJssePlatform.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* | ||
* Copyright (c) 2024-present, pull-vert and Jayo contributors. | ||
* Use of this source code is governed by the Apache 2.0 license. | ||
* | ||
* Forked from OkHttp (https://github.com/square/okhttp), original copyright is below | ||
* | ||
* Copyright (C) 2013 Square, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package jayo.internal.platform; | ||
|
||
import jayo.tls.AlpnProtocol; | ||
import org.bouncycastle.jsse.BCSSLEngine; | ||
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; | ||
import org.jspecify.annotations.NonNull; | ||
import org.jspecify.annotations.Nullable; | ||
|
||
import javax.net.ssl.SSLContext; | ||
import javax.net.ssl.SSLEngine; | ||
import javax.net.ssl.TrustManagerFactory; | ||
import javax.net.ssl.X509TrustManager; | ||
import java.security.*; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
|
||
import static jayo.tls.JssePlatform.alpnProtocolNames; | ||
|
||
/** | ||
* Platform using BouncyCastle if installed as the first Security Provider. | ||
* <p> | ||
* Requires org.bouncycastle:bctls-jdk18on on the classpath. | ||
*/ | ||
public final class BouncyCastleJssePlatform extends JdkJssePlatform { | ||
public static boolean isSupported() { | ||
try { | ||
// Trigger an early exception over a fatal error, prefer a RuntimeException over Error. | ||
Class.forName("org.bouncycastle.jsse.provider.BouncyCastleJsseProvider", false, | ||
BouncyCastleJssePlatform.class.getClassLoader()); | ||
return true; | ||
} catch (ClassNotFoundException ignored) { | ||
return false; | ||
} | ||
} | ||
|
||
public static @Nullable BouncyCastleJssePlatform buildIfSupported(boolean isFips) { | ||
return isSupported() ? new BouncyCastleJssePlatform(isFips) : null; | ||
} | ||
|
||
private final @NonNull Provider provider; | ||
|
||
private BouncyCastleJssePlatform(boolean isFips) { | ||
provider = isFips ? new BouncyCastleJsseProvider("fips:BCFIPS") : new BouncyCastleJsseProvider(); | ||
} | ||
|
||
@Override | ||
public @NonNull SSLContext newSSLContext() throws NoSuchAlgorithmException { | ||
return SSLContext.getInstance("TLS", provider); | ||
} | ||
|
||
@Override | ||
public @NonNull X509TrustManager platformTrustManager() throws NoSuchAlgorithmException, KeyStoreException, | ||
NoSuchProviderException { | ||
final var factory = TrustManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); | ||
factory.init((KeyStore) null); | ||
final var trustManagers = factory.getTrustManagers(); | ||
if (trustManagers.length != 1 | ||
|| !(trustManagers[0] instanceof X509TrustManager x509TrustManager)) { | ||
throw new IllegalStateException("Unexpected default trust managers: " + Arrays.toString(trustManagers)); | ||
} | ||
return x509TrustManager; | ||
} | ||
|
||
@Override | ||
public void configureTlsExtensions( | ||
final @NonNull SSLEngine sslEngine, | ||
final @Nullable String hostname, | ||
final @NonNull List<AlpnProtocol> protocols) { | ||
assert sslEngine != null; | ||
assert protocols != null; | ||
|
||
if (sslEngine instanceof BCSSLEngine bouncyCastleSSLEngine) { | ||
final var sslParameters = bouncyCastleSSLEngine.getParameters(); | ||
|
||
// Enable ALPN. | ||
final var names = alpnProtocolNames(protocols); | ||
sslParameters.setApplicationProtocols(names.toArray(String[]::new)); | ||
bouncyCastleSSLEngine.setParameters(sslParameters); | ||
} else { | ||
super.configureTlsExtensions(sslEngine, hostname, protocols); | ||
} | ||
} | ||
|
||
@Override | ||
public @Nullable String getSelectedProtocol(final @NonNull SSLEngine sslEngine) { | ||
assert sslEngine != null; | ||
|
||
if (sslEngine instanceof BCSSLEngine bouncyCastleSSLEngine) { | ||
final var protocol = bouncyCastleSSLEngine.getApplicationProtocol(); | ||
// Handles both un-configured and none selected. | ||
return switch (protocol) { | ||
case null -> null; | ||
case "" -> null; | ||
default -> protocol; | ||
}; | ||
} | ||
// else | ||
return super.getSelectedProtocol(sslEngine); | ||
} | ||
} |
152 changes: 152 additions & 0 deletions
152
core/src/main/java/jayo/internal/platform/ConscryptJssePlatform.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* | ||
* Copyright (c) 2024-present, pull-vert and Jayo contributors. | ||
* Use of this source code is governed by the Apache 2.0 license. | ||
* | ||
* Forked from OkHttp (https://github.com/square/okhttp), original copyright is below | ||
* | ||
* Copyright (C) 2013 Square, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package jayo.internal.platform; | ||
|
||
import jayo.tls.AlpnProtocol; | ||
import org.conscrypt.Conscrypt; | ||
import org.conscrypt.ConscryptHostnameVerifier; | ||
import org.jspecify.annotations.NonNull; | ||
import org.jspecify.annotations.Nullable; | ||
|
||
import javax.net.ssl.SSLContext; | ||
import javax.net.ssl.SSLEngine; | ||
import javax.net.ssl.SSLSession; | ||
import javax.net.ssl.X509TrustManager; | ||
import java.security.KeyStoreException; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.NoSuchProviderException; | ||
import java.security.Provider; | ||
import java.security.cert.X509Certificate; | ||
import java.util.List; | ||
|
||
import static jayo.tls.JssePlatform.alpnProtocolNames; | ||
|
||
/** | ||
* Platform using Conscrypt (<a href="https://conscrypt.org">conscrypt</a>) if installed as the first Security Provider. | ||
* <p> | ||
* Requires org.conscrypt:conscrypt-openjdk-uber >= 2.1.0 on the classpath. | ||
*/ | ||
public final class ConscryptJssePlatform extends JdkJssePlatform { | ||
public static boolean isSupported() { | ||
try { | ||
// Trigger an early exception over a fatal error, prefer a RuntimeException over Error. | ||
Class.forName("org.conscrypt.Conscrypt$Version", false, | ||
ConscryptJssePlatform.class.getClassLoader()); | ||
|
||
// Bump this version if we ever have a binary incompatibility | ||
return Conscrypt.isAvailable() && atLeastVersion(2, 1, 0); | ||
} catch (ClassNotFoundException | NoClassDefFoundError ignored) { | ||
return false; | ||
} | ||
} | ||
|
||
public static @Nullable ConscryptJssePlatform buildIfSupported() { | ||
return isSupported() ? new ConscryptJssePlatform() : null; | ||
} | ||
|
||
static boolean atLeastVersion(int major, int minor, int patch) { | ||
final var conscryptVersion = Conscrypt.version(); | ||
|
||
if (conscryptVersion.major() != major) { | ||
return conscryptVersion.major() > major; | ||
} | ||
|
||
if (conscryptVersion.minor() != minor) { | ||
return conscryptVersion.minor() > minor; | ||
} | ||
|
||
return conscryptVersion.patch() >= patch; | ||
} | ||
|
||
private final @NonNull Provider provider; | ||
|
||
private ConscryptJssePlatform() { | ||
provider = Conscrypt.newProvider(); | ||
} | ||
|
||
// See release notes https://groups.google.com/forum/#!forum/conscrypt for version differences | ||
@Override | ||
public @NonNull SSLContext newSSLContext() throws NoSuchAlgorithmException { | ||
// supports TLSv1.3 by default (version api is >= 1.4.0) | ||
return SSLContext.getInstance("TLS", provider); | ||
} | ||
|
||
@Override | ||
public @NonNull X509TrustManager platformTrustManager() throws NoSuchAlgorithmException, KeyStoreException, | ||
NoSuchProviderException { | ||
final var x509TrustManager = super.platformTrustManager(); | ||
// Disabled because Jayo will run anyway | ||
Conscrypt.setHostnameVerifier(x509TrustManager, DisabledHostnameVerifier.getInstance()); | ||
return x509TrustManager; | ||
} | ||
|
||
@Override | ||
public void configureTlsExtensions( | ||
final @NonNull SSLEngine sslEngine, | ||
final @Nullable String hostname, | ||
final @NonNull List<AlpnProtocol> protocols) { | ||
assert sslEngine != null; | ||
assert protocols != null; | ||
|
||
if (Conscrypt.isConscrypt(sslEngine)) { | ||
// Enable session tickets. | ||
Conscrypt.setUseSessionTickets(sslEngine, true); | ||
|
||
// Enable ALPN. | ||
final var names = alpnProtocolNames(protocols); | ||
Conscrypt.setApplicationProtocols(sslEngine, names.toArray(String[]::new)); | ||
} else { | ||
super.configureTlsExtensions(sslEngine, hostname, protocols); | ||
} | ||
} | ||
|
||
@Override | ||
public @Nullable String getSelectedProtocol(final @NonNull SSLEngine sslEngine) { | ||
assert sslEngine != null; | ||
|
||
if (Conscrypt.isConscrypt(sslEngine)) { | ||
return Conscrypt.getApplicationProtocol(sslEngine); | ||
} | ||
// else | ||
return super.getSelectedProtocol(sslEngine); | ||
} | ||
|
||
private static final class DisabledHostnameVerifier implements ConscryptHostnameVerifier { | ||
private static ConscryptHostnameVerifier INSTANCE; | ||
|
||
private DisabledHostnameVerifier() { | ||
} | ||
|
||
private static ConscryptHostnameVerifier getInstance() { | ||
if (INSTANCE == null) { | ||
INSTANCE = new DisabledHostnameVerifier(); | ||
} | ||
|
||
return INSTANCE; | ||
} | ||
|
||
@Override | ||
public boolean verify(X509Certificate[] x509Certificates, String s, SSLSession sslSession) { | ||
return true; | ||
} | ||
} | ||
} |
Oops, something went wrong.