Skip to content

Commit e49d7ec

Browse files
[Android] Fix SslStream.IsMutuallyAuthenticated (#79601)
* Implement CertificateValidationPal.IsLocalCertificateUsed on Android * Enable test on Android * Update comment
1 parent a88b1a4 commit e49d7ec

7 files changed

Lines changed: 42 additions & 4 deletions

File tree

src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Ssl.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ internal static void SSLStreamSetTargetHost(
8686
throw new SslException();
8787
}
8888

89+
[LibraryImport(Interop.Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamIsLocalCertificateUsed")]
90+
[return: MarshalAs(UnmanagedType.U1)]
91+
internal static partial bool SSLStreamIsLocalCertificateUsed(SafeSslHandle sslHandle);
92+
8993
[LibraryImport(Interop.Libraries.AndroidCryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamRequestClientAuthentication")]
9094
internal static partial void SSLStreamRequestClientAuthentication(SafeSslHandle sslHandle);
9195

src/libraries/System.Net.Security/src/System/Net/CertificateValidationPal.Android.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,15 @@ internal static SslPolicyErrors VerifyCertificateProperties(
9191
return cert;
9292
}
9393

94-
// This is only called when we selected local client certificate.
95-
// Currently this is only when Java crypto asked for it.
96-
internal static bool IsLocalCertificateUsed(SafeDeleteContext? _) => true;
94+
// Check if the local certificate has been sent to the peer during the handshake.
95+
internal static bool IsLocalCertificateUsed(SafeDeleteContext? securityContext)
96+
{
97+
SafeSslHandle? sslContext = ((SafeDeleteSslContext?)securityContext)?.SslContext;
98+
if (sslContext == null)
99+
return false;
100+
101+
return Interop.AndroidCrypto.SSLStreamIsLocalCertificateUsed(sslContext);
102+
}
97103

98104
//
99105
// Used only by client SSL code, never returns null.

src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamMutualAuthenticationTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ public async Task SslStream_RequireClientCert_IsMutuallyAuthenticated_ReturnsTru
8686

8787
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindows7))]
8888
[ClassData(typeof(SslProtocolSupport.SupportedSslProtocolsTestData))]
89-
[ActiveIssue("https://github.com/dotnet/runtime/issues/65563", TestPlatforms.Android)]
9089
public async Task SslStream_CachedCredentials_IsMutuallyAuthenticatedCorrect(
9190
SslProtocols protocol)
9291
{

src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ jmethodID g_SSLContextCreateSSLEngineMethodWithHostAndPort;
463463
jclass g_SSLSession;
464464
jmethodID g_SSLSessionGetApplicationBufferSize;
465465
jmethodID g_SSLSessionGetCipherSuite;
466+
jmethodID g_SSLSessionGetLocalCertificates;
466467
jmethodID g_SSLSessionGetPacketBufferSize;
467468
jmethodID g_SSLSessionGetPeerCertificates;
468469
jmethodID g_SSLSessionGetProtocol;
@@ -1054,6 +1055,7 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
10541055
g_SSLSession = GetClassGRef(env, "javax/net/ssl/SSLSession");
10551056
g_SSLSessionGetApplicationBufferSize = GetMethod(env, false, g_SSLSession, "getApplicationBufferSize", "()I");
10561057
g_SSLSessionGetCipherSuite = GetMethod(env, false, g_SSLSession, "getCipherSuite", "()Ljava/lang/String;");
1058+
g_SSLSessionGetLocalCertificates = GetMethod(env, false, g_SSLSession, "getLocalCertificates", "()[Ljava/security/cert/Certificate;");
10571059
g_SSLSessionGetPacketBufferSize = GetMethod(env, false, g_SSLSession, "getPacketBufferSize", "()I");
10581060
g_SSLSessionGetPeerCertificates = GetMethod(env, false, g_SSLSession, "getPeerCertificates", "()[Ljava/security/cert/Certificate;");
10591061
g_SSLSessionGetProtocol = GetMethod(env, false, g_SSLSession, "getProtocol", "()Ljava/lang/String;");

src/native/libs/System.Security.Cryptography.Native.Android/pal_jni.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,7 @@ extern jmethodID g_SSLContextCreateSSLEngineMethodWithHostAndPort;
477477
extern jclass g_SSLSession;
478478
extern jmethodID g_SSLSessionGetApplicationBufferSize;
479479
extern jmethodID g_SSLSessionGetCipherSuite;
480+
extern jmethodID g_SSLSessionGetLocalCertificates;
480481
extern jmethodID g_SSLSessionGetPacketBufferSize;
481482
extern jmethodID g_SSLSessionGetPeerCertificates;
482483
extern jmethodID g_SSLSessionGetProtocol;

src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,6 +1039,25 @@ bool AndroidCryptoNative_SSLStreamVerifyHostname(SSLStream* sslStream, char* hos
10391039
return ret;
10401040
}
10411041

1042+
bool AndroidCryptoNative_SSLStreamIsLocalCertificateUsed(SSLStream* sslStream)
1043+
{
1044+
abort_if_invalid_pointer_argument(sslStream);
1045+
JNIEnv* env = GetJNIEnv();
1046+
1047+
bool ret = false;
1048+
INIT_LOCALS(loc, localCertificates);
1049+
1050+
// X509Certificate[] localCertificates = sslSession.getLocalCertificates();
1051+
loc[localCertificates] = (*env)->CallObjectMethod(env, sslStream->sslSession, g_SSLSessionGetLocalCertificates);
1052+
ON_EXCEPTION_PRINT_AND_GOTO(cleanup);
1053+
1054+
ret = loc[localCertificates] != NULL;
1055+
1056+
cleanup:
1057+
RELEASE_LOCALS(loc, env);
1058+
return ret;
1059+
}
1060+
10421061
bool AndroidCryptoNative_SSLStreamShutdown(SSLStream* sslStream)
10431062
{
10441063
abort_if_invalid_pointer_argument (sslStream);

src/native/libs/System.Security.Cryptography.Native.Android/pal_sslstream.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ Returns 1 on success, 0 otherwise
7777
*/
7878
PALEXPORT int32_t AndroidCryptoNative_SSLStreamSetTargetHost(SSLStream* sslStream, char* targetHost);
7979

80+
/*
81+
Check if the local certificate has been sent to the peer during the TLS handshake.
82+
83+
Returns true if the local certificate has been sent to the peer, false otherwise.
84+
*/
85+
PALEXPORT bool AndroidCryptoNative_SSLStreamIsLocalCertificateUsed(SSLStream* sslStream);
86+
8087
/*
8188
Start or continue the TLS handshake
8289
*/

0 commit comments

Comments
 (0)