Skip to content

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

@steveisok

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

Metadata

Metadata

Assignees

Type

No type

Projects

Status

No status

Relationships

None yet

Development

No branches or pull requests

Issue actions