-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[AndroidCrypto] Implement X509 chain building #49532
Conversation
TODO: - set custom trust root - handle revocation checking - propagate errors/status where possible
Tagging subscribers to this area: @bartonjs, @vcsjones, @krwq, @GrabYourPitchforks Issue DetailsThere isn't a way to get rich status information (like what .NET APIs expose) or ignore certain validation around chain building on Android. In order to build a chain at all through the APIs available on Android, there must be a path with a valid time, signature, name constraints, policy constraints, and trusted root.
Tests:
This gets almost all the The Platform not supported:
Not handled in this change:
cc @jkoritzinsky @steveisok @AaronRobinsonMSFT @bartonjs
|
9f84029
to
aa47315
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not familiar enough with the cert side to fully grok if the logic is correct, but generally looks good to me. Just a few small nits from my first review pass.
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509chain.c
Outdated
Show resolved
Hide resolved
...tem.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
@@ -35,7 +38,319 @@ public static bool ReleaseSafeX509ChainHandle(IntPtr handle) | |||
TimeSpan timeout, | |||
bool disableAia) | |||
{ | |||
throw new NotImplementedException(nameof(BuildChain)); | |||
var chainPal = new AndroidCertPath(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like we do anything with the disableAia
parameter here. This maps to X509ChainPolicy.DisableCertificateDownloads
from the public API.
Does Android have a way to prevent fetching intermediate certificates? If not, should a PNSE be thrown if someone sets it to true? Should we ignore it and document that it does not work in Android?
There is some precedent for ignoring it with macOS. In macOS, this property only works if revocation checking is disabled as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is actually that we don't have a good way to enable fetching. This is part of my 'not handled in this change'. By default, the fetching is disabled and can only be enabled though a system property which gets read and stored once. I don't think we really have a good way of dealing with that - I think we'd have to do something like the Unix/OpenSSl implementation's CertificateAssetDownloader
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until the need is proven otherwise, I'm OK with saying/believing that Android's use cases don't require AIA fetching.
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.h
Show resolved
Hide resolved
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509chain.c
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/DynamicChainTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
...tem.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Jeremy Barton <jbarton@microsoft.com>
...tem.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Android/ChainPal.cs
Outdated
Show resolved
Hide resolved
Validation in two passes - with / without revocation for better status
Okay. PR description has been updated. With the latest updates, the chain-related tests should be passing except for |
} | ||
} | ||
|
||
return PAL_X509ChainPartialChain; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do better than this?
The main thing is that we never return true
from chain.Build if we don't know why something failed, so this is sort of OK, but I know I'm about to ask why a PartialChain is popping up and I'm guessing it's this fallback here.
On macOS our details processing comes from weak string processing, and anytime we get an unknown value we throw an exception (since we don't know if unknown means fatal or innocuous).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A big source of PartialChain
without any details would be from the initial build (instead of the second-pass validation). Unfortunately, all seem to come as a CertPathBuilderException
with a generic message (unable to find valid certification path to requested target
) and no wrapped exception, so I don't think there's any better we can do in that case.
In the case of the CertPathValidatorException
without a reason (not set or on a version where it doesn't exist), I think we could do something like walk through any wrapped exceptions and check for specific exception types (e.g. the subclasses of CertificateException
) to determine a better status.
Testing on a version that has the reason API available, I was seeing errors with it set such that we could map them to a status, so I think it is on older versions where trying additional metrics would be helpful. I'll add it as an item to #45741.
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509chain.c
Show resolved
Hide resolved
src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509chain.c
Outdated
Show resolved
Hide resolved
...ystem.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Security.Cryptography.X509Certificates/tests/ChainTests.cs
Outdated
Show resolved
Hide resolved
...ystem.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs
Outdated
Show resolved
Hide resolved
...ystem.Security.Cryptography.X509Certificates/tests/RevocationTests/DynamicRevocationTests.cs
Outdated
Show resolved
Hide resolved
Alrighty, I think we're good on the product code, but a few bits of evolutionary cleanup remain in the test code. Almost done! |
/backport to release/6.0-preview3 |
Started backporting to release/6.0-preview3: https://github.com/dotnet/runtime/actions/runs/681018345 |
@elinor-fung backporting to release/6.0-preview3 failed, the patch most likely resulted in conflicts: $ git am --3way --ignore-whitespace --keep-non-patch changes.patch
Applying: Basic chain building
Using index info to reconstruct a base tree...
M src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt
M src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
M src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
M src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c
M src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx
M src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj
Falling back to patching base and 3-way merge...
Auto-merging src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj
CONFLICT (content): Merge conflict in src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj
Auto-merging src/libraries/System.Security.Cryptography.X509Certificates/src/Resources/Strings.resx
Auto-merging src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_x509.c
Auto-merging src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
CONFLICT (content): Merge conflict in src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.h
Auto-merging src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
CONFLICT (content): Merge conflict in src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_jni.c
Auto-merging src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt
CONFLICT (content): Merge conflict in src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
Patch failed at 0001 Basic chain building
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
Error: The process '/usr/bin/git' failed with exit code 128 Please backport manually! |
There isn't a way to get rich status information (like what .NET APIs expose) or ignore certain validation around chain building on Android. In order to build a chain at all through the APIs available on Android, there must be a path with a valid time, signature, name constraints, policy constraints, and trusted root.
CertPathBuilder
X509Chain.ChainElements
is empty andX509Chain.ChainStatus
hasPartialChain
with whatever the exception message was.CertPathValidator
PartialChain
.Tests:
RevocationResponder
to handle POST requests for OCSPAllowUnknownCertificateAuthority
to validate other scenarios. On Android, you can't build a chain at all in that case.This gets
ChainTests
,DynamicChainTests
, andDynamicRevocationTests
(outerloop) working. There is one failure inCertificateRequestChainTests
:CreateChain_RSAPSS
- fails to build any chain (zero-element,PartialChain
)Platform not supported:
AllowUnknownCertificateAuthority
,IgnoreInvalidName
,IgnoreInvalidPolicy
,IgnoreTimeNotValid
Offline
modeOnline
EndCertificateOnly
when newer Android APIs supporting it aren't availableExcludeRoot
EntireChain
ExcludeRoot
cc @jkoritzinsky @steveisok @AaronRobinsonMSFT @bartonjs