RFR: 8347067: Load certificates without explicit trust settings in KeyChainStore
Alexey Bakhtin
abakhtin at openjdk.org
Fri Jan 24 21:17:27 UTC 2025
On Fri, 3 Jan 2025 11:28:01 GMT, Tim Jacomb <duke at openjdk.org> wrote:
> ## The change
>
> Without this change intermediate certificates that don't have explicit trust settings are ignored not added to the truststore.
>
>
>
> ## Reproducer
>
> See https://github.com/timja/openjdk-intermediate-ca-reproducer
>
> Without this change the reproducer fails, and with this change it succeeds.
>
> ## Example failing architecture
>
> Root CA -> Intermediate 1 -> Intermediate 2 -> Leaf
>
> Where:
> * All certs are in admin domain kSecTrustSettingsDomainAdmin
> * Root CA is marked as always trust
> * Intermediate 1 and 2 are Unspecified
>
> Previously Root CA would be found but intermediate 1 and 2 would be skipped when verifying trust settings.
>
> ## Background reading
>
> ### Rust
> see also Rust Lib that is used throughout Rust ecosystem for this:
> https://github.com/rustls/rustls-native-certs/blob/efe7b1d77bf6080851486535664d1dc7ef0dea68/src/macos.rs#L39-L58
>
> e.g. in Deno `https://github.com/denoland/deno/pull/11491` where I've verified it is correctly implemented and works in my setup
>
> ## Python
>
> I also looked at the Python implementation for inspiration as well (which also works on my system): https://github.com/sethmlarson/truststore/blob/main/src/truststore/_macos.py
I'm afraid but it looks like this implementation violates the https://developer.apple.com/documentation/security/sectrustsettingscopytrustsettings(_:_:_:) specification.
It always creates an empty input trust and fills it with the provided non-null trustSettings. So, the certificate always has at least empty trustSettings. However, according to this specification, two different scenarios should be considered:
1. Empty trustSettings means that the certificate is trusted if it is self-signed.
2. Null trustSettings means that the certificate must be verified before adding to the trust store.
The current implementation adds Root certificate to the TrustStore because it has "Always Trust" settings.
Implementation does not add the intermediate certificate to the TrustStore because it has "System Defaults" settings ( SecTrustSettingsCopyTrustSettings returns null trustSettings), and the current implementation only adds certificates with trust settings.
I think, in this particular case, we need two iterations to add certificates into the trust store. The first iteration will add certificates with non-null trust settings, and the second iteration should verify and add certificates with null trust settings.
Thank you for this patch. It looks correct now (see my comment about subjCerts above)
Is it possible to add jtreg test for this scenario?
Also, You'll need a jbs issue to submit this PR
src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m line 480:
> 478: CFRelease(policy);
> 479: }
> 480: if (secTrust) {
I think subjCerts should be released here too
-------------
PR Comment: https://git.openjdk.org/jdk/pull/22911#issuecomment-2569957562
PR Comment: https://git.openjdk.org/jdk/pull/22911#issuecomment-2573747523
PR Review Comment: https://git.openjdk.org/jdk/pull/22911#discussion_r1904455215
More information about the security-dev
mailing list