Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AndroidCrypto] Handle setting non-default SslProtocols #50987

Merged
merged 7 commits into from
Apr 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.InteropServices;
using System.Security.Authentication;

internal static partial class Interop
{
internal static partial class AndroidCrypto
{
[DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLGetSupportedProtocols")]
internal static extern SslProtocols SSLGetSupportedProtocols();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Buffers;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

using Microsoft.Win32.SafeHandles;
Expand Down Expand Up @@ -78,6 +79,15 @@ internal static void SSLStreamConfigureParameters(
throw new SslException();
}

[DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamSetEnabledProtocols")]
private static extern int SSLStreamSetEnabledProtocols(SafeSslHandle sslHandle, ref SslProtocols protocols, int length);
internal static void SSLStreamSetEnabledProtocols(SafeSslHandle sslHandle, ReadOnlySpan<SslProtocols> protocols)
{
int ret = SSLStreamSetEnabledProtocols(sslHandle, ref MemoryMarshal.GetReference(protocols), protocols.Length);
if (ret != SUCCESS)
throw new SslException();
}

[DllImport(Interop.Libraries.CryptoNative, EntryPoint = "AndroidCryptoNative_SSLStreamHandshake")]
internal static extern PAL_SSLStreamStatus SSLStreamHandshake(SafeSslHandle sslHandle);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static partial class PlatformDetection

public static bool IsSuperUser => IsBrowser || IsWindows ? false : libc.geteuid() == 0;

public static Version OpenSslVersion => !IsOSXLike && !IsWindows ?
public static Version OpenSslVersion => !IsOSXLike && !IsWindows && !IsAndroid ?
GetOpenSslVersion() :
throw new PlatformNotSupportedException();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static bool IsDrawingSupported

}
}

public static bool IsLineNumbersSupported => true;

public static bool IsInContainer => GetIsInContainer();
Expand Down Expand Up @@ -293,6 +293,13 @@ private static bool OpenSslGetTlsSupport(SslProtocols protocol)
return ret == 1;
}

private static readonly Lazy<SslProtocols> s_androidSupportedSslProtocols = new Lazy<SslProtocols>(Interop.AndroidCrypto.SSLGetSupportedProtocols);
private static bool AndroidGetSslProtocolSupport(SslProtocols protocol)
{
Debug.Assert(IsAndroid);
return (protocol & s_androidSupportedSslProtocols.Value) == protocol;
}

private static bool GetTls10Support()
{
// on Windows, macOS, and Android TLS1.0/1.1 are supported.
Expand Down Expand Up @@ -359,6 +366,14 @@ private static bool GetTls13Support()
// [ActiveIssue("https://github.com/dotnet/runtime/issues/1979")]
return false;
}
else if (IsAndroid)
{
#if NETFRAMEWORK
return false;
#else
return AndroidGetSslProtocolSupport(SslProtocols.Tls13);
#endif
}
else if (IsOpenSslSupported)
{
// Covers Linux, FreeBSD, illumos and Solaris
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<Compile Include="System\PlatformDetection.cs" />
<Compile Include="System\PlatformDetection.Unix.cs" />
<Compile Include="System\PlatformDetection.Windows.cs" />
<!--
<!--
Interop.Library is not designed to support runtime checks therefore we are picking the Windows
variant from the Common folder and adding the missing members manually.
-->
Expand Down Expand Up @@ -66,6 +66,11 @@
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetEUid.cs"
Link="Common\Interop\Unix\Interop.GetEUid.cs" />
</ItemGroup>
<!-- Android imports -->
<ItemGroup>
<Compile Include="$(CommonPath)Interop\Android\System.Security.Cryptography.Native.Android\Interop.Ssl.ProtocolSupport.cs"
Link="Common\Interop\Android\System.Security.Cryptography.Native.Android\Interop.Ssl.ProtocolSupport.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.XUnitExtensions" Version="$(MicrosoftDotNetXUnitExtensionsVersion)" />
<PackageReference Include="xunit.core" Version="$(XUnitVersion)" ExcludeAssets="build" />
Expand Down
19 changes: 19 additions & 0 deletions src/libraries/Native/Unix/Common/pal_ssl_types.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma once

#include <stdint.h>

// Matches managed System.Security.Authentication.SslProtocols
enum
{
PAL_SslProtocol_None = 0,
PAL_SslProtocol_Ssl2 = 12,
PAL_SslProtocol_Ssl3 = 48,
PAL_SslProtocol_Tls10 = 192,
PAL_SslProtocol_Tls11 = 768,
PAL_SslProtocol_Tls12 = 3072,
PAL_SslProtocol_Tls13 = 12288,
};
typedef int32_t PAL_SslProtocol;
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,8 @@ jmethodID g_SSLEngineWrap;
jmethodID g_SSLEngineUnwrap;
jmethodID g_SSLEngineCloseOutbound;
jmethodID g_SSLEngineGetHandshakeStatus;
jmethodID g_SSLEngineGetSupportedProtocols;
jmethodID g_SSLEngineSetEnabledProtocols;
jmethodID g_SSLEngineSetSSLParameters;

// java/nio/ByteBuffer
Expand Down Expand Up @@ -976,6 +978,8 @@ JNI_OnLoad(JavaVM *vm, void *reserved)
g_SSLEngineUnwrap = GetMethod(env, false, g_SSLEngine, "unwrap", "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)Ljavax/net/ssl/SSLEngineResult;");
g_SSLEngineGetHandshakeStatus = GetMethod(env, false, g_SSLEngine, "getHandshakeStatus", "()Ljavax/net/ssl/SSLEngineResult$HandshakeStatus;");
g_SSLEngineCloseOutbound = GetMethod(env, false, g_SSLEngine, "closeOutbound", "()V");
g_SSLEngineGetSupportedProtocols = GetMethod(env, false, g_SSLEngine, "getSupportedProtocols", "()[Ljava/lang/String;");
g_SSLEngineSetEnabledProtocols = GetMethod(env, false, g_SSLEngine, "setEnabledProtocols", "([Ljava/lang/String;)V");
g_SSLEngineSetSSLParameters = GetMethod(env, false, g_SSLEngine, "setSSLParameters", "(Ljavax/net/ssl/SSLParameters;)V");

g_ByteBuffer = GetClassGRef(env, "java/nio/ByteBuffer");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,8 @@ extern jmethodID g_SSLEngineWrap;
extern jmethodID g_SSLEngineUnwrap;
extern jmethodID g_SSLEngineCloseOutbound;
extern jmethodID g_SSLEngineGetHandshakeStatus;
extern jmethodID g_SSLEngineGetSupportedProtocols;
extern jmethodID g_SSLEngineSetEnabledProtocols;
extern jmethodID g_SSLEngineSetSSLParameters;

// java/nio/ByteBuffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,51 @@

#include "pal_ssl.h"

int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol)
PAL_SslProtocol AndroidCryptoNative_SSLGetSupportedProtocols(void)
{
JNIEnv* env = GetJNIEnv();
jobject sslCtxObj = (*env)->CallStaticObjectMethod(env, g_sslCtxClass, g_sslCtxGetDefaultMethod);
jobject sslParametersObj = (*env)->CallObjectMethod(env, sslCtxObj, g_sslCtxGetDefaultSslParamsMethod);
jobjectArray protocols = (jobjectArray)(*env)->CallObjectMethod(env, sslParametersObj, g_SSLParametersGetProtocols);
PAL_SslProtocol supported = 0;
INIT_LOCALS(loc, context, params, protocols);

int protocolsCount = (*env)->GetArrayLength(env, protocols);
int supported = 0;
for (int i = 0; i < protocolsCount; i++)
// SSLContext context = SSLContext.getDefault();
// SSLParameters params = context.getDefaultSSLParameters();
// String[] protocols = params.getProtocols();
loc[context] = (*env)->CallStaticObjectMethod(env, g_sslCtxClass, g_sslCtxGetDefaultMethod);
loc[params] = (*env)->CallObjectMethod(env, loc[context], g_sslCtxGetDefaultSslParamsMethod);
loc[protocols] = (*env)->CallObjectMethod(env, loc[params], g_SSLParametersGetProtocols);

const char tlsv1[] = "TLSv1";
size_t tlsv1Len = (sizeof(tlsv1) / sizeof(*tlsv1)) - 1;

jsize count = (*env)->GetArrayLength(env, loc[protocols]);
for (int32_t i = 0; i < count; i++)
{
jstring protocolStr = (jstring) ((*env)->GetObjectArrayElement(env, protocols, i));
const char* protocolStrPtr = (*env)->GetStringUTFChars(env, protocolStr, NULL);
if ((!strcmp(protocolStrPtr, "TLSv1") && protocol == PAL_SSL_TLS) ||
(!strcmp(protocolStrPtr, "TLSv1.1") && protocol == PAL_SSL_TLS11) ||
(!strcmp(protocolStrPtr, "TLSv1.2") && protocol == PAL_SSL_TLS12) ||
(!strcmp(protocolStrPtr, "TLSv1.3") && protocol == PAL_SSL_TLS13))
jstring protocol = (*env)->GetObjectArrayElement(env, loc[protocols], i);
const char* protocolStr = (*env)->GetStringUTFChars(env, protocol, NULL);
if (strncmp(protocolStr, tlsv1, tlsv1Len) == 0)
{
supported = 1;
(*env)->ReleaseStringUTFChars(env, protocolStr, protocolStrPtr);
(*env)->DeleteLocalRef(env, protocolStr);
break;
if (strlen(protocolStr) == tlsv1Len)
{
supported |= PAL_SslProtocol_Tls10;
}
else if (strcmp(protocolStr + tlsv1Len, ".1") == 0)
{
supported |= PAL_SslProtocol_Tls11;
}
else if (strcmp(protocolStr + tlsv1Len, ".2") == 0)
{
supported |= PAL_SslProtocol_Tls12;
}
else if (strcmp(protocolStr + tlsv1Len, ".3") == 0)
{
supported |= PAL_SslProtocol_Tls13;
}
}
(*env)->ReleaseStringUTFChars(env, protocolStr, protocolStrPtr);
(*env)->DeleteLocalRef(env, protocolStr);

(*env)->ReleaseStringUTFChars(env, protocol, protocolStr);
(*env)->DeleteLocalRef(env, protocol);
}
(*env)->DeleteLocalRef(env, sslCtxObj);
(*env)->DeleteLocalRef(env, sslParametersObj);
(*env)->DeleteLocalRef(env, protocols);

RELEASE_LOCALS(loc, env);
return supported;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,9 @@
#pragma once

#include "pal_jni.h"
#include <pal_ssl_types.h>

typedef enum
{
PAL_SSL_NONE = 0,
PAL_SSL_SSL2 = 12,
PAL_SSL_SSL3 = 48,
PAL_SSL_TLS = 192,
PAL_SSL_TLS11 = 768,
PAL_SSL_TLS12 = 3072,
PAL_SSL_TLS13 = 12288,
} SslProtocols;

PALEXPORT int32_t CryptoNative_OpenSslGetProtocolSupport(SslProtocols protocol);
/*
Get the supported protocols
*/
PALEXPORT PAL_SslProtocol AndroidCryptoNative_SSLGetSupportedProtocols(void);
Loading