diff options
author | Hai Shalom <haishalom@google.com> | 2020-04-09 19:10:06 -0700 |
---|---|---|
committer | Hai Shalom <haishalom@google.com> | 2020-04-13 16:25:48 -0700 |
commit | f17e56bbd9dd09169b9b4a6b9735acda9d31b9d1 (patch) | |
tree | 95c19375c554482d9cab891b86b0a362c1a781ff /service | |
parent | 6e5f940b37880a6d05a9a50c0dbb7245f2448ce0 (diff) |
[Passpoint] Add metrics for Root CA and Subscription Expiration
Add metrics for counting profiles with no Root CA, profiles
with self-signed Root CAs and profiles with Subscription Expiration.
Bug: 153695144
Test: atest PasspointManagerTest
Test: atest WifiMetricsTest
Change-Id: I94dd0a3a8948d612a3bccdcf6fcea677f93d97bf
Diffstat (limited to 'service')
-rw-r--r-- | service/java/com/android/server/wifi/WifiMetrics.java | 27 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/hotspot2/PasspointManager.java | 69 | ||||
-rw-r--r-- | service/proto/src/metrics.proto | 9 |
3 files changed, 105 insertions, 0 deletions
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index 0760dee4a..a9385ed91 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -2657,6 +2657,33 @@ public class WifiMetrics { } /** + * Increment number of Passpoint providers with no Root CA in their profile. + */ + public void incrementNumPasspointProviderWithNoRootCa() { + synchronized (mLock) { + mWifiLogProto.numPasspointProviderWithNoRootCa++; + } + } + + /** + * Increment number of Passpoint providers with a self-signed Root CA in their profile. + */ + public void incrementNumPasspointProviderWithSelfSignedRootCa() { + synchronized (mLock) { + mWifiLogProto.numPasspointProviderWithSelfSignedRootCa++; + } + } + + /** + * Increment number of Passpoint providers with subscription expiration date in their profile. + */ + public void incrementNumPasspointProviderWithSubscriptionExpiration() { + synchronized (mLock) { + mWifiLogProto.numPasspointProviderWithSubscriptionExpiration++; + } + } + + /** * Increment number of times we detected a radio mode change to MCC. */ public void incrementNumRadioModeChangeToMcc() { diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java index a702c7e98..b60ef3f63 100644 --- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java +++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java @@ -29,6 +29,8 @@ import static android.net.wifi.WifiManager.EXTRA_ICON; import static android.net.wifi.WifiManager.EXTRA_SUBSCRIPTION_REMEDIATION_METHOD; import static android.net.wifi.WifiManager.EXTRA_URL; +import static java.security.cert.PKIXReason.NO_TRUST_ANCHOR; + import android.annotation.NonNull; import android.app.AppOpsManager; import android.content.Context; @@ -65,7 +67,16 @@ import com.android.server.wifi.hotspot2.anqp.HSOsuProvidersElement; import com.android.server.wifi.hotspot2.anqp.OsuProviderInfo; import com.android.server.wifi.util.InformationElementUtil; +import java.io.IOException; import java.io.PrintWriter; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.CertPath; +import java.security.cert.CertPathValidator; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertificateFactory; +import java.security.cert.PKIXParameters; +import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -439,6 +450,34 @@ public class PasspointManager { mWifiCarrierInfoManager, mProviderIndex++, uid, packageName, isFromSuggestion); newProvider.setTrusted(isTrusted); + boolean metricsNoRootCa = false; + boolean metricsSelfSignedRootCa = false; + boolean metricsSubscriptionExpiration = false; + + if (config.getCredential().getUserCredential() != null + || config.getCredential().getCertCredential() != null) { + X509Certificate[] x509Certificates = config.getCredential().getCaCertificates(); + if (x509Certificates == null) { + metricsNoRootCa = true; + } else { + try { + for (X509Certificate certificate : x509Certificates) { + verifyCaCert(certificate); + } + } catch (CertPathValidatorException e) { + // A self signed Root CA will fail path validation checks with NO_TRUST_ANCHOR + if (e.getReason() == NO_TRUST_ANCHOR) { + metricsSelfSignedRootCa = true; + } + } catch (Exception e) { + // Other exceptions, fall through, will be handled below + } + } + } + if (config.getSubscriptionExpirationTimeMillis() != Long.MIN_VALUE) { + metricsSubscriptionExpiration = true; + } + if (!newProvider.installCertsAndKeys()) { Log.e(TAG, "Failed to install certificates and keys to keystore"); return false; @@ -477,6 +516,15 @@ public class PasspointManager { Log.d(TAG, "Added/updated Passpoint configuration for FQDN: " + config.getHomeSp().getFqdn() + " with unique ID: " + config.getUniqueId() + " by UID: " + uid); + if (metricsNoRootCa) { + mWifiMetrics.incrementNumPasspointProviderWithNoRootCa(); + } + if (metricsSelfSignedRootCa) { + mWifiMetrics.incrementNumPasspointProviderWithSelfSignedRootCa(); + } + if (metricsSubscriptionExpiration) { + mWifiMetrics.incrementNumPasspointProviderWithSubscriptionExpiration(); + } mWifiMetrics.incrementNumPasspointProviderInstallSuccess(); return true; } @@ -1256,4 +1304,25 @@ public class PasspointManager { mAnqpRequestManager.clear(); mAnqpCache.flush(); } + + /** + * Verify that the given certificate is trusted by one of the pre-loaded public CAs in the + * system key store. + * + * @param caCert The CA Certificate to verify + * @throws CertPathValidatorException + * @throws Exception + */ + private void verifyCaCert(X509Certificate caCert) + throws GeneralSecurityException, IOException { + CertificateFactory factory = CertificateFactory.getInstance("X.509"); + CertPathValidator validator = + CertPathValidator.getInstance(CertPathValidator.getDefaultType()); + CertPath path = factory.generateCertPath(Arrays.asList(caCert)); + KeyStore ks = KeyStore.getInstance("AndroidCAStore"); + ks.load(null, null); + PKIXParameters params = new PKIXParameters(ks); + params.setRevocationEnabled(false); + validator.validate(path, params); + } } diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto index 932fb2e0f..1f6848482 100644 --- a/service/proto/src/metrics.proto +++ b/service/proto/src/metrics.proto @@ -675,6 +675,15 @@ message WifiLog { // (SSID, BSSID) tuple depending on AP configuration (in the above priority // order). repeated NumConnectableNetworksBucket observed_hotspot_r3_ess_in_scan_histogram = 188; + + // Total number of Passpoint providers with no Root CA in their profile. + optional int32 num_passpoint_provider_with_no_root_ca = 189; + + // Total number of Passpoint providers with self-signed root CA in their profile. + optional int32 num_passpoint_provider_with_self_signed_root_ca = 190; + + // Total number of Passpoint providers with subscription expiration date in their profile. + optional int32 num_passpoint_provider_with_subscription_expiration = 191; } // Information that gets logged for every WiFi connection. |