From 8ba8fbd02957a05a8ba935cfbc9ed84d48c2e85f Mon Sep 17 00:00:00 2001 From: Tom Chan Date: Mon, 10 Feb 2025 18:37:40 +0000 Subject: Do not fetch remote CRL if all certificates are recently checked This change limits remote fetches to at most once every 24 hours and reduces potentially metered network use for repeated attestations from the same device. Test: Manually, also atest AttestationVerificationTest:com.android.server.security.CertificateRevocationStatusManagerTest Bug: 389088384 Flag: EXEMPT bug fix Change-Id: Ie68b7c904b5a75145e75654f173f44655dae6d31 --- .../CertificateRevocationStatusManagerTest.java | 66 ++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'tests/AttestationVerificationTest') diff --git a/tests/AttestationVerificationTest/src/com/android/server/security/CertificateRevocationStatusManagerTest.java b/tests/AttestationVerificationTest/src/com/android/server/security/CertificateRevocationStatusManagerTest.java index c38517ace5e6..586bb76388f6 100644 --- a/tests/AttestationVerificationTest/src/com/android/server/security/CertificateRevocationStatusManagerTest.java +++ b/tests/AttestationVerificationTest/src/com/android/server/security/CertificateRevocationStatusManagerTest.java @@ -277,6 +277,72 @@ public class CertificateRevocationStatusManagerTest { } } + @Test + public void checkRevocationStatus_allCertificatesRecentlyChecked_doesNotFetchRemoteCrl() + throws Exception { + copyFromAssetToFile( + REVOCATION_LIST_WITHOUT_CERTIFICATES_USED_IN_THIS_TEST, mRevocationListFile); + mCertificateRevocationStatusManager = + new CertificateRevocationStatusManager( + mContext, mRevocationListUrl, mRevocationStatusFile, false); + mCertificateRevocationStatusManager.checkRevocationStatus(mCertificates1); + // indirectly verifies the remote list is not fetched by simulating a remote revocation + copyFromAssetToFile( + REVOCATION_LIST_WITH_CERTIFICATES_USED_IN_THIS_TEST, mRevocationListFile); + + // no exception + mCertificateRevocationStatusManager.checkRevocationStatus(mCertificates1); + } + + @Test + public void checkRevocationStatus_allCertificatesBarelyRecentlyChecked_doesNotFetchRemoteCrl() + throws Exception { + copyFromAssetToFile( + REVOCATION_LIST_WITH_CERTIFICATES_USED_IN_THIS_TEST, mRevocationListFile); + mCertificateRevocationStatusManager = + new CertificateRevocationStatusManager( + mContext, mRevocationListUrl, mRevocationStatusFile, false); + Map lastCheckedDates = new HashMap<>(); + LocalDateTime barelyRecently = + LocalDateTime.now() + .minusHours( + CertificateRevocationStatusManager.NUM_HOURS_BEFORE_NEXT_CHECK - 1); + for (X509Certificate certificate : mCertificates1) { + lastCheckedDates.put(getSerialNumber(certificate), barelyRecently); + } + mCertificateRevocationStatusManager.storeLastRevocationCheckData(lastCheckedDates); + + // Indirectly verify the remote CRL is not checked by checking there is no exception despite + // a certificate being revoked. This test differs from the next only in the lastCheckedDate, + // one before the NUM_HOURS_BEFORE_NEXT_CHECK cutoff and one after + mCertificateRevocationStatusManager.checkRevocationStatus(mCertificates1); + } + + @Test + public void checkRevocationStatus_certificatesRevokedAfterCheck_throwsException() + throws Exception { + copyFromAssetToFile( + REVOCATION_LIST_WITH_CERTIFICATES_USED_IN_THIS_TEST, mRevocationListFile); + mCertificateRevocationStatusManager = + new CertificateRevocationStatusManager( + mContext, mRevocationListUrl, mRevocationStatusFile, false); + Map lastCheckedDates = new HashMap<>(); + // To save network use, we do not check the remote CRL if all the certificates are recently + // checked, so we set the lastCheckDate to some time not recent. + LocalDateTime notRecently = + LocalDateTime.now() + .minusHours( + CertificateRevocationStatusManager.NUM_HOURS_BEFORE_NEXT_CHECK + 1); + for (X509Certificate certificate : mCertificates1) { + lastCheckedDates.put(getSerialNumber(certificate), notRecently); + } + mCertificateRevocationStatusManager.storeLastRevocationCheckData(lastCheckedDates); + + assertThrows( + CertPathValidatorException.class, + () -> mCertificateRevocationStatusManager.checkRevocationStatus(mCertificates1)); + } + private List getCertificateChain(String fileName) throws Exception { Collection certificates = mFactory.generateCertificates(mContext.getResources().getAssets().open(fileName)); -- cgit v1.2.3-59-g8ed1b