[Android] Support delayed client certificate selection in SslStream#130755
Open
simonrozsival wants to merge 5 commits into
Open
[Android] Support delayed client certificate selection in SslStream#130755simonrozsival wants to merge 5 commits into
simonrozsival wants to merge 5 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 07:56 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 07:57 — with
GitHub Actions
Inactive
|
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. |
Contributor
|
Tagging subscribers to this area: @dotnet/ncl, @bartonjs, @vcsjones |
simonrozsival
had a problem deploying
to
copilot-pat-pool
July 15, 2026 07:58 — with
GitHub Actions
Failure
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 07:59 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 07:59 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 08:00 — with
GitHub Actions
Inactive
Contributor
There was a problem hiding this comment.
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
X509ExtendedKeyManagerpath on Android that can call back into managed code to select/create key managers when aCertificateRequestarrives. - 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
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 09:46 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 09:46 — with
GitHub Actions
Inactive
simonrozsival
had a problem deploying
to
copilot-pat-pool
July 15, 2026 09:48 — with
GitHub Actions
Failure
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 09:48 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 09:49 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 09:49 — with
GitHub Actions
Inactive
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 10:27 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 10:27 — with
GitHub Actions
Inactive
simonrozsival
had a problem deploying
to
copilot-pat-pool
July 15, 2026 10:28 — with
GitHub Actions
Failure
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 10:29 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 10:30 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 10:30 — with
GitHub Actions
Inactive
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d4c4e834-d70e-482c-88aa-d762e1d390bd
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 11:49 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 11:49 — with
GitHub Actions
Inactive
simonrozsival
had a problem deploying
to
copilot-pat-pool
July 15, 2026 11:50 — with
GitHub Actions
Failure
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 11:52 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 11:52 — with
GitHub Actions
Inactive
simonrozsival
temporarily deployed
to
copilot-pat-pool
July 15, 2026 11:52 — with
GitHub Actions
Inactive
This was referenced Jul 15, 2026
Open
Member
Author
|
/azp run runtime-android |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
simonrozsival
marked this pull request as ready for review
July 16, 2026 09:55
|
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. |
This was referenced Jul 16, 2026
Member
Author
|
/azp run runtime-android |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #109532
On Android,
LocalCertificateSelectionCallbackwas invoked only before the TLS handshake. If it returnednull,SslStreamcould not invoke it again when the server later sentCertificateRequest.Install a proxy
X509ExtendedKeyManagerwhen a client selection callback is configured without an initial certificate. When JSSE processesCertificateRequest, the proxy calls into managedSslStreamwith the acceptable issuers and current handshake state.SslStreaminvokesLocalCertificateSelectionCallback, turns the selected certificate into a JavaKeyManager[], 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:
SocketsHttpHandlerselection using an Android KeyStore certificateNote
This PR description was generated with GitHub Copilot assistance.