Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3102766
CipherSuitePolicy implementation (Linux)
krwq Apr 5, 2019
4323618
SSL_CIPHER_find
krwq Apr 7, 2019
5e3b703
do not call TLS1.3 APIs on platforms which don't support it
krwq Apr 7, 2019
3031634
Non-TLS1.3 specific tests are skipped when not enough cipher suites i…
krwq Apr 8, 2019
af30465
clean ups
krwq Apr 8, 2019
ef3519d
attempt to fix OSX
krwq Apr 8, 2019
1a6f1f7
another attempt to fix OSX
krwq Apr 8, 2019
80fc8a1
missing define
krwq Apr 8, 2019
9978be7
address some feedback, try to fix test failures
krwq Apr 8, 2019
d402d7b
portable build fix
krwq Apr 8, 2019
6e78270
do not call old set ciphers API when only TLS 1.3 is requested
krwq Apr 9, 2019
fab7fd1
apply feedback
krwq Apr 10, 2019
8c5e2d5
add OSX implementation
krwq Apr 10, 2019
8a2a49e
fixes to OSX
krwq Apr 10, 2019
ea000aa
explicit convert
krwq Apr 10, 2019
60e1235
use explicit SSLCipherSuite instead of uint16_t
krwq Apr 10, 2019
d106a33
random change to trigger CI
krwq Apr 10, 2019
0975c53
s/unsafe/fixed
krwq Apr 10, 2019
b1c3382
fixes
krwq Apr 10, 2019
7bc25fb
random change to trigger CI
krwq Apr 10, 2019
550ad52
client ordering does not have to win
krwq Apr 10, 2019
2ad5374
tests: AllowedCipherSuites, new CipherSuitesPolicy(null)
krwq Apr 11, 2019
b6fce4f
run AllowedCipherSuites tests only when CSP is supported
krwq Apr 11, 2019
6fdb6b4
add summary on CipherSuitesPolicy
krwq Apr 11, 2019
3a62889
address feedback
krwq Apr 11, 2019
bb57ff8
move OS specific files to CipherSuitesPolicyPal
krwq Apr 11, 2019
314d2c9
FALLBACK->LIGHTUP and remove local_
krwq Apr 12, 2019
0382355
do not call 1.1.1 function on non-portable build when lower openssl v…
krwq Apr 12, 2019
9b7c610
get rid of warning that arg is unused
krwq Apr 12, 2019
85c1dd0
make CipherSuitesPolicyPal public members internal
krwq Apr 12, 2019
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
Expand Up @@ -146,6 +146,9 @@ private static extern int AppleCryptoNative_SslIsHostnameMatch(
[DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetProtocolVersion")]
internal static extern int SslGetProtocolVersion(SafeSslHandle sslHandle, out SslProtocols protocol);

[DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetEnabledCipherSuites")]
unsafe internal static extern int SslSetEnabledCipherSuites(SafeSslHandle sslHandle, uint* cipherSuites, int numCipherSuites);

internal static void SslSetAcceptClientCert(SafeSslHandle sslHandle)
{
int osStatus = AppleCryptoNative_SslSetAcceptClientCert(sslHandle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,55 @@ internal static SafeSslHandle AllocateSslContext(SslProtocols protocols, SafeX50
throw CreateSslException(SR.net_allocate_ssl_context_failed);
}

// TLS 1.3 uses different ciphersuite restrictions than previous versions.
// It has no equivalent to a NoEncryption option.
if (policy == EncryptionPolicy.NoEncryption)
if (!Interop.Ssl.Tls13Supported)
{
if (protocols != SslProtocols.None &&
CipherSuitesPolicyPal.WantsTls13(protocols))
{
protocols = protocols & (~SslProtocols.Tls13);
}
}
else if (CipherSuitesPolicyPal.WantsTls13(protocols) &&
CipherSuitesPolicyPal.ShouldOptOutOfTls13(sslAuthenticationOptions.CipherSuitesPolicy, policy))
{
if (protocols == SslProtocols.None)
{
// we are using default settings but cipher suites policy says that TLS 1.3
// is not compatible with our settings (i.e. we requested no encryption or disabled
// all TLS 1.3 cipher suites)
protocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
}
else
{
protocols &= ~SslProtocols.Tls13;

if (protocols == SslProtocols.None)
{
throw new SslException(
SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy));
}
// user explicitly asks for TLS 1.3 but their policy is not compatible with TLS 1.3
throw new SslException(
SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy));
}
}

if (CipherSuitesPolicyPal.ShouldOptOutOfLowerThanTls13(sslAuthenticationOptions.CipherSuitesPolicy, policy))
{
if (!CipherSuitesPolicyPal.WantsTls13(protocols))
{
// We cannot provide neither TLS 1.3 or non TLS 1.3, user disabled all cipher suites
throw new SslException(
SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy));
}

protocols = SslProtocols.Tls13;
}

// Configure allowed protocols. It's ok to use DangerousGetHandle here without AddRef/Release as we just
// create the handle, it's rooted by the using, no one else has a reference to it, etc.
Ssl.SetProtocolOptions(innerContext.DangerousGetHandle(), protocols);

// Sets policy and security level
if (!Ssl.SetEncryptionPolicy(innerContext, policy))
{
throw new SslException(
SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy));
}

// The logic in SafeSslHandle.Disconnect is simple because we are doing a quiet
// shutdown (we aren't negotiating for session close to enable later session
// restoration).
Expand All @@ -98,10 +122,23 @@ internal static SafeSslHandle AllocateSslContext(SslProtocols protocols, SafeX50
// https://www.openssl.org/docs/manmaster/ssl/SSL_shutdown.html
Ssl.SslCtxSetQuietShutdown(innerContext);

if (!Ssl.SetEncryptionPolicy(innerContext, policy))
byte[] cipherList =
Copy link
Member

Choose a reason for hiding this comment

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

Should Debug.Assert that these are null terminated.

Copy link
Member Author

Choose a reason for hiding this comment

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

I already do the checks inside ShouldOptOutOfTls13 and ShouldOptOutOfLowerThanTls13 but can add another one

CipherSuitesPolicyPal.GetOpenSslCipherList(sslAuthenticationOptions.CipherSuitesPolicy, protocols, policy);

byte[] cipherSuites =
CipherSuitesPolicyPal.GetOpenSslCipherSuites(sslAuthenticationOptions.CipherSuitesPolicy, protocols, policy);

unsafe
{
Crypto.ErrClearError();
throw new PlatformNotSupportedException(SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy));
fixed (byte* cipherListStr = cipherList)
fixed (byte* cipherSuitesStr = cipherSuites)
{
if (!Ssl.SetCiphers(innerContext, cipherListStr, cipherSuitesStr))
{
Crypto.ErrClearError();
throw new PlatformNotSupportedException(SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy));
Copy link
Member

Choose a reason for hiding this comment

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

What would hit this case?

Copy link
Member Author

@krwq krwq Apr 11, 2019

Choose a reason for hiding this comment

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

i.e. all cipher suites provided by user are known by open ssl but disabled by default, in such case open ssl returns that none of the cipher suites can be used (i.e. NULL cipher suites).

Copy link
Member Author

Choose a reason for hiding this comment

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

perhaps error can be improved (it will be wrapped by authentication exception anyway though)

}
}
}

