Repository navigation
Implement System.Security.Cryptography.Native.Android PAL #45741
Copy link
Copy link
Open
Labels
area-Interop-coreclros-androidtrackingThis issue is tracking the completion of other related issues.This issue is tracking the completion of other related issues.
Milestone
Description
Since we're not able to ship Openssl w/ Android, we need to implement as much as we can with the Android API's.
Implementation
- Ensure all tests pass Ensure Tests Pass Using System.Security.Cryptography.Native.Android PAL #45740
- CI build + test
- Test runs have been running out of memory in runtime-staging builds - haven't been able to repro locally. Emulator used in CI for x64:
- Build ID: QPP6.190730.005.B1
- Image: system-images;android-29;default;x86_64
- Command line arguments:
-avd <emulatorName> -memory 3072 -wipe-data -delay-adb -skip-adb-auth -no-boot-anim -no-window -no-audio -gpu swiftshader_indirect -logcat-output '/tmp/<emulatorName>-logcat.log'
- Test runs have been running out of memory in runtime-staging builds - haven't been able to repro locally. Emulator used in CI for x64:
System.Security.Cryptogaphy
- Fix reading of PEM certificate bytes where the certificate label is not the first bytes.
- Seems like Android expects the label to be the first thing (doesn't handle explanatory text or whitespace before the label)
System.Net.Security
- Basic SSL stream implementation - [AndroidCrypto] Basic SSL stream implementation #50519
- SSL configuration options
- SSL protocols - [AndroidCrypto] Handle setting non-default SslProtocols #50987
- Application protocols - [AndroidCrypto] Handle setting non-default application protocols #51187
HttpClientsetsApplicationProtocolsonly if intending to use HTTP/2+
- Cipher suites
CipherSuitesPolicythrows PNSE on Windows, so this is nice to have, but not critical
- Encryption policy - [AndroidCrypto] Handle setting non-default SslProtocols #50987
- Request client cert (server mode with
RemoteCertRequired) - [AndroidCrypto] Handle setting non-default application protocols #51187
- Implement
SslStreamPal.QueryContextChannelBinding- [AndroidCrypto] Fix handling of no peer certificates #51316 - Implement
CertificateValidationPal.GetRequestCertificateAuthorities - Automated tests
- Many existing innerloop e2e scenario tests rely on non-system-default certificate validation, which there isn't a good way for us to support (see 'Not supported' section below)
- Test app could be created such that it bundles in a network security configuration file and test root certificates: https://developer.android.com/training/articles/security-config
Not supported
The following are not supported on Android. They should be documented, marked with UnsupportedOSPlatform, and/or throw PlatformNotSupportedException as appropriate.
System.Security.Cryptogaphy
-
RC2algorithmCreateDecryptorandCreateEncryptorcurrently throw PNSE,Createdoes not
-
IncrementalHash.GetCurrentHashusing HMAC - Ignoring verification during chain building that can't be bypassed on Android:
AllowUnknownCertificateAuthority,IgnoreInvalidName,IgnoreInvalidPolicy,IgnoreTimeNotValidX509Chain.Buildwill return false and havePartialChainstatus with no certificates
- AIA fetching during chain building
- Revocation checking options - these intentionally do not throw and are treated as supported options instead
X509RevocationMode:Offlinetreated asOnlineX509RevocationFlag:EntireChaintreated asExcludeRoot
- Custom certificate stores (should be possible to do as a future improvement if desired)
- Revocation checking via OCSP on versions of Android without
PKIXRevocationChecker(API level <24)
System.Net.Security
- Non-system-default certificate validation
Any- resolved in .NET 8RemoteCertificateValidationCallbackwill only get an opportunity to validate certificates that have already been accepted by the system's built-in trust manager.This means that the use cases of the callback for self-signed certificates or custom trust will not work.- resolved in .NET 8
- Authenticating with
EncryptionPolicy.NoEncryption(onSslClientAuthenticationOptions.EncryptionPolicyorSslServerAuthenticationOptions.EncryptionPolicy) - Certain protocols (on
HttpClientHandler.SslProtocols,SslClientAuthenticationOptions.EnabledSslProtocols, orSslServerAuthenticationOptions.EnabledSslProtocols):SslProtocols.Ssl2- not supportedSslProtocols.Ssl3- not supportedSslProtocols.Tls13- only on some versions of Android (>= API level 29)
- Underscores in host name (
SslClientAuthenticationOptions.TargetHost)
Future improvements
The following should be considered after the initial implementation. If it is determined they are desired, they can be split into their own issues.
- Better error messages
- All exceptions are just dumped to the Android error log and not propagated to the calling API, so errors just come through as a generic
CryptographicException. - Some concept of storing/getting/clearing last exception at the shim API layer could be introduced in order to get actual error messages
- All exceptions are just dumped to the Android error log and not propagated to the calling API, so errors just come through as a generic
System.Security.Cryptogaphy
- Use Java Pbkdf2 implementations when on available API levels.
- Use Java PBE implementations when on available API levels.
- Use Java RSA signature APIs directly when processing data (not hashes). Requires minimum API level 23 (where all padding options are supported in Java) to be worth the cost
- Custom certificate stores
- Use some well-known location for loading/storing a
KeyStore
- Use some well-known location for loading/storing a
- Improve chain error status on versions of Android without
CertPathValidatorException.getReason(API level <24)- Try checking all the wrapped exceptions for specific
CertificateExceptiontypes to determine a better status
- Try checking all the wrapped exceptions for specific
System.Net.Security
- Investigate using JNI NIO support for byte buffers in SSL stream implementation - potential perf improvement
- Investigate handling non-system-default certificate validation
- Would require implementing a
TrustManager. Android doesn't allow defining a class via JNI, so doing this would involve actually creating/shipping a Java class. - Possible issues around Android store validation rejecting applications with trust managers deemed insecure
- If allowed certificates are known ahead of time, it would be possible to load/create
KeyStoreand useTrustManagerFactoryto create and initialize a trust manager with it.
- Would require implementing a
Clean-up
- Remove OpenSSL as a dependency in the build and all branching based on AndroidCrypto vs. OpenSSL on Android
- Rename native library:
runtime/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/CMakeLists.txt
Lines 45 to 47 in f64246c
# TODO: Use "System.Security.Cryptography.Native.Android" name (will require a lot of csproj changes here and there) set_target_properties(System.Security.Cryptography.Native.Android PROPERTIES OUTPUT_NAME "System.Security.Cryptography.Native.OpenSsl") set_target_properties(System.Security.Cryptography.Native.Android-Static PROPERTIES OUTPUT_NAME "System.Security.Cryptography.Native.OpenSsl") - Cleaner split of Android vs. OpenSSL implementations for ciphers / hashes / HMAC.
- With the original plan to just implement P/Invokes, the managed side of these were shared. Making a clean split and reworking the shim APIs to align more with Android would simplify things and reduce a bunch of interop calls.
Other
- Implement pinvokes needed to perform a simple https request - Perform simple https request with System.Security.Cryptography.Native.Android PAL #45739
- Tracking status of pinvokes implemented.
Reacted by janseris, Morten Nielsen and Ronnie Overby
Metadata
Metadata
Assignees
Labels
area-Interop-coreclros-androidtrackingThis issue is tracking the completion of other related issues.This issue is tracking the completion of other related issues.
Type
Projects
- StatusShow more project fieldsNo status
Activity
[Mono.Android-Tests] Update ignored .NET 6 tests (#5802)
JamesNK commentedon Jun 25, 2021
This makes testing against a local ASP.NET Core web app that is using a self-signed development certificate difficult.
Couldn't this be supported by creating a custom SSLSocketFactory? If
RemoteCertificateValidationCallbackis configured then there is a factory that trusts all certificates. Cert details are then passed to the callback so it can make a decision about whether the cert is allowed or not.SO answer about it - https://stackoverflow.com/a/6378872
Blog post - http://howardism.org/Technical/Java/SelfSignedCerts.html
steveisok commentedon Jun 25, 2021
@JamesNK we made the decision early on to make this a purely JNI integration. Android doesn't support creating Java classes out of JNI, which I believe makes a custom trust manager not possible.
This is something we could look at trying to support in net7.
JamesNK commentedon Jun 27, 2021
There are a number of options suggested in the SO thread that don't involve creating new Java classes. However, I don't know Java and Android HTTP APIs so I don't know what approaches are valid.
11 remaining items
dotMorten commentedon Sep 6, 2023
I'm hitting an issue with being able to use Android's Certificate picker (
KeyChain.ChoosePrivateKeyAlias), and reusing the certificate with SocketsHttpHandler. Since installed certificates can't export the private key, I can't really convert it to a .NET certificate.With the old Android client handlers, you would override
ConfigureCustomSSLSocketFactoryand returning the SSLSocketFactory to use the chosen certificate.Would this issue also address this need?
borrrden commentedon Nov 14, 2023
Has anything regarding this been done in .NET 8? Specifically I need to know if I can use a custom TLS certificate verification callback yet. In .NET 6 / 7 the only way to accomplish this is by having a system trusted certificate setup ahead of time (usually via network_security.config or whatever it is called), but in a P2P model this fails because often certs are generated on the fly purely to get the encryption portion. This means they are rejected without any remedy to explicitly trust them programmatically (the callback is simply not called and the certs are marked as untrusted)
Wait reading back I see
So this is never going to be supported?
CedreLo commentedon Nov 21, 2023
Any news on this ?
simonrozsival commentedon Nov 21, 2023
@borrrden @CedreLo hey! we shipped support for
RemoteCertificateValidationCallbackon Android in .NET 8 (#77386). You should also be able to useHttpClientHandler. ServerCertificateCustomValidationCallbackandSocketsHttpHandler.SslOptions.RemoteCertificateValidationCallback.I'll update this issue to reflect this, sorry for the confusion. Let me know if you run into any issues with the custom certificate validation.
CedreLo commentedon Nov 21, 2023
Great news!
as soon as visual studio will support ..NET8, i will switch to .NET8
borrrden commentedon Nov 21, 2023
To clarify, will this also work with
SslStreamusing the validation callback passed into the constructor? That is the use case we are currently using. The linked issue indicates yes.simonrozsival commentedon Nov 22, 2023
@borrrden yes,
SslStreamwill now use the validation callback you pass into the constructor.akoeplinger commentedon Nov 22, 2023
@CedreLo Visual Studio 2022 version 17.8 has full support for .NET8: https://devblogs.microsoft.com/visualstudio/visual-studio-17-8-now-available/
dotMorten commentedon Nov 22, 2023
@simonrozsival Will we now also be able to use the certificates installed on the device? Like the ones coming from
KeyChain.ChoosePrivateKeyAlias? We can create the X509Certificate with the Java Pointer to the Java certificate just fine, but the private key isn't directly available for .NET to use, and need to use the underlying Java APIs to authenticate the stream. (So far I've only been able to use certificates that are loaded from a file on disk and has full access to the private key, but that's not generally how customers deploy their PKI certificates, since it creates a risk of exporting the private key).simonrozsival commentedon Nov 23, 2023
@dotMorten I think there currently isn't a good way to access the certificates installed on device without using the Java APIs directly. Have you already opened an issue with the use case? If not, could you please open one? We could then discuss if that's something to look into in .NET 9.
dotMorten commentedon Mar 17, 2024
@simonrozsival For some reason I missed your comment, and for a while thought the issue was the same as this one - I've added a separate issue: #99874
dotnet-policy-service commentedon Apr 13, 2026
Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.