Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Self signed certificates with user-installed CA show as revoked on Android #69

Closed
dani-garcia opened this issue Mar 6, 2024 · 10 comments · Fixed by #108
Closed

Self signed certificates with user-installed CA show as revoked on Android #69

dani-garcia opened this issue Mar 6, 2024 · 10 comments · Fixed by #108

Comments

@dani-garcia
Copy link

I’ve been testing the use of this library and while it’s been working great so far on Mac, iOS and Android for certificates generated from system-trusted CAs, I’ve found that Android can’t seem to deal with certificates signed by user-installed CAs, and always reports them as Revoked.

My tests have gone like this:

  • Make an HTTPS request to a site using a self signed certificate (for example https://untrusted-root.badssl.com/). This returns InvalidCertificate(UnknownIssuer) on all platforms, which is expected.
  • Get the CA certificate from that domain and install it in the OS trust store
  • Make a new request again, this succeeds in Mac and iOS, but on Android I get InvalidCertificate(Revoked)

I've also tested other certificates signed by a local CA in a dev server, like the ones generated by mkcert, and I can reproduce the same problem there too.

I've also checked that the requests succeed if you make them with an Android native HTTP client (like Kotlins Ktor HTTP client), which suggests to me that the certificate is installed correctly at least.

Any ideas what could be causing this issue?

PS: I have made a small app to reproduce the issue if that helps, it's just using the ureq library with rustls-platform-verifier, and can be used from the included Android app and the CLI: https://github.com/dani-garcia/rpv-selfsigned

@cpu
Copy link
Member

cpu commented Mar 12, 2024

Hi @dani-garcia,

Thanks for opening an issue and linking to your reproducer. This is a curious situation and I don't have any immediate ideas.

Based on what you describe it sounds like X509TrustManager.checkServerTrusted is passing for the presented chain using the Android trust store, but CertPathValidator.validate is throwing an exception we map to the revoked state (possibly masking an underlying error of a different sort?).

I think reproducing this with a test run in the emulator would be a good next step. I think it's likely that either the revocation checking is expecting certain metadata that isn't present in the added trust anchor and is failing closed, or there is a separate validation error being presented incorrectly as a revocation error.

The main open question in my mind is the best way to programmatically inject a new trust anchor into the emulator's system trust bundle to make writing a test possible. How did you handle that in your rpv-selfsigned reproducer?

@cpu
Copy link
Member

cpu commented Mar 13, 2024

The main open question in my mind is the best way to programmatically inject a new trust anchor into the emulator's system trust bundle

Perhaps like this: https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/

@cpu
Copy link
Member

cpu commented Mar 13, 2024

Perhaps like this: https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/

Ah, I misread. These instructions inject a trust anchor as if it were system provided to explicitly side-step the usual opt-in that's required for user-installed trust anchors. I think to repro this we want to programmatically mount a user-installed trust anchor and then make sure the test application is opted in to the mechanism that allows its use, like you appear to have done in the repro app.

@dani-garcia
Copy link
Author

I've done my testing on an Android 14 emulator, and haven't found a way to automate the user provided certificate installation, so I just copied the certificate over with ADB and then installed it myself and ran the repro manually:

This is how I copied and installed the cert

In that file there are also some of the attempts I tried to install the certificate in the user trust store, but I couldn't get it to work. I'll check if I can find another way to automate the process.

I've also updated the repro to remove the HTTP client and instead use rustls_platform_verifier::Verifier::new().verify_server_cert(...) directly in case it was causing problems or hiding the error but I still get the same result:

  • On MacOS: Ok(ServerCertVerified(()))
  • On Android: Err(InvalidCertificate(Revoked))

@flisky
Copy link

flisky commented May 30, 2024

try {
validator.validate(certFactory.generateCertPath(validChain), parameters)
} catch (e: CertPathValidatorException) {
return VerificationResult(StatusCode.Revoked, e.toString())
}

In my case, e is java.security.cert.CertPathValidatorException: Certificate does not specify OCSP responder, so I vendor the CertificateVerifier.kt and disable OCSP validation when building debug app.

@complexspaces
Copy link
Collaborator

@flisky Thank you for that extra information!

@cpu I think that bringing back the isKnownRoot check that existed prior to #40 might be the solution here. IMO, we shouldn't be attempting the revocation codepath for non-public certificate chains here since enterprises and other self-signed issuance cases aren't required to meet the same bar.

I suspect (but don't have the time to verify) that the reason it works fine on macOS is because it doesn't have the same very-strict revocation certificate extension data requirements that Android's implementation does.

@cpu
Copy link
Member

cpu commented Jun 4, 2024

@cpu I think that bringing back the isKnownRoot check that existed prior to #40 might be the solution here.

Sounds reasonable to me. Do you think you'll have time to open a PR or should I look at doing that? I could probably find time closer to the end of the week.

@complexspaces
Copy link
Collaborator

I think that I can get a PR open for this 👍

@complexspaces
Copy link
Collaborator

complexspaces commented Jul 4, 2024

If anyone has the time, I would appreciate a look and attempt to try running #108. It should resolve this issue from my testing.

@dani-garcia
Copy link
Author

Sorry for the delay, I tested the changes in the PR and it also solves my issues, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants