Skip to content

Implement System.Security.Cryptography.Native.Android PAL #45741

Open

Description

@steveisok

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'

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

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

  • RC2 algorithm
    • CreateDecryptor and CreateEncryptor currently throw PNSE, Create does not
  • IncrementalHash.GetCurrentHash using HMAC
  • Ignoring verification during chain building that can't be bypassed on Android: AllowUnknownCertificateAuthority, IgnoreInvalidName, IgnoreInvalidPolicy, IgnoreTimeNotValid
    • X509Chain.Build will return false and have PartialChain status with no certificates
  • AIA fetching during chain building
  • Revocation checking options - these intentionally do not throw and are treated as supported options instead
    • X509RevocationMode: Offline treated as Online
    • X509RevocationFlag: EntireChain treated as ExcludeRoot
  • 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 RemoteCertificateValidationCallback will only get an opportunity to validate certificates that have already been accepted by the system's built-in trust manager. - resolved in .NET 8
    • 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 (on SslClientAuthenticationOptions.EncryptionPolicy or SslServerAuthenticationOptions.EncryptionPolicy)
  • Certain protocols (on HttpClientHandler.SslProtocols, SslClientAuthenticationOptions.EnabledSslProtocols, or SslServerAuthenticationOptions.EnabledSslProtocols):
    • SslProtocols.Ssl2 - not supported
    • SslProtocols.Ssl3 - not supported
    • SslProtocols.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

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
  • Improve chain error status on versions of Android without CertPathValidatorException.getReason (API level <24)
    • Try checking all the wrapped exceptions for specific CertificateException types to determine a better status

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 KeyStore and use TrustManagerFactory to create and initialize a trust manager with it.

Clean-up

  • Remove OpenSSL as a dependency in the build and all branching based on AndroidCrypto vs. OpenSSL on Android
  • Rename native library:
    # 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

Activity

  1. added this to the 6.0.0 milestone on Dec 8, 2020
  2. removed
    untriagedNew issue has not been triaged by the area owner
    on Dec 8, 2020
  3. removed their assignment
    on Feb 10, 2021
  4. JamesNK commented on Jun 25, 2021

    @JamesNK
    Member
    • Non-system-default certificate validation

      • Any RemoteCertificateValidationCallback will 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.

    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 RemoteCertificateValidationCallback is 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

  5. steveisok commented on Jun 25, 2021

    @steveisok
    MemberAuthor

    @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.

  6. JamesNK commented on Jun 27, 2021

    @JamesNK
    Member

    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.

  7. modified the milestones: 6.0.0, 7.0.0 on Aug 19, 2021
  8. 11 remaining items

  9. dotMorten commented on Sep 6, 2023

    @dotMorten

    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 ConfigureCustomSSLSocketFactory and returning the SSLSocketFactory to use the chosen certificate.
    Would this issue also address this need?

  10. borrrden commented on Nov 14, 2023

    @borrrden

    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

    Non-system-default certificate validation

    Any RemoteCertificateValidationCallback will 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.
    

    So this is never going to be supported?

  11. CedreLo commented on Nov 21, 2023

    @CedreLo

    Any news on this ?

  12. simonrozsival commented on Nov 21, 2023

    @simonrozsival
    Member

    @borrrden @CedreLo hey! we shipped support for RemoteCertificateValidationCallback on Android in .NET 8 (#77386). You should also be able to use HttpClientHandler. ServerCertificateCustomValidationCallback and SocketsHttpHandler.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.

  13. CedreLo commented on Nov 21, 2023

    @CedreLo

    Great news!

    as soon as visual studio will support ..NET8, i will switch to .NET8

  14. borrrden commented on Nov 21, 2023

    @borrrden

    To clarify, will this also work with SslStream using the validation callback passed into the constructor? That is the use case we are currently using. The linked issue indicates yes.

  15. simonrozsival commented on Nov 22, 2023

    @simonrozsival
    Member

    @borrrden yes, SslStream will now use the validation callback you pass into the constructor.

  16. akoeplinger commented on Nov 22, 2023

    @akoeplinger
    Member

    as soon as visual studio will support ..NET8, i will switch to .NET8

    @CedreLo Visual Studio 2022 version 17.8 has full support for .NET8: https://devblogs.microsoft.com/visualstudio/visual-studio-17-8-now-available/

  17. dotMorten commented on Nov 22, 2023

    @dotMorten

    @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).

  18. simonrozsival commented on Nov 23, 2023

    @simonrozsival
    Member

    @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.

  19. dotMorten commented on Mar 17, 2024

    @dotMorten

    @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

  20. dotnet-policy-service commented on Apr 13, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @dotnet/interop-contrib
    See info in area-owners.md if you want to be subscribed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

  • Status
    No status

Relationships

None yet

Development

No branches or pull requests

Issue actions