Skip to content

[Android] Support delayed client certificate selection in SslStream#130755

Open
simonrozsival wants to merge 5 commits into
mainfrom
dev/simonrozsival/android-delayed-client-cert-selection
Open

[Android] Support delayed client certificate selection in SslStream#130755
simonrozsival wants to merge 5 commits into
mainfrom
dev/simonrozsival/android-delayed-client-cert-selection

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Jul 15, 2026

Copy link
Copy Markdown
Member

Fixes #109532

On Android, LocalCertificateSelectionCallback was invoked only before the TLS handshake. If it returned null, SslStream could not invoke it again when the server later sent CertificateRequest.

Install a proxy X509ExtendedKeyManager when a client selection callback is configured without an initial certificate. When JSSE processes CertificateRequest, the proxy calls into managed SslStream with the acceptable issuers and current handshake state. SslStream invokes LocalCertificateSelectionCallback, turns the selected certificate into a Java KeyManager[], and returns it to JSSE to complete the handshake.

The bridge supports exportable private keys and Android KeyStore private-key entries. It uses a typed GCHandle<JavaProxy> for the native callback lifetime, caches a successful Java key-manager selection for the connection, and surfaces delayed-callback exceptions through the TLS handshake.

Tests cover:

  • TLS 1.2 delayed selection, with and without a client certificate
  • TLS 1.3 delayed selection, with and without a client certificate
  • Delayed callback exception propagation for TLS 1.2 and TLS 1.3
  • SocketsHttpHandler selection using an Android KeyStore certificate

Note

This PR description was generated with GitHub Copilot assistance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Android SslStream TLS client-certificate plumbing so LocalCertificateSelectionCallback can be invoked later (during handshake) when the peer requests a client certificate, rather than being limited to an early/pre-handshake selection on Android.

Changes:

  • Add a proxy X509ExtendedKeyManager path on Android that can call back into managed code to select/create key managers when a CertificateRequest arrives.
  • Plumb new native exports / managed interop for registering SslStream callbacks and creating key managers for delayed selection.
  • Expand tests to cover Android delayed selection (including TLS 1.3 scenarios), exception propagation, and SocketsHttpHandler + Android KeyStore usage.
Show a summary per file
File Description
src/native/libs/System.Security.Cryptography.Native.Android/pal_trust_manager.h Renames/splits remote-cert callback registration into an internal helper used by the new combined registration path.
src/native/libs/System.Security.Cryptography.Native.Android/pal_trust_manager.c Implements internal callback registration via atomic store for remote validation callback.
src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.c Updates key manager construction to use the renamed constructor ID for PrivateKeyEntry-based managers.
src/native/libs/System.Security.Cryptography.Native.Android/pal_key_manager.h Introduces new native surface for combined SslStream callback registration + delayed key manager selection.
src/native/libs/System.Security.Cryptography.Native.Android/pal_key_manager.c Implements proxy key manager creation and JNI native method to call managed selection callback with acceptable issuers.
src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.h Adds new cached ctor method IDs for proxy vs PrivateKeyEntry DotnetX509KeyManager constructors.
src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c Registers new DotnetX509KeyManager JNI native method and initializes new ctor method IDs.
src/native/libs/System.Security.Cryptography.Native.Android/net/dot/android/crypto/DotnetX509KeyManager.java Extends to X509ExtendedKeyManager and adds proxy mode that triggers managed selection on client-cert request.
src/native/libs/System.Security.Cryptography.Native.Android/CMakeLists.txt Adds new pal_key_manager.c to native build sources.
src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs Adds LibraryImport declarations for new native exports and combined callback registration.
src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Protocol.cs Enables passing acceptable issuers into selection logic for delayed handshake selection.
src/libraries/System.Net.Security/src/System/Net/Security/SslStream.Android.cs Adds managed callback to create key managers on-demand; registers both remote validation + local selection callbacks.
src/libraries/System.Net.Security/src/System/Net/Security/Pal.Android/SafeDeleteSslContext.cs Installs proxy key manager when a selection callback exists but no initial certificate context is available.
src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Android.cs Surfaces delayed selection exceptions through handshake status mapping.
src/libraries/System.Net.Security/tests/FunctionalTests/CertificateValidationClientServer.cs Removes Android skip and adds Android-only tests for delayed selection and exception propagation (TLS 1.2/1.3).
src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.ClientCertificates.cs Adds delayed-selection coverage for SocketsHttpHandler with Android KeyStore certificate selection.

Copilot's findings

  • Files reviewed: 16/16 changed files
  • Comments generated: 0

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
Copilot AI review requested due to automatic review settings July 15, 2026 09:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 16/16 changed files
  • Comments generated: 1

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
Copilot AI review requested due to automatic review settings July 15, 2026 10:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 16/16 changed files
  • Comments generated: 0 new

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
Copilot AI review requested due to automatic review settings July 15, 2026 11:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 18/18 changed files
  • Comments generated: 0 new

@simonrozsival

Copy link
Copy Markdown
Member Author

/azp run runtime-android

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@simonrozsival
simonrozsival marked this pull request as ready for review July 16, 2026 09:55
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
10 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@simonrozsival

Copy link
Copy Markdown
Member Author

/azp run runtime-android

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

android: Cannot detect when HTTPS server needs a client certificate with SocketsHttpHandler

2 participants