bool hasCertificateAndKey =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Diagnostics;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;
Expand Down Expand Up @@ -135,6 +136,21 @@ internal static extern bool GetSslConnectionInfo(
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SslGetCurrentCipherId(SafeSslHandle ssl, out int cipherId);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetOpenSslCipherSuiteName")]
private static extern IntPtr GetOpenSslCipherSuiteName(SafeSslHandle ssl, int cipherSuite, out int isTls12OrLower);

internal static string GetOpenSslCipherSuiteName(SafeSslHandle ssl, TlsCipherSuite cipherSuite, out bool isTls12OrLower)
{
string ret = Marshal.PtrToStringAnsi(GetOpenSslCipherSuiteName(ssl, (int)cipherSuite, out int isTls12OrLowerInt));
isTls12OrLower = isTls12OrLowerInt != 0;
return ret;
}

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Tls13Supported")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool Tls13SupportedImpl();
internal static readonly bool Tls13Supported = Tls13SupportedImpl();

internal static SafeSharedX509NameStackHandle SslGetClientCAList(SafeSslHandle ssl)
{
Crypto.CheckValidOpenSslHandle(ssl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ internal static partial class Ssl
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetVerify")]
internal static extern void SslCtxSetVerify(SafeSslContextHandle ctx, SslCtxSetVerifyCallback callback);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetCiphers")]
internal static unsafe extern bool SetCiphers(SafeSslContextHandle ctx, byte* cipherList, byte* cipherSuites);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetEncryptionPolicy")]
internal static extern bool SetEncryptionPolicy(SafeSslContextHandle ctx, EncryptionPolicy policy);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,12 +443,44 @@ int32_t AppleCryptoNative_SslGetProtocolVersion(SSLContextRef sslContext, PAL_Ss
return osStatus;
}

int32_t AppleCryptoNative_SslGetCipherSuite(SSLContextRef sslContext, uint32_t* pCipherSuiteOut)
int32_t AppleCryptoNative_SslGetCipherSuite(SSLContextRef sslContext, uint16_t* pCipherSuiteOut)
{
if (pCipherSuiteOut == NULL)
*pCipherSuiteOut = 0;
{
return errSecParam;
}

SSLCipherSuite cipherSuite;
OSStatus status = SSLGetNegotiatedCipher(sslContext, &cipherSuite);
*pCipherSuiteOut = (uint16_t)cipherSuite;

return status;
}

int32_t AppleCryptoNative_SslSetEnabledCipherSuites(SSLContextRef sslContext, const uint32_t* cipherSuites, int32_t numCipherSuites)
{
// Max numCipherSuites is 2^16 (all possible cipher suites)
assert(numCipherSuites < (1 << 16));

return SSLGetNegotiatedCipher(sslContext, pCipherSuiteOut);
if (sizeof(SSLCipherSuite) == sizeof(uint32_t))
{
// macOS
return SSLSetEnabledCiphers(sslContext, cipherSuites, (size_t)numCipherSuites);
}
else
{
// iOS, tvOS, watchOS
SSLCipherSuite* cipherSuites16 = (SSLCipherSuite*)malloc(sizeof(SSLCipherSuite) * (size_t)numCipherSuites);
Copy link
Member

Choose a reason for hiding this comment

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

Return value of malloc should be checked against nullptr for OOM conditions. (And honestly it's best practice to use calloc instead of malloc.)

Copy link
Member Author

@krwq krwq Apr 13, 2019

Choose a reason for hiding this comment

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

agree on OOM, for calloc comment: we fill it out anyway instruction later so not sure why use calloc - we will double initialize

Copy link
Member

Choose a reason for hiding this comment

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

This isn't a hot code path, so not concerned about double-initialization. In general the primary benefit of calloc is that you avoid possible integer overflow when computing the total required byte size. I can't imagine this particular call would overflow, but it's a good habit to get in to.

for (int i = 0; i < numCipherSuites; i++)
{
cipherSuites16[i] = (SSLCipherSuite)cipherSuites[i];
}

OSStatus status = SSLSetEnabledCiphers(sslContext, cipherSuites16, (size_t)numCipherSuites);

free(cipherSuites16);
return status;
}
}

__attribute__((constructor)) static void InitializeAppleCryptoSslShim()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,14 @@ Retrieve the TLS Cipher Suite which was negotiated for the current session.
Returns the output of SSLGetNegotiatedCipher.

Output:
pProtocol: The TLS CipherSuite value (from the RFC), e.g. ((uint32_t)0xC030) for
pProtocol: The TLS CipherSuite value (from the RFC), e.g. ((uint16_t)0xC030) for
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
*/
DLLEXPORT int32_t AppleCryptoNative_SslGetCipherSuite(SSLContextRef sslContext, uint32_t* pCipherSuiteOut);
DLLEXPORT int32_t AppleCryptoNative_SslGetCipherSuite(SSLContextRef sslContext, uint16_t* pCipherSuiteOut);

/*
Sets enabled cipher suites for the current session.

Returns the output of SSLSetEnabledCiphers.
*/
DLLEXPORT int32_t AppleCryptoNative_SslSetEnabledCipherSuites(SSLContextRef sslContext, const uint32_t* cipherSuites, int32_t numCipherSuites);
25 changes: 23 additions & 2 deletions src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,16 @@
#include <openssl/x509v3.h>

#include "pal_crypto_config.h"
#define OPENSSL_VERSION_1_1_1_RTM 0x10101000L
#define OPENSSL_VERSION_1_1_0_RTM 0x10100000L
#define OPENSSL_VERSION_1_0_2_RTM 0x10002000L

#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_1_RTM
#define HAVE_OPENSSL_SET_CIPHERSUITES 1
#else
#define HAVE_OPENSSL_SET_CIPHERSUITES 0
#endif

#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM

// Remove problematic #defines
Expand Down Expand Up @@ -77,6 +84,14 @@ int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP* group, const EC_POINT*
int EC_POINT_set_affine_coordinates_GF2m(
const EC_GROUP* group, EC_POINT* p, const BIGNUM* x, const BIGNUM* y, BN_CTX* ctx);
#endif

#if !HAVE_OPENSSL_SET_CIPHERSUITES
#undef HAVE_OPENSSL_SET_CIPHERSUITES
#define HAVE_OPENSSL_SET_CIPHERSUITES 1
int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
const SSL_CIPHER* SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
#endif

#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM
typedef struct stack_st _STACK;
int CRYPTO_add_lock(int* pointer, int amount, int type, const char* file, int line);
Expand Down Expand Up @@ -422,9 +437,11 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
REQUIRED_FUNCTION(RSA_size) \
REQUIRED_FUNCTION(RSA_up_ref) \
REQUIRED_FUNCTION(RSA_verify) \
REQUIRED_FUNCTION(SSL_CIPHER_description) \
LIGHTUP_FUNCTION(SSL_CIPHER_find) \
REQUIRED_FUNCTION(SSL_CIPHER_get_bits) \
REQUIRED_FUNCTION(SSL_CIPHER_get_id) \
LIGHTUP_FUNCTION(SSL_CIPHER_get_name) \
LIGHTUP_FUNCTION(SSL_CIPHER_get_version) \
REQUIRED_FUNCTION(SSL_ctrl) \
REQUIRED_FUNCTION(SSL_set_quiet_shutdown) \
REQUIRED_FUNCTION(SSL_CTX_check_private_key) \
Expand All @@ -436,6 +453,7 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
LIGHTUP_FUNCTION(SSL_CTX_set_alpn_select_cb) \
REQUIRED_FUNCTION(SSL_CTX_set_cert_verify_callback) \
REQUIRED_FUNCTION(SSL_CTX_set_cipher_list) \
LIGHTUP_FUNCTION(SSL_CTX_set_ciphersuites) \
REQUIRED_FUNCTION(SSL_CTX_set_client_cert_cb) \
REQUIRED_FUNCTION(SSL_CTX_set_quiet_shutdown) \
FALLBACK_FUNCTION(SSL_CTX_set_options) \
Expand Down Expand Up @@ -810,8 +828,10 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define sk_push OPENSSL_sk_push_ptr
#define sk_value OPENSSL_sk_value_ptr
#define SSL_CIPHER_get_bits SSL_CIPHER_get_bits_ptr
#define SSL_CIPHER_description SSL_CIPHER_description_ptr
#define SSL_CIPHER_find SSL_CIPHER_find_ptr
#define SSL_CIPHER_get_id SSL_CIPHER_get_id_ptr
#define SSL_CIPHER_get_name SSL_CIPHER_get_name_ptr
#define SSL_CIPHER_get_version SSL_CIPHER_get_version_ptr
#define SSL_ctrl SSL_ctrl_ptr
#define SSL_set_quiet_shutdown SSL_set_quiet_shutdown_ptr
#define SSL_CTX_check_private_key SSL_CTX_check_private_key_ptr
Expand All @@ -822,6 +842,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
#define SSL_CTX_set_alpn_select_cb SSL_CTX_set_alpn_select_cb_ptr
#define SSL_CTX_set_cert_verify_callback SSL_CTX_set_cert_verify_callback_ptr
#define SSL_CTX_set_cipher_list SSL_CTX_set_cipher_list_ptr
#define SSL_CTX_set_ciphersuites SSL_CTX_set_ciphersuites_ptr
#define SSL_CTX_set_client_cert_cb SSL_CTX_set_client_cert_cb_ptr
#define SSL_CTX_set_options SSL_CTX_set_options_ptr
#define SSL_CTX_set_quiet_shutdown SSL_CTX_set_quiet_shutdown_ptr
Expand Down
Loading