Closed dani-garcia closed 1 week ago
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?
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/
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.
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:
Ok(ServerCertVerified(()))
Err(InvalidCertificate(Revoked))
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.
@flisky Thank you for that extra information!
@cpu I think that bringing back the isKnownRoot
check that existed prior to https://github.com/rustls/rustls-platform-verifier/pull/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 I think that bringing back the isKnownRoot check that existed prior to https://github.com/rustls/rustls-platform-verifier/pull/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.
I think that I can get a PR open for this 👍
If anyone has the time, I would appreciate a look and attempt to try running #108. It should resolve this issue from my testing.
Sorry for the delay, I tested the changes in the PR and it also solves my issues, thank you!
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:
https://untrusted-root.badssl.com/
). This returnsInvalidCertificate(UnknownIssuer)
on all platforms, which is expected.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 withrustls-platform-verifier
, and can be used from the included Android app and the CLI: https://github.com/dani-garcia/rpv-selfsigned