Add checkServerTrusted variant to X509TrustManagerExtensions
This variant passes down the OCSP and TLS data that may be required to
validate the Certificate Transparency status of a certificate.
This is required for network stacks that are not able to pass down an
SSLSession nor a Socket (e.g., Cronet).
Bug: 293505388
Bug: 319829948
Bug: 377159091
Test: build
API-Coverage-Bug: 376139811
Flag: android.net.platform.flags.x509_extensions_certificate_transparency
Change-Id: I0304c97e799452a51916174788ba7dd6c9a82fb6
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index e184704..e951708 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -105,6 +105,7 @@
"com.android.server.flags.services-aconfig-java",
"com.android.text.flags-aconfig-java",
"com.android.window.flags.window-aconfig-java",
+ "conscrypt_exported_aconfig_flags_lib",
"device_policy_aconfig_flags_lib",
"display_flags_lib",
"dropbox_flags_lib",
@@ -194,6 +195,14 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+// Conscrypt
+java_aconfig_library {
+ name: "conscrypt_exported_aconfig_flags_lib",
+ aconfig_declarations: "conscrypt-aconfig-flags",
+ mode: "exported",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// Telecom
java_aconfig_library {
name: "telecom_flags_core_java_lib",
diff --git a/core/api/current.txt b/core/api/current.txt
index af7d6f1..a2ded05 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29836,6 +29836,7 @@
public class X509TrustManagerExtensions {
ctor public X509TrustManagerExtensions(javax.net.ssl.X509TrustManager) throws java.lang.IllegalArgumentException;
method public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(java.security.cert.X509Certificate[], String, String) throws java.security.cert.CertificateException;
+ method @FlaggedApi("android.net.platform.flags.x509_extensions_certificate_transparency") @NonNull public java.util.List<java.security.cert.X509Certificate> checkServerTrusted(@NonNull java.security.cert.X509Certificate[], @Nullable byte[], @Nullable byte[], @NonNull String, @NonNull String) throws java.security.cert.CertificateException;
method public boolean isSameTrustConfiguration(String, String);
method public boolean isUserAddedCertificate(java.security.cert.X509Certificate);
}
diff --git a/core/java/android/net/flags.aconfig b/core/java/android/net/flags.aconfig
index f7dc790..3e7263d 100644
--- a/core/java/android/net/flags.aconfig
+++ b/core/java/android/net/flags.aconfig
@@ -28,3 +28,11 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "x509_extensions_certificate_transparency"
+ is_exported: true
+ namespace: "network_security"
+ description: "Flag to use checkServerTrusted to verify SCTs in OCSP and TLS Data"
+ bug: "319829948"
+}
diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java
index 280dad0..b44f75a 100644
--- a/core/java/android/net/http/X509TrustManagerExtensions.java
+++ b/core/java/android/net/http/X509TrustManagerExtensions.java
@@ -16,6 +16,13 @@
package android.net.http;
+import static com.android.org.conscrypt.flags.Flags.certificateTransparencyCheckservertrustedApi;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.net.platform.flags.Flags;
import android.security.net.config.UserCertificateSource;
import com.android.org.conscrypt.TrustManagerImpl;
@@ -24,6 +31,7 @@
import java.lang.reflect.Method;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import java.util.Collections;
import java.util.List;
import javax.net.ssl.X509TrustManager;
@@ -31,9 +39,9 @@
/**
* X509TrustManager wrapper exposing Android-added features.
* <p>
- * The checkServerTrusted method allows callers to perform additional
- * verification of certificate chains after they have been successfully verified
- * by the platform.
+ * The checkServerTrusted methods allow callers to provide some additional
+ * context for the verification. This is particularly useful when an SSLEngine
+ * or SSLSocket is not available.
* </p>
*/
public class X509TrustManagerExtensions {
@@ -42,6 +50,7 @@
// Methods to use when mDelegate is not a TrustManagerImpl and duck typing is being used.
private final X509TrustManager mTrustManager;
private final Method mCheckServerTrusted;
+ private final Method mCheckServerTrustedOcspAndTlsData;
private final Method mIsSameTrustConfiguration;
/**
@@ -55,6 +64,7 @@
mDelegate = (TrustManagerImpl) tm;
mTrustManager = null;
mCheckServerTrusted = null;
+ mCheckServerTrustedOcspAndTlsData = null;
mIsSameTrustConfiguration = null;
return;
}
@@ -69,8 +79,19 @@
String.class);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("Required method"
- + " checkServerTrusted(X509Certificate[], String, String, String) missing");
+ + " checkServerTrusted(X509Certificate[], String, String) missing");
}
+ // Check that the OCSP and TlsData aware checkServerTrusted is present.
+ Method checkServerTrustedOcspAndTlsData = null;
+ try {
+ checkServerTrustedOcspAndTlsData = tm.getClass().getMethod("checkServerTrusted",
+ X509Certificate[].class,
+ Byte[].class,
+ Byte[].class,
+ String.class,
+ String.class);
+ } catch (ReflectiveOperationException ignored) { }
+ mCheckServerTrustedOcspAndTlsData = checkServerTrustedOcspAndTlsData;
// Get the option isSameTrustConfiguration method.
Method isSameTrustConfiguration = null;
try {
@@ -115,6 +136,65 @@
}
/**
+ * Verifies the given certificate chain.
+ *
+ * <p>See {@link X509TrustManager#checkServerTrusted(X509Certificate[], String)} for a
+ * description of the chain and authType parameters. The final parameter, host, should be the
+ * hostname of the server.</p>
+ *
+ * <p>ocspData and tlsSctData may be provided to verify any Signed Certificate Timestamp (SCT)
+ * attached to the connection. These are ASN.1 octet strings (SignedCertificateTimestampList)
+ * as described in RFC 6962, Section 3.3. Note that SCTs embedded in the certificate chain
+ * will automatically be processed.
+ * </p>
+ *
+ * @throws CertificateException if the chain does not verify correctly.
+ * @throws IllegalArgumentException if the TrustManager is not compatible.
+ * @return the properly ordered chain used for verification as a list of X509Certificates.
+ */
+ @FlaggedApi(Flags.FLAG_X509_EXTENSIONS_CERTIFICATE_TRANSPARENCY)
+ @NonNull
+ public List<X509Certificate> checkServerTrusted(
+ @SuppressLint("ArrayReturn") @NonNull X509Certificate[] chain,
+ @Nullable byte[] ocspData,
+ @Nullable byte[] tlsSctData,
+ @NonNull String authType,
+ @NonNull String host) throws CertificateException {
+ List<X509Certificate> result;
+ if (mDelegate != null) {
+ if (certificateTransparencyCheckservertrustedApi()) {
+ result = mDelegate.checkServerTrusted(chain, ocspData, tlsSctData, authType, host);
+ return result == null ? Collections.emptyList() : result;
+ } else {
+ // The conscrypt mainline module does not have the required method.
+ throw new IllegalArgumentException("Required method"
+ + " checkServerTrusted(X509Certificate[], byte[], byte[], String, String)"
+ + " not available in TrustManagerImpl");
+ }
+ }
+ if (mCheckServerTrustedOcspAndTlsData == null) {
+ throw new IllegalArgumentException("Required method"
+ + " checkServerTrusted(X509Certificate[], byte[], byte[], String, String)"
+ + " missing");
+ }
+ try {
+ result = (List<X509Certificate>) mCheckServerTrustedOcspAndTlsData.invoke(mTrustManager,
+ ocspData, tlsSctData, chain, authType, host);
+ return result == null ? Collections.emptyList() : result;
+ } catch (IllegalAccessException e) {
+ throw new CertificateException("Failed to call checkServerTrusted", e);
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof CertificateException) {
+ throw (CertificateException) e.getCause();
+ }
+ if (e.getCause() instanceof RuntimeException) {
+ throw (RuntimeException) e.getCause();
+ }
+ throw new CertificateException("checkServerTrusted failed", e.getCause());
+ }
+ }
+
+ /**
* Checks whether a CA certificate is added by an user.
*
* <p>Since {@link X509TrustManager#checkServerTrusted} may allow its parameter {@code chain} to