From 105ad9203d9083e54a48b0a70fe3ee8b26f842c1 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: May 07 2019 11:52:08 +0000 Subject: import dotnet-2.1.504-1.el8 --- diff --git a/.dotnet.metadata b/.dotnet.metadata new file mode 100644 index 0000000..cd04b98 --- /dev/null +++ b/.dotnet.metadata @@ -0,0 +1 @@ +be6fda6aad5a9f60d9b391b141ee415ae4de4bf1 SOURCES/dotnet-v2.1.8.tar.gz diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d46f0ea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/dotnet-v2.1.8.tar.gz diff --git a/SOURCES/0001-NetFX-compatibility-fixes-for-X500DistinguishedName.patch b/SOURCES/0001-NetFX-compatibility-fixes-for-X500DistinguishedName.patch new file mode 100644 index 0000000..08265f2 --- /dev/null +++ b/SOURCES/0001-NetFX-compatibility-fixes-for-X500DistinguishedName.patch @@ -0,0 +1,724 @@ +From 7f5ccbde792c7fd94ec27c33861ae1c3118ecf93 Mon Sep 17 00:00:00 2001 +From: Filip Navara +Date: Sun, 24 Jun 2018 06:29:39 +0200 +Subject: [PATCH 1/7] NetFX compatibility fixes for X500DistinguishedName. + +* Don't write a separator after the empty DN +* Make T61String behave like it does on Windows (UTF-8 with a Latin-1 fallback) +* Use the managed decoder on Linux, instead of a lot of P/Invokes back into OpenSSL. +--- + .../Interop.ASN1.cs | 27 ---- + .../Interop.X509Name.cs | 39 ------ + .../Interop.X509NameEntry.cs | 61 --------- + .../SafeHandles/SafeX509NameHandle.Unix.cs | 30 ----- + .../Cryptography/DerSequenceReader.cs | 35 +++++ + .../pal_x509_name.cpp | 5 + + .../pal_x509_name.h | 5 + + .../src/System.Net.Http.csproj | 3 - + .../src/System.Net.Security.csproj | 3 - + ...em.Security.Cryptography.Algorithms.csproj | 1 + + ...stem.Security.Cryptography.Encoding.csproj | 1 + + ...ystem.Security.Cryptography.OpenSsl.csproj | 1 + + .../Pal.Unix/X500NameEncoder.ManagedDecode.cs | 4 +- + .../Pal.Unix/X500NameEncoder.OpenSslDecode.cs | 123 ------------------ + .../Cryptography/Pal.Unix/X500NameEncoder.cs | 7 +- + ...urity.Cryptography.X509Certificates.csproj | 10 +- + .../tests/X500DistinguishedNameTests.cs | 69 ++++++++++ + 17 files changed, 125 insertions(+), 299 deletions(-) + delete mode 100644 src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs + delete mode 100644 src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs + delete mode 100644 src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs + +diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs +index 962eaa426f..5bd2e8b9b4 100644 +--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs ++++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs +@@ -61,22 +61,6 @@ internal static partial class Interop + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1StringFree")] + internal static extern void Asn1StringFree(IntPtr o); + +- internal static string GetOidValue(SafeSharedAsn1ObjectHandle asn1Object) +- { +- Debug.Assert(asn1Object != null); +- +- bool added = false; +- asn1Object.DangerousAddRef(ref added); +- try +- { +- return GetOidValue(asn1Object.DangerousGetHandle()); +- } +- finally +- { +- asn1Object.DangerousRelease(); +- } +- } +- + internal static unsafe string GetOidValue(IntPtr asn1ObjectPtr) + { + // OBJ_obj2txt returns the number of bytes that should have been in the answer, but it does not accept +@@ -127,14 +111,3 @@ internal static partial class Interop + } + } + } +- +-namespace Microsoft.Win32.SafeHandles +-{ +- internal class SafeSharedAsn1ObjectHandle : SafeInteriorHandle +- { +- private SafeSharedAsn1ObjectHandle() : +- base(IntPtr.Zero, ownsHandle: true) +- { +- } +- } +-} +diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs +index 0f0fecad24..70097d7db2 100644 +--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs ++++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs +@@ -15,16 +15,6 @@ internal static partial class Interop + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackFieldCount")] + internal static extern int GetX509NameStackFieldCount(SafeSharedX509NameStackHandle sk); + +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PushX509NameStackField")] +- [return: MarshalAs(UnmanagedType.Bool)] +- internal static extern bool PushX509NameStackField(SafeX509NameStackHandle stack, SafeX509NameHandle x509_Name); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RecursiveFreeX509NameStack")] +- internal static extern void RecursiveFreeX509NameStack(IntPtr stack); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_NewX509NameStack")] +- internal static extern SafeX509NameStackHandle NewX509NameStack(); +- + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackField")] + private static extern SafeSharedX509NameHandle GetX509NameStackField_private(SafeSharedX509NameStackHandle sk, + int loc); +@@ -32,15 +22,6 @@ internal static partial class Interop + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameRawBytes")] + private static extern int GetX509NameRawBytes(SafeSharedX509NameHandle x509Name, byte[] buf, int cBuf); + +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509Name")] +- internal static extern SafeX509NameHandle DecodeX509Name(byte[] buf, int len); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509NameDestroy")] +- internal static extern void X509NameDestroy(IntPtr a); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntryCount")] +- internal static extern int GetX509NameEntryCount(SafeX509NameHandle x509Name); +- + internal static X500DistinguishedName LoadX500Name(SafeSharedX509NameHandle namePtr) + { + CheckValidOpenSslHandle(namePtr); +@@ -86,25 +67,5 @@ namespace Microsoft.Win32.SafeHandles + { + } + } +- +- internal sealed class SafeX509NameStackHandle : SafeHandle +- { +- private SafeX509NameStackHandle() : +- base(IntPtr.Zero, ownsHandle: true) +- { +- } +- +- protected override bool ReleaseHandle() +- { +- Interop.Crypto.RecursiveFreeX509NameStack(handle); +- SetHandle(IntPtr.Zero); +- return true; +- } +- +- public override bool IsInvalid +- { +- get { return handle == IntPtr.Zero; } +- } +- } + } + +diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs +deleted file mode 100644 +index eeeea54d0c..0000000000 +--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs ++++ /dev/null +@@ -1,61 +0,0 @@ +-// Licensed to the .NET Foundation under one or more agreements. +-// The .NET Foundation licenses this file to you under the MIT license. +-// See the LICENSE file in the project root for more information. +- +-using System; +-using System.Runtime.InteropServices; +-using Microsoft.Win32.SafeHandles; +- +-internal static partial class Interop +-{ +- internal static partial class Crypto +- { +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntry")] +- private static extern SafeSharedX509NameEntryHandle GetX509NameEntry_private(SafeX509NameHandle x509Name, int loc); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntryOid")] +- private static extern SafeSharedAsn1ObjectHandle GetX509NameEntryOid_private(SafeSharedX509NameEntryHandle nameEntry); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntryData")] +- private static extern SafeSharedAsn1StringHandle GetX509NameEntryData_private(SafeSharedX509NameEntryHandle nameEntry); +- +- internal static SafeSharedX509NameEntryHandle GetX509NameEntry(SafeX509NameHandle x509Name, int loc) +- { +- CheckValidOpenSslHandle(x509Name); +- +- return SafeInteriorHandle.OpenInteriorHandle( +- (nameHandle, i) => GetX509NameEntry_private(nameHandle, i), +- x509Name, +- loc); +- } +- +- internal static SafeSharedAsn1ObjectHandle GetX509NameEntryOid(SafeSharedX509NameEntryHandle nameEntry) +- { +- CheckValidOpenSslHandle(nameEntry); +- +- return SafeInteriorHandle.OpenInteriorHandle( +- handle => GetX509NameEntryOid_private(handle), +- nameEntry); +- } +- +- internal static SafeSharedAsn1StringHandle GetX509NameEntryData(SafeSharedX509NameEntryHandle nameEntry) +- { +- CheckValidOpenSslHandle(nameEntry); +- +- return SafeInteriorHandle.OpenInteriorHandle( +- handle => GetX509NameEntryData_private(handle), +- nameEntry); +- } +- } +-} +- +-namespace Microsoft.Win32.SafeHandles +-{ +- internal sealed class SafeSharedX509NameEntryHandle : SafeInteriorHandle +- { +- private SafeSharedX509NameEntryHandle() : +- base(IntPtr.Zero, ownsHandle: true) +- { +- } +- } +-} +diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs +deleted file mode 100644 +index ae22b92303..0000000000 +--- a/src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs ++++ /dev/null +@@ -1,30 +0,0 @@ +-// Licensed to the .NET Foundation under one or more agreements. +-// The .NET Foundation licenses this file to you under the MIT license. +-// See the LICENSE file in the project root for more information. +- +-using System; +-using System.Security; +-using System.Runtime.InteropServices; +- +-namespace Microsoft.Win32.SafeHandles +-{ +- internal sealed class SafeX509NameHandle : SafeHandle +- { +- private SafeX509NameHandle() : +- base(IntPtr.Zero, ownsHandle: true) +- { +- } +- +- protected override bool ReleaseHandle() +- { +- Interop.Crypto.X509NameDestroy(handle); +- SetHandle(IntPtr.Zero); +- return true; +- } +- +- public override bool IsInvalid +- { +- get { return handle == IntPtr.Zero; } +- } +- } +-} +diff --git a/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs b/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs +index b68c9da093..68d9ac1bd2 100644 +--- a/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs ++++ b/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs +@@ -30,6 +30,9 @@ namespace System.Security.Cryptography + + internal static DateTimeFormatInfo s_validityDateTimeFormatInfo; + ++ private static System.Text.Encoding s_utf8EncodingWithExceptionFallback; ++ private static System.Text.Encoding s_latin1Encoding; ++ + private readonly byte[] _data; + private readonly int _end; + private int _position; +@@ -383,6 +386,38 @@ namespace System.Security.Cryptography + return TrimTrailingNulls(ia5String); + } + ++ internal string ReadT61String() ++ { ++ EatTag(DerTag.T61String); ++ int contentLength = EatLength(); ++ string t61String; ++ ++ // Technically the T.61 encoding (code page 20261) should be used here, but many ++ // implementations don't follow that and use different character sets. CryptoAPI ++ // on NetFX seems to interpret it as UTF-8 with fallback to ISO 8859-1. OpenSSL ++ // seems to interpret it as ISO 8859-1 with no support for UTF-8. ++ // https://github.com/dotnet/corefx/issues/27466 ++ ++ System.Text.Encoding utf8EncodingWithExceptionFallback = LazyInitializer.EnsureInitialized( ++ ref s_utf8EncodingWithExceptionFallback, ++ () => new UTF8Encoding(false, true)); ++ System.Text.Encoding latin1Encoding = LazyInitializer.EnsureInitialized( ++ ref s_latin1Encoding, ++ () => System.Text.Encoding.GetEncoding("iso-8859-1")); ++ ++ try ++ { ++ t61String = utf8EncodingWithExceptionFallback.GetString(_data, _position, contentLength); ++ } ++ catch (DecoderFallbackException) ++ { ++ t61String = latin1Encoding.GetString(_data, _position, contentLength); ++ } ++ _position += contentLength; ++ ++ return TrimTrailingNulls(t61String); ++ } ++ + internal DateTime ReadX509Date() + { + byte tag = PeekTag(); +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.cpp +index 2195b74906..02cbfee4a2 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.cpp +@@ -14,6 +14,11 @@ extern "C" X509_NAME* CryptoNative_GetX509NameStackField(X509NameStack* sk, int3 + return sk_X509_NAME_value(sk, loc); + } + ++/* ++ * The following methods are kept around for compatiblity during servicing. ++ * They are not used. ++ */ ++ + extern "C" X509_NAME* CryptoNative_DecodeX509Name(const uint8_t* buf, int32_t len) + { + if (!buf || !len) +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h +index 76a77ccc1f..b24a794bbd 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h +@@ -18,6 +18,11 @@ Direct shim to sk_X509_NAME_value + */ + extern "C" X509_NAME* CryptoNative_GetX509NameStackField(X509NameStack* sk, int32_t loc); + ++/* ++ * The following methods are kept around for compatiblity during servicing. ++ * They are not used. ++ */ ++ + /* + Shims the d2i_X509_NAME method and makes it easier to invoke from managed code. + */ +diff --git a/src/System.Net.Http/src/System.Net.Http.csproj b/src/System.Net.Http/src/System.Net.Http.csproj +index 3fa7cdd26f..66e5b8d5f8 100644 +--- a/src/System.Net.Http/src/System.Net.Http.csproj ++++ b/src/System.Net.Http/src/System.Net.Http.csproj +@@ -530,9 +530,6 @@ + + Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs + +- +- Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs +- + + Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs + +diff --git a/src/System.Net.Security/src/System.Net.Security.csproj b/src/System.Net.Security/src/System.Net.Security.csproj +index 9dff20160e..bf8d773a4e 100644 +--- a/src/System.Net.Security/src/System.Net.Security.csproj ++++ b/src/System.Net.Security/src/System.Net.Security.csproj +@@ -328,9 +328,6 @@ + + Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs + +- +- Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs +- + + Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs + +diff --git a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +index 9b1cb26508..fbe6f4c269 100644 +--- a/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj ++++ b/src/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj +@@ -558,6 +558,7 @@ + + + ++ + + + +diff --git a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj +index 9681ef62e4..388d4f36a6 100644 +--- a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj ++++ b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj +@@ -106,6 +106,7 @@ + + + ++ + + + +diff --git a/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj b/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj +index 095d62bc6d..3846bcad23 100644 +--- a/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj ++++ b/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj +@@ -160,6 +160,7 @@ + + + ++ + + + +diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs +index 094e95c20d..0285415ba3 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs ++++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs +@@ -127,7 +127,7 @@ namespace Internal.Cryptography.Pal + } + } + +- if (addTrailingDelimiter) ++ if (addTrailingDelimiter && decodedName.Length > 0) + { + decodedName.Append(dnSeparator); + } +@@ -150,7 +150,7 @@ namespace Internal.Cryptography.Pal + case DerSequenceReader.DerTag.UTF8String: + return tavReader.ReadUtf8String(); + case DerSequenceReader.DerTag.T61String: +- return ""; ++ return tavReader.ReadT61String(); + default: + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } +diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs +deleted file mode 100644 +index 0c03283475..0000000000 +--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs ++++ /dev/null +@@ -1,123 +0,0 @@ +-// Licensed to the .NET Foundation under one or more agreements. +-// The .NET Foundation licenses this file to you under the MIT license. +-// See the LICENSE file in the project root for more information. +- +-using System.Text; +- +-using Microsoft.Win32.SafeHandles; +- +-namespace Internal.Cryptography.Pal +-{ +- internal static partial class X500NameEncoder +- { +- private static string X500DistinguishedNameDecode( +- byte[] encodedName, +- bool printOid, +- bool reverse, +- bool quoteIfNeeded, +- string dnSeparator, +- string multiValueSeparator, +- bool addTrailingDelimiter) +- { +- using (SafeX509NameHandle x509Name = Interop.Crypto.DecodeX509Name(encodedName, encodedName.Length)) +- { +- if (x509Name.IsInvalid) +- { +- Interop.Crypto.ErrClearError(); +- return ""; +- } +- +- // We need to allocate a StringBuilder to hold the data as we're building it, and there's the usual +- // arbitrary process of choosing a number that's "big enough" to minimize reallocations without wasting +- // too much space in the average case. +- // +- // So, let's look at an example of what our output might be. +- // +- // GitHub.com's SSL cert has a "pretty long" subject (partially due to the unknown OIDs): +- // businessCategory=Private Organization +- // 1.3.6.1.4.1.311.60.2.1.3=US +- // 1.3.6.1.4.1.311.60.2.1.2=Delaware +- // serialNumber=5157550 +- // street=548 4th Street +- // postalCode=94107 +- // C=US +- // ST=California +- // L=San Francisco +- // O=GitHub, Inc. +- // CN=github.com +- // +- // Which comes out to 228 characters using OpenSSL's default pretty-print +- // (openssl x509 -in github.cer -text -noout) +- // Throw in some "maybe-I-need-to-quote-this" quotes, and a couple of extra/extra-long O/OU values +- // and round that up to the next programmer number, and you get that 512 should avoid reallocations +- // in all but the most dire of cases. +- StringBuilder decodedName = new StringBuilder(512); +- int entryCount = Interop.Crypto.GetX509NameEntryCount(x509Name); +- bool printSpacing = false; +- +- for (int i = 0; i < entryCount; i++) +- { +- int loc = reverse ? entryCount - i - 1 : i; +- +- using (SafeSharedX509NameEntryHandle nameEntry = Interop.Crypto.GetX509NameEntry(x509Name, loc)) +- { +- Interop.Crypto.CheckValidOpenSslHandle(nameEntry); +- +- string thisOidValue; +- +- using (SafeSharedAsn1ObjectHandle oidHandle = Interop.Crypto.GetX509NameEntryOid(nameEntry)) +- { +- thisOidValue = Interop.Crypto.GetOidValue(oidHandle); +- } +- +- if (printSpacing) +- { +- decodedName.Append(dnSeparator); +- } +- else +- { +- printSpacing = true; +- } +- +- if (printOid) +- { +- AppendOid(decodedName, thisOidValue); +- } +- +- string rdnValue; +- +- using (SafeSharedAsn1StringHandle valueHandle = Interop.Crypto.GetX509NameEntryData(nameEntry)) +- { +- rdnValue = Interop.Crypto.Asn1StringToManagedString(valueHandle); +- } +- +- bool quote = quoteIfNeeded && NeedsQuoting(rdnValue); +- +- if (quote) +- { +- decodedName.Append('"'); +- +- // If the RDN itself had a quote within it, that quote needs to be escaped +- // with another quote. +- rdnValue = rdnValue.Replace("\"", "\"\""); +- } +- +- decodedName.Append(rdnValue); +- +- if (quote) +- { +- decodedName.Append('"'); +- } +- } +- } +- +- if (addTrailingDelimiter) +- { +- decodedName.Append(dnSeparator); +- } +- +- return decodedName.ToString(); +- } +- } +- } +-} +diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs +index 56da9ae40c..005e09abe3 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs ++++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs +@@ -40,7 +40,7 @@ namespace Internal.Cryptography.Pal + byte[] encodedName, + bool printOid, + X500DistinguishedNameFlags flags, +- bool addTrailingDelimieter=false) ++ bool addTrailingDelimiter = false) + { + bool reverse = (flags & X500DistinguishedNameFlags.Reversed) == X500DistinguishedNameFlags.Reversed; + bool quoteIfNeeded = (flags & X500DistinguishedNameFlags.DoNotUseQuotes) != X500DistinguishedNameFlags.DoNotUseQuotes; +@@ -51,7 +51,8 @@ namespace Internal.Cryptography.Pal + { + dnSeparator = "; "; + } +- else if ((flags & X500DistinguishedNameFlags.UseNewLines) == X500DistinguishedNameFlags.UseNewLines) ++ // Explicit UseCommas has preference over explicit UseNewLines. ++ else if ((flags & (X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.UseCommas)) == X500DistinguishedNameFlags.UseNewLines) + { + dnSeparator = Environment.NewLine; + } +@@ -73,7 +74,7 @@ namespace Internal.Cryptography.Pal + quoteIfNeeded, + dnSeparator, + multiValueSparator, +- addTrailingDelimieter); ++ addTrailingDelimiter); + } + catch (CryptographicException) + { +diff --git a/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +index 20b0328943..3bdef009b9 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj ++++ b/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +@@ -169,7 +169,6 @@ + + + +- + + + +@@ -223,9 +222,6 @@ + + Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Name.cs + +- +- Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509NameEntry.cs +- + + Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Stack.cs + +@@ -274,9 +270,6 @@ + + Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs + +- +- Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs +- + + Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs + +@@ -390,7 +383,6 @@ + + + +- + + + +@@ -398,6 +390,7 @@ + + + ++ + + + +@@ -417,6 +410,7 @@ + + + ++ + + + +diff --git a/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs +index 027823ffbd..95ac1ed519 100644 +--- a/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs ++++ b/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs +@@ -126,6 +126,16 @@ namespace System.Security.Cryptography.X509Certificates.Tests + + Assert.Equal(notQuoted, dn.Decode(X500DistinguishedNameFlags.DoNotUseQuotes)); + } ++ ++ [Theory] ++ [MemberData(nameof(T61Cases))] ++ public static void T61Strings(string expected, string hexEncoded) ++ { ++ byte[] encoded = hexEncoded.HexToByteArray(); ++ X500DistinguishedName dn = new X500DistinguishedName(encoded); ++ ++ Assert.Equal(expected, dn.Name); ++ } + + [Fact] + public static void PrintComplexReversed() +@@ -158,6 +168,22 @@ namespace System.Security.Cryptography.X509Certificates.Tests + Assert.EndsWith(expected, dn.Decode(X500DistinguishedNameFlags.None), StringComparison.Ordinal); + } + ++ [Fact] ++ public static void EdgeCaseEmptyFormat() ++ { ++ X500DistinguishedName dn = new X500DistinguishedName(""); ++ Assert.Equal(String.Empty, dn.Format(true)); ++ Assert.Equal(String.Empty, dn.Format(false)); ++ } ++ ++ [Fact] ++ public static void EdgeCaseUseCommaAndNewLines() ++ { ++ const string rname = "C=US, O=\"RSA Data Security, Inc.\", OU=Secure Server Certification Authority"; ++ X500DistinguishedName dn = new X500DistinguishedName(rname, X500DistinguishedNameFlags.None); ++ Assert.Equal(rname, dn.Decode(X500DistinguishedNameFlags.UseCommas | X500DistinguishedNameFlags.UseNewLines)); ++ } ++ + public static readonly object[][] WhitespaceBeforeCases = + { + // Regular space. +@@ -386,6 +412,49 @@ namespace System.Security.Cryptography.X509Certificates.Tests + }, + }; + ++ public static readonly object[][] T61Cases = ++ { ++ // https://github.com/dotnet/corefx/issues/27466 ++ new object[] ++ { ++ "CN=GrapeCity inc., OU=Tools Development, O=GrapeCity inc., " + ++ "L=Sendai Izumi-ku, S=Miyagi, C=JP", ++ "308186310b3009060355040613024a50310f300d060355040813064d69796167" + ++ "69311830160603550407130f53656e64616920497a756d692d6b753117301506" + ++ "0355040a140e47726170654369747920696e632e311a3018060355040b141154" + ++ "6f6f6c7320446576656c6f706d656e74311730150603550403140e4772617065" + ++ "4369747920696e632e" ++ }, ++ ++ // Mono test case taken from old bug report ++ new object[] ++ { ++ "SERIALNUMBER=CVR:13471967-UID:121212121212, E=vhm@use.test.dk, " + ++ "CN=Hedeby's M\u00f8belhandel - Salgsafdelingen, " + ++ "O=Hedeby's M\u00f8belhandel // CVR:13471967, C=DK", ++ "3081B5310B300906035504061302444B312D302B060355040A14244865646562" + ++ "792773204DF862656C68616E64656C202F2F204356523A313334373139363731" + ++ "2F302D060355040314264865646562792773204DF862656C68616E64656C202D" + ++ "2053616C6773616664656C696E67656E311E301C06092A864886F70D01090116" + ++ "0F76686D407573652E746573742E646B312630240603550405131D4356523A31" + ++ "333437313936372D5549443A313231323132313231323132" ++ }, ++ ++ // Valid UTF-8 string is interpreted as UTF-8 ++ new object[] ++ { ++ "C=\u00a2", ++ "300D310B300906035504061402C2A2" ++ }, ++ ++ // Invalid UTF-8 string with valid UTF-8 sequence is interpreted as ISO 8859-1 ++ new object[] ++ { ++ "L=\u00c2\u00a2\u00f8", ++ "300E310C300A06035504071403C2A2F8" ++ }, ++ }; ++ + private const string MicrosoftDotComSubject = + "3082010F31133011060B2B0601040182373C02010313025553311B3019060B2B" + + "0601040182373C0201020C0A57617368696E67746F6E311D301B060355040F13" + +-- +2.20.1 + diff --git a/SOURCES/0002-Drop-pal_asn1_print-in-favor-of-the-managed-code.patch b/SOURCES/0002-Drop-pal_asn1_print-in-favor-of-the-managed-code.patch new file mode 100644 index 0000000..fe61638 --- /dev/null +++ b/SOURCES/0002-Drop-pal_asn1_print-in-favor-of-the-managed-code.patch @@ -0,0 +1,355 @@ +From 3fd578c3ccea681efd14aea07a0364b3baa3cca7 Mon Sep 17 00:00:00 2001 +From: Filip Navara +Date: Mon, 9 Jul 2018 19:08:50 +0200 +Subject: [PATCH 2/7] Drop pal_asn1_print in favor of the managed code + +* Drop pal_asn1_print in favor of the managed code that is already used on macOS. + +* Add handling of T61 strings to ManagedCertificateFinder.DerStringToManagedString. +--- + .../Interop.ASN1.Print.cs | 144 ------------------ + .../Win32/SafeHandles/Asn1SafeHandles.Unix.cs | 28 ---- + .../pal_asn1_print.cpp | 5 + + .../pal_asn1_print.h | 5 + + .../Internal/Cryptography/Pal.OSX/FindPal.cs | 28 ---- + .../Pal.Unix/ManagedCertificateFinder.cs | 31 +++- + .../Pal.Unix/OpenSslCertificateFinder.cs | 5 - + ...urity.Cryptography.X509Certificates.csproj | 3 - + 8 files changed, 40 insertions(+), 209 deletions(-) + delete mode 100644 src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Print.cs + +diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Print.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Print.cs +deleted file mode 100644 +index 12199563c8..0000000000 +--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Print.cs ++++ /dev/null +@@ -1,144 +0,0 @@ +-// Licensed to the .NET Foundation under one or more agreements. +-// The .NET Foundation licenses this file to you under the MIT license. +-// See the LICENSE file in the project root for more information. +- +-using System; +-using System.Runtime.InteropServices; +-using System.Text; +-using Microsoft.Win32.SafeHandles; +- +-internal static partial class Interop +-{ +- internal static partial class Crypto +- { +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeAsn1TypeBytes")] +- private static extern SafeAsn1StringHandle DecodeAsn1TypeBytes(byte[] buf, int len, Asn1StringTypeFlags flags); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1StringPrintEx")] +- private static extern int Asn1StringPrintEx(SafeBioHandle bio, SafeAsn1StringHandle str, Asn1StringPrintFlags flags); +- +- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1StringPrintEx")] +- private static extern int Asn1StringPrintEx(SafeBioHandle bio, SafeSharedAsn1StringHandle str, Asn1StringPrintFlags flags); +- +- internal static string DerStringToManagedString(byte[] derString) +- { +- SafeAsn1StringHandle asn1String = DecodeAsn1TypeBytes(derString, derString.Length, AnyTextStringType); +- +- if (asn1String.IsInvalid) +- { +- Interop.Crypto.ErrClearError(); +- return null; +- } +- +- using (asn1String) +- { +- return Asn1StringToManagedString( +- asn1String, +- (bio, str, flags) => Asn1StringPrintEx(bio, str, flags)); +- } +- } +- +- internal static string Asn1StringToManagedString(SafeSharedAsn1StringHandle asn1String) +- { +- CheckValidOpenSslHandle(asn1String); +- +- return Asn1StringToManagedString( +- asn1String, +- (bio, str, flags) => Asn1StringPrintEx(bio, str, flags)); +- } +- +- private static string Asn1StringToManagedString( +- THandle asn1String, +- Func asn1StringPrintEx) +- { +- byte[] utf8Bytes; +- +- using (SafeBioHandle bio = CreateMemoryBio()) +- { +- CheckValidOpenSslHandle(bio); +- +- int len = asn1StringPrintEx(bio, asn1String, Asn1StringPrintFlags.ASN1_STRFLGS_UTF8_CONVERT); +- +- if (len < 0) +- { +- throw CreateOpenSslCryptographicException(); +- } +- +- if (len == 0) +- { +- return ""; +- } +- +- int bioSize = GetMemoryBioSize(bio); +- utf8Bytes = new byte[bioSize + 1]; +- +- int read = BioRead(bio, utf8Bytes, utf8Bytes.Length); +- +- if (read < 0) +- { +- throw CreateOpenSslCryptographicException(); +- } +- } +- +- int nonNullCount = utf8Bytes.Length; +- +- if (utf8Bytes[utf8Bytes.Length - 1] == 0) +- { +- for (int i = utf8Bytes.Length - 1; i >= 0; i--) +- { +- if (utf8Bytes[i] != 0) +- { +- break; +- } +- +- nonNullCount = i; +- } +- } +- +- return Encoding.UTF8.GetString(utf8Bytes, 0, nonNullCount); +- } +- +- [Flags] +- private enum Asn1StringPrintFlags : ulong +- { +- ASN1_STRFLGS_UTF8_CONVERT = 0x10, +- } +- +- [Flags] +- private enum Asn1StringTypeFlags +- { +- B_ASN1_NUMERICSTRING = 0x0001, +- B_ASN1_PRINTABLESTRING = 0x0002, +- B_ASN1_T61STRING = 0x0004, +- B_ASN1_VIDEOTEXSTRING = 0x0008, +- B_ASN1_IA5STRING = 0x0010, +- B_ASN1_GRAPHICSTRING = 0x0020, +- B_ASN1_VISIBLESTRING = 0x0040, +- B_ASN1_GENERALSTRING = 0x0080, +- B_ASN1_UNIVERSALSTRING = 0x0100, +- B_ASN1_OCTET_STRING = 0x0200, +- B_ASN1_BIT_STRING = 0x0400, +- B_ASN1_BMPSTRING = 0x0800, +- B_ASN1_UNKNOWN = 0x1000, +- B_ASN1_UTF8STRING = 0x2000, +- B_ASN1_UTCTIME = 0x4000, +- B_ASN1_GENERALIZEDTIME = 0x8000, +- B_ASN1_SEQUENCE = 0x10000, +- } +- +- private const Asn1StringTypeFlags AnyTextStringType = +- Asn1StringTypeFlags.B_ASN1_NUMERICSTRING | +- Asn1StringTypeFlags.B_ASN1_PRINTABLESTRING | +- Asn1StringTypeFlags.B_ASN1_T61STRING | +- Asn1StringTypeFlags.B_ASN1_VIDEOTEXSTRING | +- Asn1StringTypeFlags.B_ASN1_IA5STRING | +- Asn1StringTypeFlags.B_ASN1_GRAPHICSTRING | +- Asn1StringTypeFlags.B_ASN1_VISIBLESTRING | +- Asn1StringTypeFlags.B_ASN1_GENERALSTRING | +- Asn1StringTypeFlags.B_ASN1_UNIVERSALSTRING | +- Asn1StringTypeFlags.B_ASN1_BMPSTRING | +- Asn1StringTypeFlags.B_ASN1_UTF8STRING | +- Asn1StringTypeFlags.B_ASN1_UTCTIME | +- Asn1StringTypeFlags.B_ASN1_GENERALIZEDTIME; +- } +-} +diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/Asn1SafeHandles.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/Asn1SafeHandles.Unix.cs +index 3fdde3f602..ddf413110c 100644 +--- a/src/Common/src/Microsoft/Win32/SafeHandles/Asn1SafeHandles.Unix.cs ++++ b/src/Common/src/Microsoft/Win32/SafeHandles/Asn1SafeHandles.Unix.cs +@@ -68,34 +68,6 @@ namespace Microsoft.Win32.SafeHandles + } + } + +- internal sealed class SafeAsn1StringHandle : SafeHandle +- { +- private SafeAsn1StringHandle() : +- base(IntPtr.Zero, ownsHandle: true) +- { +- } +- +- protected override bool ReleaseHandle() +- { +- Interop.Crypto.Asn1StringFree(handle); +- SetHandle(IntPtr.Zero); +- return true; +- } +- +- public override bool IsInvalid +- { +- get { return handle == IntPtr.Zero; } +- } +- } +- +- internal sealed class SafeSharedAsn1StringHandle : SafeInteriorHandle +- { +- private SafeSharedAsn1StringHandle() : +- base(IntPtr.Zero, ownsHandle: true) +- { +- } +- } +- + internal sealed class SafeSharedAsn1IntegerHandle : SafeInteriorHandle + { + private SafeSharedAsn1IntegerHandle() : +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp +index ffbfef980d..01a544f5e9 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp +@@ -4,6 +4,11 @@ + + #include "pal_asn1_print.h" + ++/* ++ * This file is completely unused. It's kept around for compatiblity between ++ * servicing updates. ++ */ ++ + static_assert(PAL_B_ASN1_NUMERICSTRING == B_ASN1_NUMERICSTRING, ""); + static_assert(PAL_B_ASN1_PRINTABLESTRING == B_ASN1_PRINTABLESTRING, ""); + static_assert(PAL_B_ASN1_T61STRING == B_ASN1_T61STRING, ""); +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h +index 982506e420..71205cc13c 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.h +@@ -5,6 +5,11 @@ + #include "pal_types.h" + #include "opensslshim.h" + ++/* ++ * This file is completely unused. It's kept around for compatiblity between ++ * servicing updates. ++ */ ++ + /* + Flags for the 'type' parameter of CryptoNative_DecodeAsn1TypeBytes. + */ +diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs +index b2d2846c1a..e66bad7e76 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs ++++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.OSX/FindPal.cs +@@ -22,34 +22,6 @@ namespace Internal.Cryptography.Pal + { + } + +- protected override string DerStringToManagedString(byte[] anyString) +- { +- DerSequenceReader reader = DerSequenceReader.CreateForPayload(anyString); +- +- var tag = (DerSequenceReader.DerTag)reader.PeekTag(); +- string value = null; +- +- switch (tag) +- { +- case DerSequenceReader.DerTag.BMPString: +- value = reader.ReadBMPString(); +- break; +- case DerSequenceReader.DerTag.IA5String: +- value = reader.ReadIA5String(); +- break; +- case DerSequenceReader.DerTag.PrintableString: +- value = reader.ReadPrintableString(); +- break; +- case DerSequenceReader.DerTag.UTF8String: +- value = reader.ReadUtf8String(); +- break; +- +- // Ignore anything we don't know how to read. +- } +- +- return value; +- } +- + protected override byte[] GetSubjectPublicKeyInfo(X509Certificate2 cert) + { + AppleCertificatePal pal = (AppleCertificatePal)cert.Pal; +diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs +index ebc5ee48d1..a70bf1488d 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs ++++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/ManagedCertificateFinder.cs +@@ -123,7 +123,36 @@ namespace Internal.Cryptography.Pal + FindCore(cert => cert.NotAfter < normalized); + } + +- protected abstract string DerStringToManagedString(byte[] anyString); ++ private string DerStringToManagedString(byte[] anyString) ++ { ++ DerSequenceReader reader = DerSequenceReader.CreateForPayload(anyString); ++ ++ var tag = (DerSequenceReader.DerTag)reader.PeekTag(); ++ string value = null; ++ ++ switch (tag) ++ { ++ case DerSequenceReader.DerTag.BMPString: ++ value = reader.ReadBMPString(); ++ break; ++ case DerSequenceReader.DerTag.IA5String: ++ value = reader.ReadIA5String(); ++ break; ++ case DerSequenceReader.DerTag.PrintableString: ++ value = reader.ReadPrintableString(); ++ break; ++ case DerSequenceReader.DerTag.UTF8String: ++ value = reader.ReadUtf8String(); ++ break; ++ case DerSequenceReader.DerTag.T61String: ++ value = reader.ReadT61String(); ++ break; ++ ++ // Ignore anything we don't know how to read. ++ } ++ ++ return value; ++ } + + public void FindByTemplateName(string templateName) + { +diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs +index 720c298994..717ee3753b 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs ++++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslCertificateFinder.cs +@@ -13,11 +13,6 @@ namespace Internal.Cryptography.Pal + { + } + +- protected override string DerStringToManagedString(byte[] anyString) +- { +- return Interop.Crypto.DerStringToManagedString(anyString); +- } +- + protected override byte[] GetSubjectPublicKeyInfo(X509Certificate2 cert) + { + OpenSslX509CertificateReader certPal = (OpenSslX509CertificateReader)cert.Pal; +diff --git a/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +index 3bdef009b9..5d9e22a7f3 100644 +--- a/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj ++++ b/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +@@ -186,9 +186,6 @@ + + Common\Interop\Unix\System.Security.Cryptography.Native\Interop.ASN1.GetIntegerBytes.cs + +- +- Common\Interop\Unix\System.Security.Cryptography.Native\Interop.ASN1.Print.cs +- + + Common\Interop\Unix\System.Security.Cryptography.Native\Interop.Bignum.cs + +-- +2.20.1 + diff --git a/SOURCES/0003-Add-hybrid-support-for-OpenSSL-1.0-and-1.1.patch b/SOURCES/0003-Add-hybrid-support-for-OpenSSL-1.0-and-1.1.patch new file mode 100644 index 0000000..fb53b0a --- /dev/null +++ b/SOURCES/0003-Add-hybrid-support-for-OpenSSL-1.0-and-1.1.patch @@ -0,0 +1,3594 @@ +From e4bcbd5885e93ea4620103efc303c9b61982851b Mon Sep 17 00:00:00 2001 +From: Jeremy Barton +Date: Tue, 4 Sep 2018 12:53:06 -0700 +Subject: [PATCH 3/7] Add hybrid support for OpenSSL 1.0 and 1.1 + +This changes the functional code to use OpenSSL 1.1 API in the places where the API changed. "apibridge" provides equivalent methods for the OpenSSL 1.0 environment. + +The following configurations have been tested: + +* Non-portable against OpenSSL 1.0 +* Non-portable against OpenSSL 1.1 +* Portable, built against OpenSSL 1.0 and run against OpenSSL 1.0 +* Portable, built against OpenSSL 1.0 and run against OpenSSL 1.1 +* Portable, built against OpenSSL 1.1 and run against OpenSSL 1.0 +* Portable, built against OpenSSL 1.1 and run against OpenSSL 1.1 + +In opensslshim, the PER_FUNCTION_BLOCK macro style has been broken up into a named purposes: + +* REQUIRED_FUNCTION(fn) + * API that we use unconditionally, regardless of version + * Formerly PER_FUNCTION_BLOCK(fn, true) +* NEW_REQUIRED_FUNCTION(fn) + * API that we use unconditionally in paths that only exist against OpenSSL 1.1, is not probed for when the runtime is 1.0 +* LIGHTUP_FUNCTION(fn) + * API that might not exist, must be probed with API_EXISTS checks before being utilized + * Formerly PER_FUNCTION_BLOCK(fn, false) +* FALLBACK_FUNCTION(fn) + * API that is required on OpenSSL 1.1, and when not found will bind to a method named local_#fn in the shim library +* RENAMED_FUNCTION(fn,oldfn) + * Handles a rename with no signature change from oldfn to newfn, binds appropriately based on the runtime library. +* LEGACY_FUNCTION(fn) + * API that we use unconditionally in paths that only exist against OpenSSL 1.0, is not probed for when the runtime is 1.1. + +Two new #defines are available, but ideally need no further usage: + +* NEED_OPENSSL_1_0 + * Defined when building portable, or on non-portable when the headers are OpenSSL 1.0 +* NEED_OPENSSL_1_1 + * Defined when building portable, or on non-portable when the headers are OpenSSL 1.1 +--- + .../SafeHandles/SafeEvpPKeyHandle.Unix.cs | 7 +- + .../CMakeLists.txt | 3 +- + .../apibridge.cpp | 524 ++++++++++ + .../apibridge.h | 45 + + .../configure.cmake | 5 - + .../openssl.cpp | 199 ++-- + .../openssl.h | 11 + + .../openssl_1_0_structs.h | 139 +++ + .../opensslshim.cpp | 60 +- + .../opensslshim.h | 928 ++++++++++++------ + .../pal_asn1.cpp | 2 +- + .../pal_asn1.h | 2 +- + .../pal_asn1_print.cpp | 9 +- + .../pal_crypto_config.h.in | 2 - + .../pal_dsa.cpp | 123 ++- + .../pal_dsa.h | 10 +- + .../pal_evp.cpp | 6 +- + .../pal_evp_cipher.cpp | 26 +- + .../pal_evp_pkey.cpp | 2 +- + .../pal_hmac.cpp | 12 +- + .../pal_hmac.h | 1 - + .../pal_rsa.cpp | 158 +-- + .../pal_rsa.h | 16 +- + .../pal_ssl.cpp | 144 ++- + .../pal_x509.cpp | 16 +- + .../pal_x509_root.cpp | 1 + + .../Internal/Cryptography/OpenSslCipher.cs | 19 + + 27 files changed, 1878 insertions(+), 592 deletions(-) + create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp + create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/apibridge.h + create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/openssl.h + create mode 100644 src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h + +diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs +index c706b1ce88..e51a7ca981 100644 +--- a/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs ++++ b/src/Common/src/Microsoft/Win32/SafeHandles/SafeEvpPKeyHandle.Unix.cs +@@ -52,12 +52,9 @@ namespace System.Security.Cryptography + // that we don't lose a tracked reference in low-memory situations. + SafeEvpPKeyHandle safeHandle = new SafeEvpPKeyHandle(); + +- int newRefCount = Interop.Crypto.UpRefEvpPkey(this); ++ int success = Interop.Crypto.UpRefEvpPkey(this); + +- // UpRefEvpPkey returns the number of references to this key, if it's less than 2 +- // (the incoming handle, and this one) then someone has already Disposed() this key +- // into non-existence. +- if (newRefCount < 2) ++ if (success != 1) + { + Debug.Fail("Called UpRefEvpPkey on a key which was already marked for destruction"); + throw Interop.Crypto.CreateOpenSslCryptographicException(); +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt b/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt +index 352f456d07..9fef63fda8 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt ++++ b/src/Native/Unix/System.Security.Cryptography.Native/CMakeLists.txt +@@ -6,7 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) + # These are happening inside of OpenSSL-defined macros out of our control + add_compile_options(-Wno-cast-align) + +-add_definitions(-DPIC=1) ++add_definitions(-DPIC=1 -DOPENSSL_API_COMPAT=0x10100000L) + + if(CMAKE_STATIC_LIB_LINK) + set(CMAKE_FIND_LIBRARY_SUFFIXES .a) +@@ -16,6 +16,7 @@ find_package(OpenSSL REQUIRED) + include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR}) + + set(NATIVECRYPTO_SOURCES ++ apibridge.cpp + openssl.cpp + pal_asn1.cpp + pal_asn1_print.cpp +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp +new file mode 100644 +index 0000000000..fd43051c3f +--- /dev/null ++++ b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.cpp +@@ -0,0 +1,524 @@ ++// Licensed to the .NET Foundation under one or more agreements. ++// The .NET Foundation licenses this file to you under the MIT license. ++// See the LICENSE file in the project root for more information. ++ ++#include "opensslshim.h" ++#include "pal_crypto_types.h" ++#include "pal_types.h" ++ ++#ifdef NEED_OPENSSL_1_0 ++ ++#include "apibridge.h" ++ ++// Minimally define the structs from 1.0.x which went opaque in 1.1.0 for the ++// portable build building against the 1.1.x headers ++#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM ++#include "openssl_1_0_structs.h" ++ ++#define CRYPTO_LOCK_X509 3 ++#define CRYPTO_LOCK_EVP_PKEY 10 ++ ++#define SSL_CTRL_GET_SESSION_REUSED 8 ++#define SSL_CTRL_OPTIONS 32 ++ ++#define SSL_ST_OK 3 ++#endif ++ ++extern "C" const ASN1_TIME* local_X509_get0_notBefore(const X509* x509) ++{ ++ if (x509 && x509->cert_info && x509->cert_info->validity) ++ { ++ return x509->cert_info->validity->notBefore; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" const ASN1_TIME* local_X509_get0_notAfter(const X509* x509) ++{ ++ if (x509 && x509->cert_info && x509->cert_info->validity) ++ { ++ return x509->cert_info->validity->notAfter; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" const ASN1_TIME* local_X509_CRL_get0_nextUpdate(const X509_CRL* crl) ++{ ++ if (crl && crl->crl) ++ { ++ return crl->crl->nextUpdate; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" int32_t local_X509_get_version(const X509* x509) ++{ ++ if (x509 && x509->cert_info) ++ { ++ long ver = ASN1_INTEGER_get(x509->cert_info->version); ++ return (int32_t)ver; ++ } ++ ++ return -1; ++} ++ ++extern "C" X509_PUBKEY* local_X509_get_X509_PUBKEY(const X509* x509) ++{ ++ if (x509) ++ { ++ return x509->cert_info->key; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" int32_t local_X509_PUBKEY_get0_param( ++ ASN1_OBJECT** palgOid, const uint8_t** pkeyBytes, int* pkeyBytesLen, X509_ALGOR** palg, X509_PUBKEY* pubkey) ++{ ++ if (palgOid) ++ { ++ *palgOid = pubkey->algor->algorithm; ++ } ++ ++ if (pkeyBytes) ++ { ++ *pkeyBytes = pubkey->public_key->data; ++ *pkeyBytesLen = pubkey->public_key->length; ++ } ++ ++ if (palg) ++ { ++ *palg = pubkey->algor; ++ } ++ ++ return 1; ++} ++ ++extern "C" const X509_ALGOR* local_X509_get0_tbs_sigalg(const X509* x509) ++{ ++ if (x509 && x509->cert_info) ++ { ++ return x509->cert_info->signature; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" ASN1_BIT_STRING* local_X509_get0_pubkey_bitstr(const X509* x509) ++{ ++ if (x509 && x509->cert_info && x509->cert_info->key) ++ { ++ return x509->cert_info->key->public_key; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" int32_t local_X509_NAME_get0_der(X509_NAME* x509Name, const uint8_t** pder, size_t* pderlen) ++{ ++ if (!x509Name || !x509Name->bytes) ++ { ++ return 0; ++ } ++ ++ if (pder) ++ { ++ *pder = (unsigned char*)x509Name->bytes->data; ++ } ++ ++ if (pderlen) ++ { ++ *pderlen = x509Name->bytes->length; ++ } ++ ++ return 1; ++} ++ ++#ifndef SSLEAY_VERSION ++#define SSLEAY_VERSION 0 ++#endif ++ ++extern "C" const char* local_OpenSSL_version(int t) ++{ ++ (void)t; ++ return SSLeay_version(SSLEAY_VERSION); ++} ++ ++extern "C" const DSA_METHOD* local_DSA_get_method(const DSA* dsa) ++{ ++ if (dsa) ++ { ++ return dsa->meth; ++ } ++ ++ return nullptr; ++} ++ ++extern "C" void local_DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g) ++{ ++ if (!dsa) ++ { ++ return; ++ } ++ ++ if (p) ++ { ++ *p = dsa->p; ++ } ++ ++ if (q) ++ { ++ *q = dsa->q; ++ } ++ ++ if (g) ++ { ++ *g = dsa->g; ++ } ++} ++ ++extern "C" const BIGNUM* local_DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey) ++{ ++ if (dsa) ++ { ++ if (pubKey) ++ { ++ *pubKey = dsa->pub_key; ++ } ++ ++ if (privKey) ++ { ++ *privKey = dsa->priv_key; ++ } ++ } ++ ++ return nullptr; ++} ++ ++extern "C" int32_t local_DSA_set0_pqg(DSA* dsa, BIGNUM* bnP, BIGNUM* bnQ, BIGNUM* bnG) ++{ ++ if (!dsa) ++ { ++ return 0; ++ } ++ ++ if ((dsa->p == nullptr && bnP == nullptr) || (dsa->q == nullptr && bnQ == nullptr) || (dsa->g == nullptr && bnG == nullptr)) ++ { ++ return 0; ++ } ++ ++ if (bnP) ++ { ++ BN_free(dsa->p); ++ dsa->p = bnP; ++ } ++ ++ if (bnQ) ++ { ++ BN_free(dsa->q); ++ dsa->q = bnQ; ++ } ++ ++ if (bnG) ++ { ++ BN_free(dsa->g); ++ dsa->g = bnG; ++ } ++ ++ return 1; ++} ++ ++extern "C" int32_t local_DSA_set0_key(DSA* dsa, BIGNUM* bnY, BIGNUM* bnX) ++{ ++ if (!dsa) ++ { ++ return 0; ++ } ++ ++ if (dsa->pub_key == nullptr && bnY == nullptr) ++ { ++ return 0; ++ } ++ ++ if (bnY) ++ { ++ BN_free(dsa->pub_key); ++ dsa->pub_key = bnY; ++ } ++ ++ if (bnX) ++ { ++ BN_free(dsa->priv_key); ++ dsa->priv_key = bnX; ++ } ++ ++ return 1; ++} ++ ++extern "C" int32_t local_EVP_PKEY_up_ref(EVP_PKEY* pkey) ++{ ++ if (!pkey) ++ { ++ return 0; ++ } ++ ++ return CRYPTO_add_lock(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY, __FILE__, __LINE__) > 1; ++} ++ ++extern "C" EVP_CIPHER_CTX* local_EVP_CIPHER_CTX_new() ++{ ++ EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)calloc(1, sizeof(EVP_CIPHER_CTX)); ++ return ctx; ++} ++ ++extern "C" int32_t local_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX* ctx) ++{ ++ if (ctx) ++ { ++ int ret = EVP_CIPHER_CTX_cleanup(ctx); ++ EVP_CIPHER_CTX_init(ctx); ++ return ret; ++ } ++ ++ // OpenSSL 1.1 returns succes 1 on a NULL input ++ return 1; ++} ++ ++extern "C" void local_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx) ++{ ++ if (ctx) ++ { ++ local_EVP_CIPHER_CTX_reset(ctx); ++ free(ctx); ++ } ++} ++ ++extern "C" HMAC_CTX* local_HMAC_CTX_new() ++{ ++ HMAC_CTX* ctx = (HMAC_CTX*)calloc(1, sizeof(HMAC_CTX)); ++ ++ if (ctx) ++ { ++ HMAC_CTX_init(ctx); ++ } ++ ++ return ctx; ++} ++ ++extern "C" void local_HMAC_CTX_free(HMAC_CTX* ctx) ++{ ++ if (ctx != nullptr) ++ { ++ HMAC_CTX_cleanup(ctx); ++ free(ctx); ++ } ++} ++ ++extern "C" int32_t local_RSA_meth_get_flags(const RSA_METHOD* meth) ++{ ++ if (meth) ++ { ++ return meth->flags; ++ } ++ ++ return 0; ++} ++ ++extern "C" void local_RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d) ++{ ++ if (rsa) ++ { ++ if (n) ++ { ++ *n = rsa->n; ++ } ++ ++ if (e) ++ { ++ *e = rsa->e; ++ } ++ ++ if (d) ++ { ++ *d = rsa->d; ++ } ++ } ++} ++ ++extern "C" void local_RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q) ++{ ++ if (rsa) ++ { ++ if (p) ++ { ++ *p = rsa->p; ++ } ++ ++ if (q) ++ { ++ *q = rsa->q; ++ } ++ } ++} ++ ++extern "C" void local_RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp) ++{ ++ if (rsa) ++ { ++ if (dmp1) ++ { ++ *dmp1 = rsa->dmp1; ++ } ++ ++ if (dmq1) ++ { ++ *dmq1 = rsa->dmq1; ++ } ++ ++ if (iqmp) ++ { ++ *iqmp = rsa->iqmp; ++ } ++ } ++} ++ ++extern "C" int32_t local_RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d) ++{ ++ if (rsa == nullptr) ++ { ++ return 0; ++ } ++ ++ if ((rsa->n == nullptr && n == nullptr) || (rsa->e == nullptr && e == nullptr)) ++ { ++ return 0; ++ } ++ ++ if (n != nullptr) ++ { ++ BN_free(rsa->n); ++ rsa->n = n; ++ } ++ ++ if (e != nullptr) ++ { ++ BN_free(rsa->e); ++ rsa->e = e; ++ } ++ ++ if (d != nullptr) ++ { ++ BN_free(rsa->d); ++ rsa->d = d; ++ } ++ ++ return 1; ++} ++ ++extern "C" int32_t local_RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q) ++{ ++ if (rsa == nullptr) ++ { ++ return 0; ++ } ++ ++ if ((rsa->p == nullptr && p == nullptr) || (rsa->q == nullptr && q == nullptr)) ++ { ++ return 0; ++ } ++ ++ if (p != nullptr) ++ { ++ BN_free(rsa->p); ++ rsa->p = p; ++ } ++ ++ if (q != nullptr) ++ { ++ BN_free(rsa->q); ++ rsa->q = q; ++ } ++ ++ return 1; ++} ++ ++extern "C" int32_t local_RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp) ++{ ++ if (rsa == nullptr) ++ { ++ return 0; ++ } ++ ++ if ((rsa->dmp1 == nullptr && dmp1 == nullptr) || (rsa->dmq1 == nullptr && dmq1 == nullptr) || ++ (rsa->iqmp == nullptr && iqmp == nullptr)) ++ { ++ return 0; ++ } ++ ++ if (dmp1 != nullptr) ++ { ++ BN_free(rsa->dmp1); ++ rsa->dmp1 = dmp1; ++ } ++ ++ if (dmq1 != nullptr) ++ { ++ BN_free(rsa->dmq1); ++ rsa->dmq1 = dmq1; ++ } ++ ++ if (iqmp != nullptr) ++ { ++ BN_free(rsa->iqmp); ++ rsa->iqmp = iqmp; ++ } ++ ++ return 1; ++} ++ ++extern "C" int32_t local_SSL_is_init_finished(const SSL* ssl) ++{ ++ return SSL_state(ssl) == SSL_ST_OK; ++} ++ ++extern "C" X509Stack* local_X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx) ++{ ++ return ctx ? ctx->untrusted : nullptr; ++} ++ ++extern "C" X509* local_X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx) ++{ ++ return ctx ? ctx->cert : nullptr; ++} ++ ++extern "C" int32_t local_X509_up_ref(X509* x509) ++{ ++ if (x509 != nullptr) ++ { ++ return CRYPTO_add_lock(&x509->references, 1, CRYPTO_LOCK_X509, __FILE__, __LINE__) > 1; ++ } ++ ++ return 0; ++} ++ ++extern "C" unsigned long local_SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options) ++{ ++ // SSL_CTX_ctrl is signed long in and signed long out; but SSL_CTX_set_options, ++ // which was a macro call to SSL_CTX_ctrl in 1.0, is unsigned/unsigned. ++ return (unsigned long)SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, (long)options, nullptr); ++} ++ ++extern "C" int local_SSL_session_reused(SSL* ssl) ++{ ++ return (int)SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, nullptr); ++} ++ ++extern "C" void local_SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level) ++{ ++ (void)ctx; ++ (void)level; ++} ++#endif +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/apibridge.h b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.h +new file mode 100644 +index 0000000000..39d2718a30 +--- /dev/null ++++ b/src/Native/Unix/System.Security.Cryptography.Native/apibridge.h +@@ -0,0 +1,45 @@ ++// Licensed to the .NET Foundation under one or more agreements. ++// The .NET Foundation licenses this file to you under the MIT license. ++// See the LICENSE file in the project root for more information. ++ ++// Functions based on OpenSSL 1.1 API, used when building against/running with OpenSSL 1.0 ++ ++#pragma once ++#include "pal_types.h" ++ ++extern "C" const BIGNUM* local_DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey); ++extern "C" void local_DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g); ++extern "C" const DSA_METHOD* local_DSA_get_method(const DSA* dsa); ++extern "C" int32_t local_DSA_set0_key(DSA* dsa, BIGNUM* bnY, BIGNUM* bnX); ++extern "C" int32_t local_DSA_set0_pqg(DSA* dsa, BIGNUM* bnP, BIGNUM* bnQ, BIGNUM* bnG); ++extern "C" void local_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx); ++extern "C" EVP_CIPHER_CTX* local_EVP_CIPHER_CTX_new(void); ++extern "C" int32_t local_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX* ctx); ++extern "C" int32_t local_EVP_PKEY_up_ref(EVP_PKEY* pkey); ++extern "C" void local_HMAC_CTX_free(HMAC_CTX* ctx); ++extern "C" HMAC_CTX* local_HMAC_CTX_new(void); ++extern "C" const char* local_OpenSSL_version(int t); ++extern "C" void local_RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp); ++extern "C" void local_RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q); ++extern "C" void local_RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d); ++extern "C" int32_t local_RSA_meth_get_flags(const RSA_METHOD* meth); ++extern "C" int32_t local_RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp); ++extern "C" int32_t local_RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q); ++extern "C" int32_t local_RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d); ++extern "C" int32_t local_SSL_is_init_finished(const SSL* ssl); ++extern "C" unsigned long local_SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options); ++extern "C" void local_SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level); ++extern "C" int local_SSL_session_reused(SSL* ssl); ++extern "C" const ASN1_TIME* local_X509_CRL_get0_nextUpdate(const X509_CRL* crl); ++extern "C" int32_t local_X509_NAME_get0_der(X509_NAME* x509Name, const uint8_t** pder, size_t* pderlen); ++extern "C" int32_t local_X509_PUBKEY_get0_param( ++ ASN1_OBJECT** palgOid, const uint8_t** pkeyBytes, int* pkeyBytesLen, X509_ALGOR** palg, X509_PUBKEY* pubkey); ++extern "C" X509* local_X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx); ++extern "C" STACK_OF(X509) * local_X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx); ++extern "C" const ASN1_TIME* local_X509_get0_notAfter(const X509* x509); ++extern "C" const ASN1_TIME* local_X509_get0_notBefore(const X509* x509); ++extern "C" ASN1_BIT_STRING* local_X509_get0_pubkey_bitstr(const X509* x509); ++extern "C" const X509_ALGOR* local_X509_get0_tbs_sigalg(const X509* x509); ++extern "C" X509_PUBKEY* local_X509_get_X509_PUBKEY(const X509* x509); ++extern "C" int32_t local_X509_get_version(const X509* x509); ++extern "C" int32_t local_X509_up_ref(X509* x509); +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake b/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake +index 809ffe318e..cdc9f50f3c 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake ++++ b/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake +@@ -2,11 +2,6 @@ include(CheckLibraryExists) + include(CheckFunctionExists) + + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) +- +-# Check which versions of TLS the OpenSSL/ssl library supports +-check_library_exists(${OPENSSL_SSL_LIBRARY} "TLSv1_1_method" "" HAVE_TLS_V1_1) +-check_library_exists(${OPENSSL_SSL_LIBRARY} "TLSv1_2_method" "" HAVE_TLS_V1_2) +- + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) + + check_function_exists( +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp b/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp +index 46396370b4..f419b755b7 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl.cpp +@@ -6,6 +6,7 @@ + #include "pal_utilities.h" + #include "pal_safecrt.h" + #include "opensslshim.h" ++#include "openssl.h" + + #include + #include +@@ -78,7 +79,7 @@ extern "C" int32_t CryptoNative_GetX509Thumbprint(X509* x509, uint8_t* pBuf, int + return -SHA_DIGEST_LENGTH; + } + +- if (!X509_digest(x509, EVP_sha1(), pBuf, NULL)) ++ if (!X509_digest(x509, EVP_sha1(), pBuf, nullptr)) + { + return 0; + } +@@ -97,14 +98,14 @@ Return values: + NULL if the validity cannot be determined, a pointer to the ASN1_TIME structure for the NotBefore value + otherwise. + */ +-extern "C" ASN1_TIME* CryptoNative_GetX509NotBefore(X509* x509) ++extern "C" const ASN1_TIME* CryptoNative_GetX509NotBefore(X509* x509) + { +- if (x509 && x509->cert_info && x509->cert_info->validity) ++ if (x509) + { +- return x509->cert_info->validity->notBefore; ++ return X509_get0_notBefore(x509); + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -118,14 +119,14 @@ Return values: + NULL if the validity cannot be determined, a pointer to the ASN1_TIME structure for the NotAfter value + otherwise. + */ +-extern "C" ASN1_TIME* CryptoNative_GetX509NotAfter(X509* x509) ++extern "C" const ASN1_TIME* CryptoNative_GetX509NotAfter(X509* x509) + { +- if (x509 && x509->cert_info && x509->cert_info->validity) ++ if (x509) + { +- return x509->cert_info->validity->notAfter; ++ return X509_get0_notAfter(x509); + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -139,14 +140,14 @@ Return values: + NULL if the validity cannot be determined, a pointer to the ASN1_TIME structure for the NextUpdate value + otherwise. + */ +-extern "C" ASN1_TIME* CryptoNative_GetX509CrlNextUpdate(X509_CRL* crl) ++extern "C" const ASN1_TIME* CryptoNative_GetX509CrlNextUpdate(X509_CRL* crl) + { + if (crl) + { +- return X509_CRL_get_nextUpdate(crl); ++ return X509_CRL_get0_nextUpdate(crl); + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -165,9 +166,9 @@ The encoded value of the version, otherwise: + */ + extern "C" int32_t CryptoNative_GetX509Version(X509* x509) + { +- if (x509 && x509->cert_info) ++ if (x509) + { +- long ver = ASN1_INTEGER_get(x509->cert_info->version); ++ long ver = X509_get_version(x509); + return static_cast(ver); + } + +@@ -187,12 +188,18 @@ describing the object type. + */ + extern "C" ASN1_OBJECT* CryptoNative_GetX509PublicKeyAlgorithm(X509* x509) + { +- if (x509 && x509->cert_info && x509->cert_info->key && x509->cert_info->key->algor) ++ if (x509) + { +- return x509->cert_info->key->algor->algorithm; ++ X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509); ++ ASN1_OBJECT* algOid; ++ ++ if (pubkey && X509_PUBKEY_get0_param(&algOid, nullptr, nullptr, nullptr, pubkey)) ++ { ++ return algOid; ++ } + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -208,12 +215,17 @@ describing the object type. + */ + extern "C" ASN1_OBJECT* CryptoNative_GetX509SignatureAlgorithm(X509* x509) + { +- if (x509 && x509->sig_alg && x509->sig_alg->algorithm) ++ if (x509) + { +- return x509->sig_alg->algorithm; ++ const X509_ALGOR* sigAlg = X509_get0_tbs_sigalg(x509); ++ ++ if (sigAlg) ++ { ++ return sigAlg->algorithm; ++ } + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -230,21 +242,35 @@ Any negative value: The input buffer size was reported as insufficient. A buffer + */ + extern "C" int32_t CryptoNative_GetX509PublicKeyParameterBytes(X509* x509, uint8_t* pBuf, int32_t cBuf) + { +- if (!x509 || !x509->cert_info || !x509->cert_info->key || !x509->cert_info->key->algor) ++ if (!x509) ++ { ++ return 0; ++ } ++ ++ X509_PUBKEY* pubkey = X509_get_X509_PUBKEY(x509); ++ ++ if (!pubkey) ++ { ++ return 0; ++ } ++ ++ X509_ALGOR* alg; ++ ++ if (!X509_PUBKEY_get0_param(nullptr, nullptr, nullptr, &alg, pubkey) || !alg) + { + return 0; + } + +- ASN1_TYPE* parameter = x509->cert_info->key->algor->parameter; ++ ASN1_TYPE* parameter = alg->parameter; + + if (!parameter) + { + // If pBuf is NULL we're asking for the length, so return 0 (which is negative-zero) + // If pBuf is non-NULL we're asking to fill the data, in which case we return 1. +- return pBuf != NULL; ++ return pBuf != nullptr; + } +- +- int len = i2d_ASN1_TYPE(parameter, NULL); ++ ++ int len = i2d_ASN1_TYPE(parameter, nullptr); + + if (cBuf < len) + { +@@ -275,12 +301,12 @@ the public key. + */ + extern "C" ASN1_BIT_STRING* CryptoNative_GetX509PublicKeyBytes(X509* x509) + { +- if (x509 && x509->cert_info && x509->cert_info->key) ++ if (x509) + { +- return x509->cert_info->key->public_key; ++ return X509_get0_pubkey_bitstr(x509); + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -353,7 +379,10 @@ Any negative value: The input buffer size was reported as insufficient. A buffer + */ + extern "C" int32_t CryptoNative_GetX509NameRawBytes(X509_NAME* x509Name, uint8_t* pBuf, int32_t cBuf) + { +- if (!x509Name || !x509Name->bytes || cBuf < 0) ++ const uint8_t* nameBuf; ++ size_t nameBufLen; ++ ++ if (!x509Name || cBuf < 0 || !X509_NAME_get0_der(x509Name, &nameBuf, &nameBufLen)) + { + return 0; + } +@@ -367,13 +396,13 @@ extern "C" int32_t CryptoNative_GetX509NameRawBytes(X509_NAME* x509Name, uint8_t + * value is less than INT_MAX in it's native format; once we know it is not + * too large, we can safely cast to an int to make sure it is not negative + */ +- if (x509Name->bytes->length > INT_MAX) ++ if (nameBufLen > INT_MAX) + { + assert(0 && "Huge length X509_NAME"); + return 0; + } + +- int length = static_cast(x509Name->bytes->length); ++ int length = static_cast(nameBufLen); + + if (length < 0) + { +@@ -386,7 +415,7 @@ extern "C" int32_t CryptoNative_GetX509NameRawBytes(X509_NAME* x509Name, uint8_t + return -length; + } + +- memcpy_s(pBuf, UnsignedCast(cBuf), x509Name->bytes->data, UnsignedCast(length)); ++ memcpy_s(pBuf, UnsignedCast(cBuf), nameBuf, UnsignedCast(length)); + return 1; + } + +@@ -437,9 +466,9 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32 + { + static const char szOidUpn[] = "1.3.6.1.4.1.311.20.2.3"; + +- if (!x509 || !x509->cert_info || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL) ++ if (!x509 || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL) + { +- return NULL; ++ return nullptr; + } + + // Algorithm behaviors (pseudocode). When forIssuer is true, replace "Subject" with "Issuer" and +@@ -454,15 +483,15 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32 + // UrlName: SAN.Entries.FirstOrDefault(type == GEN_URI); + if (nameType == NAME_TYPE_SIMPLE) + { +- X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; ++ X509_NAME* name = forIssuer ? X509_get_issuer_name(x509) : X509_get_subject_name(x509); + + if (name) + { +- ASN1_STRING* cn = NULL; +- ASN1_STRING* ou = NULL; +- ASN1_STRING* o = NULL; +- ASN1_STRING* e = NULL; +- ASN1_STRING* firstRdn = NULL; ++ ASN1_STRING* cn = nullptr; ++ ASN1_STRING* ou = nullptr; ++ ASN1_STRING* o = nullptr; ++ ASN1_STRING* e = nullptr; ++ ASN1_STRING* firstRdn = nullptr; + + // Walk the list backwards because it is stored in stack order + for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) +@@ -564,7 +593,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32 + } + + STACK_OF(GENERAL_NAME)* altNames = static_cast( +- X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL)); ++ X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, nullptr, nullptr)); + + if (altNames) + { +@@ -576,7 +605,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32 + + if (altName && altName->type == expectedType) + { +- ASN1_STRING* str = NULL; ++ ASN1_STRING* str = nullptr; + + switch (nameType) + { +@@ -629,7 +658,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32 + + if (nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_DNS) + { +- X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; ++ X509_NAME* name = forIssuer ? X509_get_issuer_name(x509) : X509_get_subject_name(x509); + int expectedNid = NID_undef; + + switch (nameType) +@@ -674,7 +703,7 @@ extern "C" BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32 + } + } + +- return NULL; ++ return nullptr; + } + + /* +@@ -821,7 +850,7 @@ extern "C" int32_t CryptoNative_CheckX509Hostname(X509* x509, const char* hostna + int subjectNid = NID_commonName; + int sanGenType = GEN_DNS; + GENERAL_NAMES* san = static_cast( +- X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ++ X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)); + char readSubject = 1; + int success = 0; + +@@ -909,7 +938,7 @@ extern "C" int32_t CryptoNative_CheckX509IpAddress( + + int subjectNid = NID_commonName; + int sanGenType = GEN_IPADD; +- GENERAL_NAMES* san = static_cast(X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL)); ++ GENERAL_NAMES* san = static_cast(X509_get_ext_d2i(x509, NID_subject_alt_name, nullptr, nullptr)); + int success = 0; + + if (san) +@@ -1070,7 +1099,7 @@ otherwise NULL. + */ + extern "C" X509* CryptoNative_ReadX509AsDerFromBio(BIO* bio) + { +- return d2i_X509_bio(bio, NULL); ++ return d2i_X509_bio(bio, nullptr); + } + + /* +@@ -1242,6 +1271,26 @@ extern "C" int32_t CryptoNative_LookupFriendlyNameByOid(const char* oidValue, co + return 0; + } + ++#ifndef OPENSSL_VERSION ++#define OPENSSL_VERSION 0 ++#endif ++ ++/* ++Function: ++SSLEayVersion ++ ++Gets the version of openssl library. ++ ++Return values: ++Textual description of the version on success. ++"not available" string on failure. ++*/ ++extern "C" char* CryptoNative_SSLEayVersion() ++{ ++ return strdup(OpenSSL_version(OPENSSL_VERSION)); ++} ++ ++#ifdef NEED_OPENSSL_1_0 + // Lock used to make sure EnsureopenSslInitialized itself is thread safe + static pthread_mutex_t g_initLock = PTHREAD_MUTEX_INITIALIZER; + +@@ -1262,6 +1311,10 @@ static void LockingCallback(int mode, int n, const char* file, int line) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wthread-safety-analysis" + ++#ifndef CRYPTO_LOCK ++#define CRYPTO_LOCK 1 ++#endif ++ + int result; + if (mode & CRYPTO_LOCK) + { +@@ -1307,7 +1360,7 @@ Return values: + 0 on success + non-zero on failure + */ +-extern "C" int32_t CryptoNative_EnsureOpenSslInitialized() ++static int32_t EnsureOpenSsl10Initialized() + { + int ret = 0; + int numLocks = 0; +@@ -1383,25 +1436,53 @@ done: + pthread_mutex_destroy(&g_locks[i]); // ignore failures + } + delete[] g_locks; +- g_locks = NULL; ++ g_locks = nullptr; + } + } + + pthread_mutex_unlock(&g_initLock); + return ret; + } ++#endif // NEED_OPENSSL_1_0 */ + +-/* +-Function: +-SSLEayVersion ++#ifdef NEED_OPENSSL_1_1 + +-Gets the version of openssl library. ++static int32_t EnsureOpenSsl11Initialized() ++{ ++ // In OpenSSL 1.0 we call OPENSSL_add_all_algorithms_conf() and ERR_load_crypto_strings(), ++ // so do the same for 1.1 ++ OPENSSL_init_ssl( ++ // OPENSSL_add_all_algorithms_conf ++ OPENSSL_INIT_ADD_ALL_CIPHERS | ++ OPENSSL_INIT_ADD_ALL_DIGESTS | ++ OPENSSL_INIT_LOAD_CONFIG | ++ // ERR_load_crypto_strings ++ OPENSSL_INIT_LOAD_CRYPTO_STRINGS | ++ OPENSSL_INIT_LOAD_SSL_STRINGS, ++ nullptr); + +-Return values: +-Textual description of the version on success. +-"not available" string on failure. +-*/ +-extern "C" char* CryptoNative_SSLEayVersion() ++ return 0; ++} ++ ++#endif ++ ++extern "C" int32_t CryptoNative_EnsureOpenSslInitialized() + { +- return strdup(SSLeay_version(SSLEAY_VERSION)); ++ // If portable then decide which OpenSSL we are, and call the right one. ++ // If 1.0, call the 1.0 one. ++ // Otherwise call the 1.1 one. ++#ifdef FEATURE_DISTRO_AGNOSTIC_SSL ++ if (API_EXISTS(SSL_state)) ++ { ++ return EnsureOpenSsl10Initialized(); ++ } ++ else ++ { ++ return EnsureOpenSsl11Initialized(); ++ } ++#elif OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM ++ return EnsureOpenSsl10Initialized(); ++#else ++ return EnsureOpenSsl11Initialized(); ++#endif + } +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl.h b/src/Native/Unix/System.Security.Cryptography.Native/openssl.h +new file mode 100644 +index 0000000000..372d6fd45a +--- /dev/null ++++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl.h +@@ -0,0 +1,11 @@ ++// Licensed to the .NET Foundation under one or more agreements. ++// The .NET Foundation licenses this file to you under the MIT license. ++// See the LICENSE file in the project root for more information. ++// ++ ++#pragma once ++ ++#include "pal_compiler.h" ++#include "opensslshim.h" ++ ++extern "C" char* CryptoNative_SSLEayVersion(); +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h b/src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h +new file mode 100644 +index 0000000000..8852c3c1b3 +--- /dev/null ++++ b/src/Native/Unix/System.Security.Cryptography.Native/openssl_1_0_structs.h +@@ -0,0 +1,139 @@ ++// Licensed to the .NET Foundation under one or more agreements. ++// The .NET Foundation licenses this file to you under the MIT license. ++// See the LICENSE file in the project root for more information. ++ ++// Definitions of structures from OpenSSL 1.0.2, modified as relevant to ++// building .NET Core. ++ ++// The CRYPTO_EX_DATA struct is smaller in 1.1, which changes the packing of ++// dsa_st ++struct crypto_ex_data_10_st ++{ ++ STACK_OF(void) * sk; ++ int dummy; ++}; ++ ++struct dsa_st ++{ ++ int _ignored0; ++ long _ignored1; ++ int _ignored2; ++ BIGNUM* p; ++ BIGNUM* q; ++ BIGNUM* g; ++ BIGNUM* pub_key; ++ BIGNUM* priv_key; ++ const void* _ignored3; ++ const void* _ignored4; ++ int _ignored5; ++ const void* _ignored6; ++ int _ignored7; ++ struct crypto_ex_data_10_st ex_data; ++ const DSA_METHOD* meth; ++}; ++ ++struct evp_cipher_ctx_st ++{ ++ // 0xA8 is the sizeof value when building against OpenSSL 1.0.2 on ++ // Ubuntu 16.04 ++ unsigned char _ignored0[0xA8]; ++}; ++ ++struct evp_pkey_st ++{ ++ int _ignored0; ++ int _ignored1; ++ int references; ++}; ++ ++struct hmac_ctx_st ++{ ++ // 0x120 is the sizeof value when building against OpenSSL 1.0.2 on ++ // Ubuntu 16.04 ++ unsigned char _ignored0[0x120]; ++}; ++ ++struct rsa_meth_st ++{ ++ const void* _ignored0; ++ const void* _ignored1; ++ const void* _ignored2; ++ const void* _ignored3; ++ const void* _ignored4; ++ const void* _ignored5; ++ const void* _ignored6; ++ const void* _ignored7; ++ const void* _ignored8; ++ int flags; ++}; ++ ++struct rsa_st ++{ ++ int _ignored0; ++ long _ignored1; ++ const RSA_METHOD* meth; ++ const void* _ignored2; ++ BIGNUM* n; ++ BIGNUM* e; ++ BIGNUM* d; ++ BIGNUM* p; ++ BIGNUM* q; ++ BIGNUM* dmp1; ++ BIGNUM* dmq1; ++ BIGNUM* iqmp; ++}; ++ ++struct x509_cinf_st ++{ ++ ASN1_INTEGER* version; ++ ASN1_INTEGER* serialNumber; ++ X509_ALGOR* signature; ++ X509_NAME* issuer; ++ X509_VAL* validity; ++ X509_NAME* subject; ++ X509_PUBKEY* key; ++}; ++ ++struct X509_crl_info_st ++{ ++ const void* _ignored0; ++ const void* _ignored1; ++ const void* _ignored2; ++ const void* _ignored3; ++ ASN1_TIME* nextUpdate; ++}; ++ ++struct X509_crl_st ++{ ++ X509_CRL_INFO* crl; ++}; ++ ++struct X509_name_st ++{ ++ STACK_OF(X509_NAME_ENTRY) * entries; ++ int _ignored0; ++ BUF_MEM* bytes; ++}; ++ ++struct X509_pubkey_st ++{ ++ X509_ALGOR* algor; ++ ASN1_BIT_STRING* public_key; ++}; ++ ++struct x509_st ++{ ++ X509_CINF* cert_info; ++ const void* _ignored0; ++ const void* _ignored1; ++ int _ignored2; ++ int references; ++}; ++ ++struct x509_store_ctx_st ++{ ++ const void* _ignored0; ++ int _ignored1; ++ X509* cert; ++ STACK_OF(X509*) untrusted; ++}; +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp +index f4e1cb71cb..585f7ac23f 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp +@@ -5,13 +5,25 @@ + + #include + #include ++#include ++#include + + #include "opensslshim.h" + +-// Define pointers to all the used ICU functions +-#define PER_FUNCTION_BLOCK(fn, isRequired) decltype(fn) fn##_ptr; ++// Define pointers to all the used OpenSSL functions ++#define REQUIRED_FUNCTION(fn) __typeof(fn) fn##_ptr; ++#define NEW_REQUIRED_FUNCTION(fn) __typeof(fn) fn##_ptr; ++#define LIGHTUP_FUNCTION(fn) __typeof(fn) fn##_ptr; ++#define FALLBACK_FUNCTION(fn) __typeof(fn) fn##_ptr; ++#define RENAMED_FUNCTION(fn,oldfn) __typeof(fn) fn##_ptr; ++#define LEGACY_FUNCTION(fn) __typeof(fn) fn##_ptr; + FOR_ALL_OPENSSL_FUNCTIONS +-#undef PER_FUNCTION_BLOCK ++#undef LEGACY_FUNCTION ++#undef RENAMED_FUNCTION ++#undef FALLBACK_FUNCTION ++#undef LIGHTUP_FUNCTION ++#undef NEW_REQUIRED_FUNCTION ++#undef REQUIRED_FUNCTION + + // x.x.x, considering the max number of decimal digits for each component + static const int MaxVersionStringLength = 32; +@@ -35,6 +47,12 @@ bool OpenLibrary() + libssl = dlopen(soName, RTLD_LAZY); + } + ++ if (libssl == nullptr) ++ { ++ // Prefer OpenSSL 1.1.x ++ libssl = dlopen("libssl.so.1.1", RTLD_LAZY); ++ } ++ + if (libssl == nullptr) + { + // Debian 9 has dropped support for SSLv3 and so they have bumped their soname. Let's try it +@@ -63,17 +81,41 @@ void InitializeOpenSSLShim() + { + if (!OpenLibrary()) + { +- fprintf(stderr, "No usable version of the libssl was found\n"); ++ fprintf(stderr, "No usable version of libssl was found\n"); + abort(); + } + +- // Get pointers to all the ICU functions that are needed +-#define PER_FUNCTION_BLOCK(fn, isRequired) \ +- fn##_ptr = reinterpret_cast(dlsym(libssl, #fn)); \ +- if ((fn##_ptr) == NULL && isRequired) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } ++ // A function defined in libcrypto.so.1.0.0/libssl.so.1.0.0 that is not defined in ++ // libcrypto.so.1.1.0/libssl.so.1.1.0 ++ const void* v1_0_sentinel = dlsym(libssl, "SSL_state"); ++ ++ // Get pointers to all the functions that are needed ++#define REQUIRED_FUNCTION(fn) \ ++ if (!(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } ++ ++#define NEW_REQUIRED_FUNCTION(fn) \ ++ if (!v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } ++ ++#define LIGHTUP_FUNCTION(fn) \ ++ fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)); ++ ++#define FALLBACK_FUNCTION(fn) \ ++ if (!(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fn##_ptr = (__typeof(fn))local_##fn; } ++ ++#define RENAMED_FUNCTION(fn,oldfn) \ ++ if (!v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } \ ++ if (v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #oldfn)))) { fprintf(stderr, "Cannot get required symbol " #oldfn " from libssl\n"); abort(); } ++ ++#define LEGACY_FUNCTION(fn) \ ++ if (v1_0_sentinel && !(fn##_ptr = (__typeof(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } + + FOR_ALL_OPENSSL_FUNCTIONS +-#undef PER_FUNCTION_BLOCK ++#undef LEGACY_FUNCTION ++#undef RENAMED_FUNCTION ++#undef FALLBACK_FUNCTION ++#undef LIGHTUP_FUNCTION ++#undef NEW_REQUIRED_FUNCTION ++#undef REQUIRED_FUNCTION + } + + __attribute__((destructor)) +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h +index afb2559d12..c10cc1d534 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h +@@ -3,7 +3,7 @@ + // See the LICENSE file in the project root for more information. + // + +-// Enable calling OpenSSL functions through shims to enable support for ++// Enable calling OpenSSL functions through shims to enable support for + // different versioned so files naming and different configuration options + // on various Linux distributions. + +@@ -16,8 +16,8 @@ + #include + #include + #include +-#include + #include ++#include + #include + #include + #include +@@ -35,34 +35,137 @@ + #include + + #include "pal_crypto_config.h" ++#define OPENSSL_VERSION_1_1_0_RTM 0x10100000L ++#define OPENSSL_VERSION_1_0_2_RTM 0x10002000L ++ ++#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM ++ ++// Remove problematic #defines ++#undef SSL_get_state ++#undef SSL_is_init_finished ++#undef X509_get_X509_PUBKEY ++#undef X509_get_version ++ ++#endif ++ ++#ifdef EVP_MD_CTX_create ++#undef EVP_MD_CTX_create ++#undef EVP_MD_CTX_init ++#undef EVP_MD_CTX_destroy ++#undef SSLv23_method ++#endif ++ ++#if defined FEATURE_DISTRO_AGNOSTIC_SSL || OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM ++#include "apibridge.h" ++#endif + + #ifdef FEATURE_DISTRO_AGNOSTIC_SSL + ++#define NEED_OPENSSL_1_0 true ++#define NEED_OPENSSL_1_1 true ++ + #if !HAVE_OPENSSL_EC2M + // In portable build, we need to support the following functions even if they were not present + // on the build OS. The shim will detect their presence at runtime. + #undef HAVE_OPENSSL_EC2M + #define HAVE_OPENSSL_EC2M 1 +-const EC_METHOD *EC_GF2m_simple_method(void); +-int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx); +-int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx); +-int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, +- const EC_POINT *p, BIGNUM *x, BIGNUM *y, BN_CTX *ctx); +-int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *p, +- const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx); ++extern "C" const EC_METHOD* EC_GF2m_simple_method(void); ++extern "C" int EC_GROUP_get_curve_GF2m(const EC_GROUP* group, BIGNUM* p, BIGNUM* a, BIGNUM* b, BN_CTX* ctx); ++extern "C" int EC_GROUP_set_curve_GF2m(EC_GROUP* group, const BIGNUM* p, const BIGNUM* a, const BIGNUM* b, BN_CTX* ctx); ++extern "C" int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP* group, const EC_POINT* p, BIGNUM* x, BIGNUM* y, BN_CTX* ctx); ++extern "C" 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 OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM ++typedef struct stack_st _STACK; ++extern "C" ASN1_STRING* d2i_ASN1_type_bytes(ASN1_STRING** a, const unsigned char** pp, long length, int type); ++extern "C" int CRYPTO_add_lock(int* pointer, int amount, int type, const char* file, int line); ++extern "C" int CRYPTO_num_locks(void); ++extern "C" void CRYPTO_set_locking_callback(void (*func)(int mode, int type, const char* file, int line)); ++extern "C" void ERR_load_crypto_strings(void); ++extern "C" int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX* a); ++extern "C" int EVP_CIPHER_CTX_init(EVP_CIPHER_CTX* a); ++extern "C" void HMAC_CTX_cleanup(HMAC_CTX* ctx); ++extern "C" void HMAC_CTX_init(HMAC_CTX* ctx); ++extern "C" void OPENSSL_add_all_algorithms_conf(void); ++extern "C" int SSL_library_init(void); ++extern "C" void SSL_load_error_strings(void); ++extern "C" int SSL_state(const SSL* ssl); ++extern "C" const char* SSLeay_version(int t); ++#else ++typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS; ++typedef struct stack_st OPENSSL_STACK; ++ ++#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0x00000002L ++#define OPENSSL_INIT_ADD_ALL_CIPHERS 0x00000004L ++#define OPENSSL_INIT_ADD_ALL_DIGESTS 0x00000008L ++#define OPENSSL_INIT_LOAD_CONFIG 0x00000040L ++#define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L ++ ++extern "C" const BIGNUM* DSA_get0_key(const DSA* dsa, const BIGNUM** pubKey, const BIGNUM** privKey); ++extern "C" void DSA_get0_pqg(const DSA* dsa, const BIGNUM** p, const BIGNUM** q, const BIGNUM** g); ++extern "C" const DSA_METHOD* DSA_get_method(const DSA* dsa); ++extern "C" int32_t DSA_set0_key(DSA* dsa, BIGNUM* bnY, BIGNUM* bnX); ++extern "C" int32_t DSA_set0_pqg(DSA* dsa, BIGNUM* bnP, BIGNUM* bnQ, BIGNUM* bnG); ++extern "C" void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX* ctx); ++extern "C" EVP_CIPHER_CTX* EVP_CIPHER_CTX_new(void); ++extern "C" int32_t EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX* ctx); ++extern "C" void EVP_MD_CTX_free(EVP_MD_CTX* ctx); ++extern "C" EVP_MD_CTX* EVP_MD_CTX_new(void); ++extern "C" int32_t EVP_PKEY_up_ref(EVP_PKEY* pkey); ++extern "C" void HMAC_CTX_free(HMAC_CTX* ctx); ++extern "C" HMAC_CTX* HMAC_CTX_new(void); ++extern "C" int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS* settings); ++extern "C" void OPENSSL_sk_free(OPENSSL_STACK*); ++extern "C" OPENSSL_STACK* OPENSSL_sk_new_null(void); ++extern "C" int OPENSSL_sk_num(const OPENSSL_STACK*); ++extern "C" void OPENSSL_sk_pop_free(OPENSSL_STACK* st, void (*func)(void*)); ++extern "C" int OPENSSL_sk_push(OPENSSL_STACK* st, const void* data); ++extern "C" void* OPENSSL_sk_value(const OPENSSL_STACK*, int); ++extern "C" const char* OpenSSL_version(int type); ++extern "C" unsigned long OpenSSL_version_num(); ++extern "C" void RSA_get0_crt_params(const RSA* rsa, const BIGNUM** dmp1, const BIGNUM** dmq1, const BIGNUM** iqmp); ++extern "C" void RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q); ++extern "C" void RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d); ++extern "C" int32_t RSA_meth_get_flags(const RSA_METHOD* meth); ++extern "C" int32_t RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp); ++extern "C" int32_t RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q); ++extern "C" int32_t RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d); ++extern "C" int32_t SSL_is_init_finished(SSL* ssl); ++#undef SSL_CTX_set_options ++extern "C" unsigned long SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options); ++extern "C" void SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level); ++#undef SSL_session_reused ++extern "C" int SSL_session_reused(SSL* ssl); ++extern "C" const SSL_METHOD* TLS_method(void); ++extern "C" const ASN1_TIME* X509_CRL_get0_nextUpdate(const X509_CRL* crl); ++extern "C" int32_t X509_NAME_get0_der(X509_NAME* x509Name, const uint8_t** pder, size_t* pderlen); ++extern "C" int32_t X509_PUBKEY_get0_param( ++ ASN1_OBJECT** palgOid, const uint8_t** pkeyBytes, int* pkeyBytesLen, X509_ALGOR** palg, X509_PUBKEY* pubkey); ++extern "C" X509* X509_STORE_CTX_get0_cert(X509_STORE_CTX* ctx); ++extern "C" STACK_OF(X509) * X509_STORE_CTX_get0_untrusted(X509_STORE_CTX* ctx); ++extern "C" const ASN1_TIME* X509_get0_notAfter(const X509* x509); ++extern "C" const ASN1_TIME* X509_get0_notBefore(const X509* x509); ++extern "C" ASN1_BIT_STRING* X509_get0_pubkey_bitstr(const X509* x509); ++extern "C" const X509_ALGOR* X509_get0_tbs_sigalg(const X509* x509); ++extern "C" X509_PUBKEY* X509_get_X509_PUBKEY(const X509* x509); ++extern "C" int32_t X509_get_version(const X509* x509); ++extern "C" int32_t X509_up_ref(X509* x509); + #endif + + #if !HAVE_OPENSSL_ALPN + #undef HAVE_OPENSSL_ALPN + #define HAVE_OPENSSL_ALPN 1 +-int SSL_CTX_set_alpn_protos(SSL_CTX* ctx, const unsigned char* protos, unsigned int protos_len); +-void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, int (*cb) (SSL *ssl, +- const unsigned char **out, +- unsigned char *outlen, +- const unsigned char *in, +- unsigned int inlen, +- void *arg), void *arg); +-void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsigned int* len); ++extern "C" int SSL_CTX_set_alpn_protos(SSL_CTX* ctx, const unsigned char* protos, unsigned int protos_len); ++extern "C" void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx, ++ int (*cb)(SSL* ssl, ++ const unsigned char** out, ++ unsigned char* outlen, ++ const unsigned char* in, ++ unsigned int inlen, ++ void* arg), ++ void* arg); ++extern "C" void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsigned int* len); + #endif + + #define API_EXISTS(fn) (fn != nullptr) +@@ -70,304 +173,350 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi + // List of all functions from the libssl that are used in the System.Security.Cryptography.Native. + // Forgetting to add a function here results in build failure with message reporting the function + // that needs to be added. ++ + #define FOR_ALL_OPENSSL_FUNCTIONS \ +- PER_FUNCTION_BLOCK(ASN1_BIT_STRING_free, true) \ +- PER_FUNCTION_BLOCK(ASN1_INTEGER_get, true) \ +- PER_FUNCTION_BLOCK(ASN1_OBJECT_free, true) \ +- PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_free, true) \ +- PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_new, true) \ +- PER_FUNCTION_BLOCK(ASN1_OCTET_STRING_set, true) \ +- PER_FUNCTION_BLOCK(ASN1_STRING_free, true) \ +- PER_FUNCTION_BLOCK(ASN1_STRING_print_ex, true) \ +- PER_FUNCTION_BLOCK(BASIC_CONSTRAINTS_free, true) \ +- PER_FUNCTION_BLOCK(BIO_ctrl, true) \ +- PER_FUNCTION_BLOCK(BIO_ctrl_pending, true) \ +- PER_FUNCTION_BLOCK(BIO_free, true) \ +- PER_FUNCTION_BLOCK(BIO_gets, true) \ +- PER_FUNCTION_BLOCK(BIO_new, true) \ +- PER_FUNCTION_BLOCK(BIO_new_file, true) \ +- PER_FUNCTION_BLOCK(BIO_read, true) \ +- PER_FUNCTION_BLOCK(BIO_s_mem, true) \ +- PER_FUNCTION_BLOCK(BIO_write, true) \ +- PER_FUNCTION_BLOCK(BN_bin2bn, true) \ +- PER_FUNCTION_BLOCK(BN_bn2bin, true) \ +- PER_FUNCTION_BLOCK(BN_clear_free, true) \ +- PER_FUNCTION_BLOCK(BN_free, true) \ +- PER_FUNCTION_BLOCK(BN_new, true) \ +- PER_FUNCTION_BLOCK(BN_num_bits, true) \ +- PER_FUNCTION_BLOCK(CRYPTO_add_lock, true) \ +- PER_FUNCTION_BLOCK(CRYPTO_num_locks, true) \ +- PER_FUNCTION_BLOCK(CRYPTO_set_locking_callback, true) \ +- PER_FUNCTION_BLOCK(d2i_ASN1_BIT_STRING, true) \ +- PER_FUNCTION_BLOCK(d2i_ASN1_OCTET_STRING, true) \ +- PER_FUNCTION_BLOCK(d2i_ASN1_type_bytes, true) \ +- PER_FUNCTION_BLOCK(d2i_BASIC_CONSTRAINTS, true) \ +- PER_FUNCTION_BLOCK(d2i_EXTENDED_KEY_USAGE, true) \ +- PER_FUNCTION_BLOCK(d2i_PKCS12, true) \ +- PER_FUNCTION_BLOCK(d2i_PKCS12_bio, true) \ +- PER_FUNCTION_BLOCK(d2i_PKCS7, true) \ +- PER_FUNCTION_BLOCK(d2i_PKCS7_bio, true) \ +- PER_FUNCTION_BLOCK(d2i_RSAPublicKey, true) \ +- PER_FUNCTION_BLOCK(d2i_X509, true) \ +- PER_FUNCTION_BLOCK(d2i_X509_bio, true) \ +- PER_FUNCTION_BLOCK(d2i_X509_CRL, true) \ +- PER_FUNCTION_BLOCK(d2i_X509_NAME, true) \ +- PER_FUNCTION_BLOCK(DSA_free, true) \ +- PER_FUNCTION_BLOCK(DSA_generate_key, true) \ +- PER_FUNCTION_BLOCK(DSA_generate_parameters_ex, true) \ +- PER_FUNCTION_BLOCK(DSA_new, true) \ +- PER_FUNCTION_BLOCK(DSA_OpenSSL, true) \ +- PER_FUNCTION_BLOCK(DSA_sign, true) \ +- PER_FUNCTION_BLOCK(DSA_size, true) \ +- PER_FUNCTION_BLOCK(DSA_up_ref, true) \ +- PER_FUNCTION_BLOCK(DSA_verify, true) \ +- PER_FUNCTION_BLOCK(ECDSA_sign, true) \ +- PER_FUNCTION_BLOCK(ECDSA_size, true) \ +- PER_FUNCTION_BLOCK(ECDSA_verify, true) \ +- PER_FUNCTION_BLOCK(EC_GFp_mont_method, true) \ +- PER_FUNCTION_BLOCK(EC_GFp_simple_method, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_check, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_free, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get0_generator, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get0_seed, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_cofactor, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_curve_GFp, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_curve_name, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_degree, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_order, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_seed_len, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_method_of, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_new, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_set_curve_GFp, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_set_generator, true) \ +- PER_FUNCTION_BLOCK(EC_GROUP_set_seed, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_check_key, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_free, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_generate_key, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_get0_group, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_get0_private_key, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_get0_public_key, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_new, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_new_by_curve_name, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_set_group, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_set_private_key, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_set_public_key_affine_coordinates, true) \ +- PER_FUNCTION_BLOCK(EC_KEY_up_ref, true) \ +- PER_FUNCTION_BLOCK(EC_METHOD_get_field_type, true) \ +- PER_FUNCTION_BLOCK(EC_POINT_free, true) \ +- PER_FUNCTION_BLOCK(EC_POINT_get_affine_coordinates_GFp, true) \ +- PER_FUNCTION_BLOCK(EC_POINT_new, true) \ +- PER_FUNCTION_BLOCK(EC_POINT_set_affine_coordinates_GFp, true) \ +- PER_FUNCTION_BLOCK(ERR_clear_error, true) \ +- PER_FUNCTION_BLOCK(ERR_error_string_n, true) \ +- PER_FUNCTION_BLOCK(ERR_get_error, true) \ +- PER_FUNCTION_BLOCK(ERR_load_crypto_strings, true) \ +- PER_FUNCTION_BLOCK(ERR_put_error, true) \ +- PER_FUNCTION_BLOCK(ERR_peek_error, true) \ +- PER_FUNCTION_BLOCK(ERR_peek_last_error, true) \ +- PER_FUNCTION_BLOCK(ERR_reason_error_string, true) \ +- PER_FUNCTION_BLOCK(EVP_aes_128_cbc, true) \ +- PER_FUNCTION_BLOCK(EVP_aes_128_ecb, true) \ +- PER_FUNCTION_BLOCK(EVP_aes_192_cbc, true) \ +- PER_FUNCTION_BLOCK(EVP_aes_192_ecb, true) \ +- PER_FUNCTION_BLOCK(EVP_aes_256_cbc, true) \ +- PER_FUNCTION_BLOCK(EVP_aes_256_ecb, true) \ +- PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_cleanup, true) \ +- PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_ctrl, true) \ +- PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_init, true) \ +- PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_set_key_length, true) \ +- PER_FUNCTION_BLOCK(EVP_CIPHER_CTX_set_padding, true) \ +- PER_FUNCTION_BLOCK(EVP_CipherFinal_ex, true) \ +- PER_FUNCTION_BLOCK(EVP_CipherInit_ex, true) \ +- PER_FUNCTION_BLOCK(EVP_CipherUpdate, true) \ +- PER_FUNCTION_BLOCK(EVP_des_cbc, true) \ +- PER_FUNCTION_BLOCK(EVP_des_ecb, true) \ +- PER_FUNCTION_BLOCK(EVP_des_ede3, true) \ +- PER_FUNCTION_BLOCK(EVP_des_ede3_cbc, true) \ +- PER_FUNCTION_BLOCK(EVP_DigestFinal_ex, true) \ +- PER_FUNCTION_BLOCK(EVP_DigestInit_ex, true) \ +- PER_FUNCTION_BLOCK(EVP_DigestUpdate, true) \ +- PER_FUNCTION_BLOCK(EVP_get_digestbyname, true) \ +- PER_FUNCTION_BLOCK(EVP_md5, true) \ +- PER_FUNCTION_BLOCK(EVP_MD_CTX_create, true) \ +- PER_FUNCTION_BLOCK(EVP_MD_CTX_destroy, true) \ +- PER_FUNCTION_BLOCK(EVP_MD_size, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_CTX_free, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_CTX_new, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_derive_set_peer, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_derive_init, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_derive, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_free, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_get1_DSA, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_get1_EC_KEY, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_get1_RSA, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_new, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_set1_DSA, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_set1_EC_KEY, true) \ +- PER_FUNCTION_BLOCK(EVP_PKEY_set1_RSA, true) \ +- PER_FUNCTION_BLOCK(EVP_rc2_cbc, true) \ +- PER_FUNCTION_BLOCK(EVP_rc2_ecb, true) \ +- PER_FUNCTION_BLOCK(EVP_sha1, true) \ +- PER_FUNCTION_BLOCK(EVP_sha256, true) \ +- PER_FUNCTION_BLOCK(EVP_sha384, true) \ +- PER_FUNCTION_BLOCK(EVP_sha512, true) \ +- PER_FUNCTION_BLOCK(EXTENDED_KEY_USAGE_free, true) \ +- PER_FUNCTION_BLOCK(GENERAL_NAMES_free, true) \ +- PER_FUNCTION_BLOCK(HMAC_CTX_cleanup, true) \ +- PER_FUNCTION_BLOCK(HMAC_CTX_init, true) \ +- PER_FUNCTION_BLOCK(HMAC_Final, true) \ +- PER_FUNCTION_BLOCK(HMAC_Init_ex, true) \ +- PER_FUNCTION_BLOCK(HMAC_Update, true) \ +- PER_FUNCTION_BLOCK(i2d_ASN1_INTEGER, true) \ +- PER_FUNCTION_BLOCK(i2d_ASN1_TYPE, true) \ +- PER_FUNCTION_BLOCK(i2d_PKCS12, true) \ +- PER_FUNCTION_BLOCK(i2d_PKCS7, true) \ +- PER_FUNCTION_BLOCK(i2d_X509, true) \ +- PER_FUNCTION_BLOCK(i2d_X509_PUBKEY, true) \ +- PER_FUNCTION_BLOCK(OBJ_ln2nid, true) \ +- PER_FUNCTION_BLOCK(OBJ_nid2ln, true) \ +- PER_FUNCTION_BLOCK(OBJ_nid2sn, true) \ +- PER_FUNCTION_BLOCK(OBJ_nid2obj, true) \ +- PER_FUNCTION_BLOCK(OBJ_obj2nid, true) \ +- PER_FUNCTION_BLOCK(OBJ_obj2txt, true) \ +- PER_FUNCTION_BLOCK(OBJ_sn2nid, true) \ +- PER_FUNCTION_BLOCK(OBJ_txt2nid, true) \ +- PER_FUNCTION_BLOCK(OBJ_txt2obj, true) \ +- PER_FUNCTION_BLOCK(OPENSSL_add_all_algorithms_conf, true) \ +- PER_FUNCTION_BLOCK(OPENSSL_cleanse, true) \ +- PER_FUNCTION_BLOCK(PEM_read_bio_PKCS7, true) \ +- PER_FUNCTION_BLOCK(PEM_read_bio_X509_AUX, true) \ +- PER_FUNCTION_BLOCK(PEM_read_bio_X509_CRL, true) \ +- PER_FUNCTION_BLOCK(PEM_write_bio_X509_CRL, true) \ +- PER_FUNCTION_BLOCK(PKCS12_create, true) \ +- PER_FUNCTION_BLOCK(PKCS12_free, true) \ +- PER_FUNCTION_BLOCK(PKCS12_parse, true) \ +- PER_FUNCTION_BLOCK(PKCS7_add_certificate, true) \ +- PER_FUNCTION_BLOCK(PKCS7_content_new, true) \ +- PER_FUNCTION_BLOCK(PKCS7_free, true) \ +- PER_FUNCTION_BLOCK(PKCS7_new, true) \ +- PER_FUNCTION_BLOCK(PKCS7_set_type, true) \ +- PER_FUNCTION_BLOCK(RAND_bytes, true) \ +- PER_FUNCTION_BLOCK(RAND_poll, true) \ +- PER_FUNCTION_BLOCK(RSA_free, true) \ +- PER_FUNCTION_BLOCK(RSA_generate_key_ex, true) \ +- PER_FUNCTION_BLOCK(RSA_get_method, true) \ +- PER_FUNCTION_BLOCK(RSA_new, true) \ +- PER_FUNCTION_BLOCK(RSA_private_decrypt, true) \ +- PER_FUNCTION_BLOCK(RSA_private_encrypt, true) \ +- PER_FUNCTION_BLOCK(RSA_public_decrypt, true) \ +- PER_FUNCTION_BLOCK(RSA_public_encrypt, true) \ +- PER_FUNCTION_BLOCK(RSA_sign, true) \ +- PER_FUNCTION_BLOCK(RSA_size, true) \ +- PER_FUNCTION_BLOCK(RSA_up_ref, true) \ +- PER_FUNCTION_BLOCK(RSA_verify, true) \ +- PER_FUNCTION_BLOCK(sk_free, true) \ +- PER_FUNCTION_BLOCK(sk_new_null, true) \ +- PER_FUNCTION_BLOCK(sk_num, true) \ +- PER_FUNCTION_BLOCK(sk_pop_free, true) \ +- PER_FUNCTION_BLOCK(sk_push, true) \ +- PER_FUNCTION_BLOCK(sk_value, true) \ +- PER_FUNCTION_BLOCK(SSL_CIPHER_description, true) \ +- PER_FUNCTION_BLOCK(SSL_ctrl, true) \ +- PER_FUNCTION_BLOCK(SSL_set_quiet_shutdown, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_check_private_key, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_ctrl, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_free, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_new, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_alpn_protos, false) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_alpn_select_cb, false) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_cert_verify_callback, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_cipher_list, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_client_cert_cb, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_quiet_shutdown, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_set_verify, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_use_certificate, true) \ +- PER_FUNCTION_BLOCK(SSL_CTX_use_PrivateKey, true) \ +- PER_FUNCTION_BLOCK(SSL_do_handshake, true) \ +- PER_FUNCTION_BLOCK(SSL_free, true) \ +- PER_FUNCTION_BLOCK(SSL_get_client_CA_list, true) \ +- PER_FUNCTION_BLOCK(SSL_get_current_cipher, true) \ +- PER_FUNCTION_BLOCK(SSL_get_error, true) \ +- PER_FUNCTION_BLOCK(SSL_get_finished, true) \ +- PER_FUNCTION_BLOCK(SSL_get_peer_cert_chain, true) \ +- PER_FUNCTION_BLOCK(SSL_get_peer_certificate, true) \ +- PER_FUNCTION_BLOCK(SSL_get_peer_finished, true) \ +- PER_FUNCTION_BLOCK(SSL_get_SSL_CTX, true) \ +- PER_FUNCTION_BLOCK(SSL_get_version, true) \ +- PER_FUNCTION_BLOCK(SSL_get0_alpn_selected, false) \ +- PER_FUNCTION_BLOCK(SSL_library_init, true) \ +- PER_FUNCTION_BLOCK(SSL_load_error_strings, true) \ +- PER_FUNCTION_BLOCK(SSL_new, true) \ +- PER_FUNCTION_BLOCK(SSL_read, true) \ +- PER_FUNCTION_BLOCK(SSL_renegotiate_pending, true) \ +- PER_FUNCTION_BLOCK(SSL_set_accept_state, true) \ +- PER_FUNCTION_BLOCK(SSL_set_bio, true) \ +- PER_FUNCTION_BLOCK(SSL_set_connect_state, true) \ +- PER_FUNCTION_BLOCK(SSL_shutdown, true) \ +- PER_FUNCTION_BLOCK(SSL_state, true) \ +- PER_FUNCTION_BLOCK(SSLeay_version, true) \ +- PER_FUNCTION_BLOCK(SSLv23_method, true) \ +- PER_FUNCTION_BLOCK(SSL_write, true) \ +- PER_FUNCTION_BLOCK(TLSv1_1_method, true) \ +- PER_FUNCTION_BLOCK(TLSv1_2_method, true) \ +- PER_FUNCTION_BLOCK(TLSv1_method, true) \ +- PER_FUNCTION_BLOCK(X509_check_issued, true) \ +- PER_FUNCTION_BLOCK(X509_check_purpose, true) \ +- PER_FUNCTION_BLOCK(X509_CRL_free, true) \ +- PER_FUNCTION_BLOCK(X509_digest, true) \ +- PER_FUNCTION_BLOCK(X509_dup, true) \ +- PER_FUNCTION_BLOCK(X509_EXTENSION_create_by_OBJ, true) \ +- PER_FUNCTION_BLOCK(X509_EXTENSION_free, true) \ +- PER_FUNCTION_BLOCK(X509_EXTENSION_get_critical, true) \ +- PER_FUNCTION_BLOCK(X509_EXTENSION_get_data, true) \ +- PER_FUNCTION_BLOCK(X509_EXTENSION_get_object, true) \ +- PER_FUNCTION_BLOCK(X509_free, true) \ +- PER_FUNCTION_BLOCK(X509_get_default_cert_dir, true) \ +- PER_FUNCTION_BLOCK(X509_get_default_cert_dir_env, true) \ +- PER_FUNCTION_BLOCK(X509_get_default_cert_file, true) \ +- PER_FUNCTION_BLOCK(X509_get_default_cert_file_env, true) \ +- PER_FUNCTION_BLOCK(X509_get_ext, true) \ +- PER_FUNCTION_BLOCK(X509_get_ext_count, true) \ +- PER_FUNCTION_BLOCK(X509_get_ext_d2i, true) \ +- PER_FUNCTION_BLOCK(X509_get_issuer_name, true) \ +- PER_FUNCTION_BLOCK(X509_get_serialNumber, true) \ +- PER_FUNCTION_BLOCK(X509_get_subject_name, true) \ +- PER_FUNCTION_BLOCK(X509_issuer_name_hash, true) \ +- PER_FUNCTION_BLOCK(X509_NAME_entry_count, true) \ +- PER_FUNCTION_BLOCK(X509_NAME_ENTRY_get_data, true) \ +- PER_FUNCTION_BLOCK(X509_NAME_ENTRY_get_object, true) \ +- PER_FUNCTION_BLOCK(X509_NAME_free, true) \ +- PER_FUNCTION_BLOCK(X509_NAME_get_entry, true) \ +- PER_FUNCTION_BLOCK(X509_NAME_get_index_by_NID, true) \ +- PER_FUNCTION_BLOCK(X509_PUBKEY_get, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_add_cert, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_add_crl, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_free, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_get0_param, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_get1_chain, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_get_error, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_get_error_depth, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_init, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_new, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_set_flags, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_CTX_set_verify_cb, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_free, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_new, true) \ +- PER_FUNCTION_BLOCK(X509_STORE_set_flags, true) \ +- PER_FUNCTION_BLOCK(X509V3_EXT_print, true) \ +- PER_FUNCTION_BLOCK(X509_verify_cert, true) \ +- PER_FUNCTION_BLOCK(X509_verify_cert_error_string, true) \ +- PER_FUNCTION_BLOCK(X509_VERIFY_PARAM_set_time, true) \ +- PER_FUNCTION_BLOCK(EC_GF2m_simple_method, false) \ +- PER_FUNCTION_BLOCK(EC_GROUP_get_curve_GF2m, false) \ +- PER_FUNCTION_BLOCK(EC_GROUP_set_curve_GF2m, false) \ +- PER_FUNCTION_BLOCK(EC_POINT_get_affine_coordinates_GF2m, false) \ +- PER_FUNCTION_BLOCK(EC_POINT_set_affine_coordinates_GF2m, false) \ ++ REQUIRED_FUNCTION(ASN1_BIT_STRING_free) \ ++ REQUIRED_FUNCTION(ASN1_INTEGER_get) \ ++ REQUIRED_FUNCTION(ASN1_OBJECT_free) \ ++ REQUIRED_FUNCTION(ASN1_OCTET_STRING_free) \ ++ REQUIRED_FUNCTION(ASN1_OCTET_STRING_new) \ ++ REQUIRED_FUNCTION(ASN1_OCTET_STRING_set) \ ++ REQUIRED_FUNCTION(ASN1_STRING_free) \ ++ REQUIRED_FUNCTION(ASN1_STRING_print_ex) \ ++ REQUIRED_FUNCTION(BASIC_CONSTRAINTS_free) \ ++ REQUIRED_FUNCTION(BIO_ctrl) \ ++ REQUIRED_FUNCTION(BIO_ctrl_pending) \ ++ REQUIRED_FUNCTION(BIO_free) \ ++ REQUIRED_FUNCTION(BIO_gets) \ ++ REQUIRED_FUNCTION(BIO_new) \ ++ REQUIRED_FUNCTION(BIO_new_file) \ ++ REQUIRED_FUNCTION(BIO_read) \ ++ REQUIRED_FUNCTION(BIO_s_mem) \ ++ REQUIRED_FUNCTION(BIO_write) \ ++ REQUIRED_FUNCTION(BN_bin2bn) \ ++ REQUIRED_FUNCTION(BN_bn2bin) \ ++ REQUIRED_FUNCTION(BN_clear_free) \ ++ REQUIRED_FUNCTION(BN_free) \ ++ REQUIRED_FUNCTION(BN_new) \ ++ REQUIRED_FUNCTION(BN_num_bits) \ ++ LEGACY_FUNCTION(CRYPTO_add_lock) \ ++ LEGACY_FUNCTION(CRYPTO_num_locks) \ ++ LEGACY_FUNCTION(CRYPTO_set_locking_callback) \ ++ REQUIRED_FUNCTION(d2i_ASN1_BIT_STRING) \ ++ REQUIRED_FUNCTION(d2i_ASN1_OCTET_STRING) \ ++ LEGACY_FUNCTION(d2i_ASN1_type_bytes) \ ++ REQUIRED_FUNCTION(d2i_BASIC_CONSTRAINTS) \ ++ REQUIRED_FUNCTION(d2i_EXTENDED_KEY_USAGE) \ ++ REQUIRED_FUNCTION(d2i_PKCS12) \ ++ REQUIRED_FUNCTION(d2i_PKCS12_bio) \ ++ REQUIRED_FUNCTION(d2i_PKCS7) \ ++ REQUIRED_FUNCTION(d2i_PKCS7_bio) \ ++ REQUIRED_FUNCTION(d2i_RSAPublicKey) \ ++ REQUIRED_FUNCTION(d2i_X509) \ ++ REQUIRED_FUNCTION(d2i_X509_bio) \ ++ REQUIRED_FUNCTION(d2i_X509_CRL) \ ++ REQUIRED_FUNCTION(d2i_X509_NAME) \ ++ REQUIRED_FUNCTION(DSA_free) \ ++ REQUIRED_FUNCTION(DSA_generate_key) \ ++ REQUIRED_FUNCTION(DSA_generate_parameters_ex) \ ++ FALLBACK_FUNCTION(DSA_get0_key) \ ++ FALLBACK_FUNCTION(DSA_get0_pqg) \ ++ FALLBACK_FUNCTION(DSA_get_method) \ ++ REQUIRED_FUNCTION(DSA_new) \ ++ REQUIRED_FUNCTION(DSA_OpenSSL) \ ++ FALLBACK_FUNCTION(DSA_set0_key) \ ++ FALLBACK_FUNCTION(DSA_set0_pqg) \ ++ REQUIRED_FUNCTION(DSA_sign) \ ++ REQUIRED_FUNCTION(DSA_size) \ ++ REQUIRED_FUNCTION(DSA_up_ref) \ ++ REQUIRED_FUNCTION(DSA_verify) \ ++ REQUIRED_FUNCTION(ECDSA_sign) \ ++ REQUIRED_FUNCTION(ECDSA_size) \ ++ REQUIRED_FUNCTION(ECDSA_verify) \ ++ REQUIRED_FUNCTION(EC_GFp_mont_method) \ ++ REQUIRED_FUNCTION(EC_GFp_simple_method) \ ++ REQUIRED_FUNCTION(EC_GROUP_check) \ ++ REQUIRED_FUNCTION(EC_GROUP_free) \ ++ REQUIRED_FUNCTION(EC_GROUP_get0_generator) \ ++ REQUIRED_FUNCTION(EC_GROUP_get0_seed) \ ++ REQUIRED_FUNCTION(EC_GROUP_get_cofactor) \ ++ REQUIRED_FUNCTION(EC_GROUP_get_curve_GFp) \ ++ REQUIRED_FUNCTION(EC_GROUP_get_curve_name) \ ++ REQUIRED_FUNCTION(EC_GROUP_get_degree) \ ++ REQUIRED_FUNCTION(EC_GROUP_get_order) \ ++ REQUIRED_FUNCTION(EC_GROUP_get_seed_len) \ ++ REQUIRED_FUNCTION(EC_GROUP_method_of) \ ++ REQUIRED_FUNCTION(EC_GROUP_new) \ ++ REQUIRED_FUNCTION(EC_GROUP_set_curve_GFp) \ ++ REQUIRED_FUNCTION(EC_GROUP_set_generator) \ ++ REQUIRED_FUNCTION(EC_GROUP_set_seed) \ ++ REQUIRED_FUNCTION(EC_KEY_check_key) \ ++ REQUIRED_FUNCTION(EC_KEY_free) \ ++ REQUIRED_FUNCTION(EC_KEY_generate_key) \ ++ REQUIRED_FUNCTION(EC_KEY_get0_group) \ ++ REQUIRED_FUNCTION(EC_KEY_get0_private_key) \ ++ REQUIRED_FUNCTION(EC_KEY_get0_public_key) \ ++ REQUIRED_FUNCTION(EC_KEY_new) \ ++ REQUIRED_FUNCTION(EC_KEY_new_by_curve_name) \ ++ REQUIRED_FUNCTION(EC_KEY_set_group) \ ++ REQUIRED_FUNCTION(EC_KEY_set_private_key) \ ++ REQUIRED_FUNCTION(EC_KEY_set_public_key_affine_coordinates) \ ++ REQUIRED_FUNCTION(EC_KEY_up_ref) \ ++ REQUIRED_FUNCTION(EC_METHOD_get_field_type) \ ++ REQUIRED_FUNCTION(EC_POINT_free) \ ++ REQUIRED_FUNCTION(EC_POINT_get_affine_coordinates_GFp) \ ++ REQUIRED_FUNCTION(EC_POINT_new) \ ++ REQUIRED_FUNCTION(EC_POINT_set_affine_coordinates_GFp) \ ++ REQUIRED_FUNCTION(ERR_clear_error) \ ++ REQUIRED_FUNCTION(ERR_error_string_n) \ ++ REQUIRED_FUNCTION(ERR_get_error) \ ++ LEGACY_FUNCTION(ERR_load_crypto_strings) \ ++ REQUIRED_FUNCTION(ERR_put_error) \ ++ REQUIRED_FUNCTION(ERR_peek_error) \ ++ REQUIRED_FUNCTION(ERR_peek_last_error) \ ++ REQUIRED_FUNCTION(ERR_reason_error_string) \ ++ REQUIRED_FUNCTION(EVP_aes_128_cbc) \ ++ REQUIRED_FUNCTION(EVP_aes_128_ecb) \ ++ REQUIRED_FUNCTION(EVP_aes_192_cbc) \ ++ REQUIRED_FUNCTION(EVP_aes_192_ecb) \ ++ REQUIRED_FUNCTION(EVP_aes_256_cbc) \ ++ REQUIRED_FUNCTION(EVP_aes_256_ecb) \ ++ LEGACY_FUNCTION(EVP_CIPHER_CTX_cleanup) \ ++ REQUIRED_FUNCTION(EVP_CIPHER_CTX_ctrl) \ ++ FALLBACK_FUNCTION(EVP_CIPHER_CTX_free) \ ++ LEGACY_FUNCTION(EVP_CIPHER_CTX_init) \ ++ FALLBACK_FUNCTION(EVP_CIPHER_CTX_new) \ ++ FALLBACK_FUNCTION(EVP_CIPHER_CTX_reset) \ ++ REQUIRED_FUNCTION(EVP_CIPHER_CTX_set_key_length) \ ++ REQUIRED_FUNCTION(EVP_CIPHER_CTX_set_padding) \ ++ REQUIRED_FUNCTION(EVP_CipherFinal_ex) \ ++ REQUIRED_FUNCTION(EVP_CipherInit_ex) \ ++ REQUIRED_FUNCTION(EVP_CipherUpdate) \ ++ REQUIRED_FUNCTION(EVP_des_cbc) \ ++ REQUIRED_FUNCTION(EVP_des_ecb) \ ++ REQUIRED_FUNCTION(EVP_des_ede3) \ ++ REQUIRED_FUNCTION(EVP_des_ede3_cbc) \ ++ REQUIRED_FUNCTION(EVP_DigestFinal_ex) \ ++ REQUIRED_FUNCTION(EVP_DigestInit_ex) \ ++ REQUIRED_FUNCTION(EVP_DigestUpdate) \ ++ REQUIRED_FUNCTION(EVP_get_digestbyname) \ ++ REQUIRED_FUNCTION(EVP_md5) \ ++ RENAMED_FUNCTION(EVP_MD_CTX_free, EVP_MD_CTX_destroy) \ ++ RENAMED_FUNCTION(EVP_MD_CTX_new, EVP_MD_CTX_create) \ ++ REQUIRED_FUNCTION(EVP_MD_size) \ ++ REQUIRED_FUNCTION(EVP_PKEY_CTX_free) \ ++ REQUIRED_FUNCTION(EVP_PKEY_CTX_new) \ ++ REQUIRED_FUNCTION(EVP_PKEY_derive_set_peer) \ ++ REQUIRED_FUNCTION(EVP_PKEY_derive_init) \ ++ REQUIRED_FUNCTION(EVP_PKEY_derive) \ ++ REQUIRED_FUNCTION(EVP_PKEY_free) \ ++ REQUIRED_FUNCTION(EVP_PKEY_get1_DSA) \ ++ REQUIRED_FUNCTION(EVP_PKEY_get1_EC_KEY) \ ++ REQUIRED_FUNCTION(EVP_PKEY_get1_RSA) \ ++ REQUIRED_FUNCTION(EVP_PKEY_new) \ ++ REQUIRED_FUNCTION(EVP_PKEY_set1_DSA) \ ++ REQUIRED_FUNCTION(EVP_PKEY_set1_EC_KEY) \ ++ REQUIRED_FUNCTION(EVP_PKEY_set1_RSA) \ ++ FALLBACK_FUNCTION(EVP_PKEY_up_ref) \ ++ REQUIRED_FUNCTION(EVP_rc2_cbc) \ ++ REQUIRED_FUNCTION(EVP_rc2_ecb) \ ++ REQUIRED_FUNCTION(EVP_sha1) \ ++ REQUIRED_FUNCTION(EVP_sha256) \ ++ REQUIRED_FUNCTION(EVP_sha384) \ ++ REQUIRED_FUNCTION(EVP_sha512) \ ++ REQUIRED_FUNCTION(EXTENDED_KEY_USAGE_free) \ ++ REQUIRED_FUNCTION(GENERAL_NAMES_free) \ ++ LEGACY_FUNCTION(HMAC_CTX_cleanup) \ ++ FALLBACK_FUNCTION(HMAC_CTX_free) \ ++ LEGACY_FUNCTION(HMAC_CTX_init) \ ++ FALLBACK_FUNCTION(HMAC_CTX_new) \ ++ REQUIRED_FUNCTION(HMAC_Final) \ ++ REQUIRED_FUNCTION(HMAC_Init_ex) \ ++ REQUIRED_FUNCTION(HMAC_Update) \ ++ REQUIRED_FUNCTION(i2d_ASN1_INTEGER) \ ++ REQUIRED_FUNCTION(i2d_ASN1_TYPE) \ ++ REQUIRED_FUNCTION(i2d_PKCS12) \ ++ REQUIRED_FUNCTION(i2d_PKCS7) \ ++ REQUIRED_FUNCTION(i2d_X509) \ ++ REQUIRED_FUNCTION(i2d_X509_PUBKEY) \ ++ REQUIRED_FUNCTION(OBJ_ln2nid) \ ++ REQUIRED_FUNCTION(OBJ_nid2ln) \ ++ REQUIRED_FUNCTION(OBJ_nid2sn) \ ++ REQUIRED_FUNCTION(OBJ_nid2obj) \ ++ REQUIRED_FUNCTION(OBJ_obj2nid) \ ++ REQUIRED_FUNCTION(OBJ_obj2txt) \ ++ REQUIRED_FUNCTION(OBJ_sn2nid) \ ++ REQUIRED_FUNCTION(OBJ_txt2nid) \ ++ REQUIRED_FUNCTION(OBJ_txt2obj) \ ++ LEGACY_FUNCTION(OPENSSL_add_all_algorithms_conf) \ ++ REQUIRED_FUNCTION(OPENSSL_cleanse) \ ++ NEW_REQUIRED_FUNCTION(OPENSSL_init_ssl) \ ++ RENAMED_FUNCTION(OPENSSL_sk_free, sk_free) \ ++ RENAMED_FUNCTION(OPENSSL_sk_new_null, sk_new_null) \ ++ RENAMED_FUNCTION(OPENSSL_sk_num, sk_num) \ ++ RENAMED_FUNCTION(OPENSSL_sk_pop_free, sk_pop_free) \ ++ RENAMED_FUNCTION(OPENSSL_sk_push, sk_push) \ ++ RENAMED_FUNCTION(OPENSSL_sk_value, sk_value) \ ++ FALLBACK_FUNCTION(OpenSSL_version) \ ++ RENAMED_FUNCTION(OpenSSL_version_num, SSLeay) \ ++ REQUIRED_FUNCTION(PEM_read_bio_PKCS7) \ ++ REQUIRED_FUNCTION(PEM_read_bio_X509_AUX) \ ++ REQUIRED_FUNCTION(PEM_read_bio_X509_CRL) \ ++ REQUIRED_FUNCTION(PEM_write_bio_X509_CRL) \ ++ REQUIRED_FUNCTION(PKCS12_create) \ ++ REQUIRED_FUNCTION(PKCS12_free) \ ++ REQUIRED_FUNCTION(PKCS12_parse) \ ++ REQUIRED_FUNCTION(PKCS7_add_certificate) \ ++ REQUIRED_FUNCTION(PKCS7_free) \ ++ REQUIRED_FUNCTION(PKCS7_new) \ ++ REQUIRED_FUNCTION(PKCS7_set_type) \ ++ REQUIRED_FUNCTION(PKCS7_content_new) \ ++ REQUIRED_FUNCTION(RAND_bytes) \ ++ REQUIRED_FUNCTION(RAND_poll) \ ++ REQUIRED_FUNCTION(RSA_free) \ ++ REQUIRED_FUNCTION(RSA_generate_key_ex) \ ++ REQUIRED_FUNCTION(RSA_get_method) \ ++ FALLBACK_FUNCTION(RSA_get0_crt_params) \ ++ FALLBACK_FUNCTION(RSA_get0_factors) \ ++ FALLBACK_FUNCTION(RSA_get0_key) \ ++ FALLBACK_FUNCTION(RSA_meth_get_flags) \ ++ REQUIRED_FUNCTION(RSA_new) \ ++ REQUIRED_FUNCTION(RSA_private_decrypt) \ ++ REQUIRED_FUNCTION(RSA_private_encrypt) \ ++ REQUIRED_FUNCTION(RSA_public_decrypt) \ ++ REQUIRED_FUNCTION(RSA_public_encrypt) \ ++ FALLBACK_FUNCTION(RSA_set0_crt_params) \ ++ FALLBACK_FUNCTION(RSA_set0_factors) \ ++ FALLBACK_FUNCTION(RSA_set0_key) \ ++ REQUIRED_FUNCTION(RSA_sign) \ ++ REQUIRED_FUNCTION(RSA_size) \ ++ REQUIRED_FUNCTION(RSA_up_ref) \ ++ REQUIRED_FUNCTION(RSA_verify) \ ++ REQUIRED_FUNCTION(SSL_CIPHER_description) \ ++ REQUIRED_FUNCTION(SSL_CIPHER_get_bits) \ ++ REQUIRED_FUNCTION(SSL_ctrl) \ ++ REQUIRED_FUNCTION(SSL_set_quiet_shutdown) \ ++ REQUIRED_FUNCTION(SSL_CTX_check_private_key) \ ++ REQUIRED_FUNCTION(SSL_CTX_ctrl) \ ++ REQUIRED_FUNCTION(SSL_CTX_free) \ ++ FALLBACK_FUNCTION(SSL_is_init_finished) \ ++ REQUIRED_FUNCTION(SSL_CTX_new) \ ++ LIGHTUP_FUNCTION(SSL_CTX_set_alpn_protos) \ ++ LIGHTUP_FUNCTION(SSL_CTX_set_alpn_select_cb) \ ++ REQUIRED_FUNCTION(SSL_CTX_set_cert_verify_callback) \ ++ REQUIRED_FUNCTION(SSL_CTX_set_cipher_list) \ ++ REQUIRED_FUNCTION(SSL_CTX_set_client_cert_cb) \ ++ REQUIRED_FUNCTION(SSL_CTX_set_quiet_shutdown) \ ++ FALLBACK_FUNCTION(SSL_CTX_set_options) \ ++ FALLBACK_FUNCTION(SSL_CTX_set_security_level) \ ++ REQUIRED_FUNCTION(SSL_CTX_set_verify) \ ++ REQUIRED_FUNCTION(SSL_CTX_use_certificate) \ ++ REQUIRED_FUNCTION(SSL_CTX_use_PrivateKey) \ ++ REQUIRED_FUNCTION(SSL_do_handshake) \ ++ REQUIRED_FUNCTION(SSL_free) \ ++ REQUIRED_FUNCTION(SSL_get_client_CA_list) \ ++ REQUIRED_FUNCTION(SSL_get_current_cipher) \ ++ REQUIRED_FUNCTION(SSL_get_error) \ ++ REQUIRED_FUNCTION(SSL_get_finished) \ ++ REQUIRED_FUNCTION(SSL_get_peer_cert_chain) \ ++ REQUIRED_FUNCTION(SSL_get_peer_certificate) \ ++ REQUIRED_FUNCTION(SSL_get_peer_finished) \ ++ REQUIRED_FUNCTION(SSL_get_SSL_CTX) \ ++ REQUIRED_FUNCTION(SSL_get_version) \ ++ LIGHTUP_FUNCTION(SSL_get0_alpn_selected) \ ++ LEGACY_FUNCTION(SSL_library_init) \ ++ LEGACY_FUNCTION(SSL_load_error_strings) \ ++ REQUIRED_FUNCTION(SSL_new) \ ++ REQUIRED_FUNCTION(SSL_read) \ ++ REQUIRED_FUNCTION(SSL_renegotiate_pending) \ ++ FALLBACK_FUNCTION(SSL_session_reused) \ ++ REQUIRED_FUNCTION(SSL_set_accept_state) \ ++ REQUIRED_FUNCTION(SSL_set_bio) \ ++ REQUIRED_FUNCTION(SSL_set_connect_state) \ ++ REQUIRED_FUNCTION(SSL_shutdown) \ ++ LEGACY_FUNCTION(SSL_state) \ ++ LEGACY_FUNCTION(SSLeay_version) \ ++ RENAMED_FUNCTION(TLS_method, SSLv23_method) \ ++ REQUIRED_FUNCTION(SSL_write) \ ++ REQUIRED_FUNCTION(X509_check_issued) \ ++ REQUIRED_FUNCTION(X509_check_purpose) \ ++ REQUIRED_FUNCTION(X509_CRL_free) \ ++ FALLBACK_FUNCTION(X509_CRL_get0_nextUpdate) \ ++ REQUIRED_FUNCTION(X509_digest) \ ++ REQUIRED_FUNCTION(X509_dup) \ ++ REQUIRED_FUNCTION(X509_EXTENSION_create_by_OBJ) \ ++ REQUIRED_FUNCTION(X509_EXTENSION_free) \ ++ REQUIRED_FUNCTION(X509_EXTENSION_get_critical) \ ++ REQUIRED_FUNCTION(X509_EXTENSION_get_data) \ ++ REQUIRED_FUNCTION(X509_EXTENSION_get_object) \ ++ REQUIRED_FUNCTION(X509_free) \ ++ REQUIRED_FUNCTION(X509_get_default_cert_dir) \ ++ REQUIRED_FUNCTION(X509_get_default_cert_dir_env) \ ++ REQUIRED_FUNCTION(X509_get_default_cert_file) \ ++ REQUIRED_FUNCTION(X509_get_default_cert_file_env) \ ++ REQUIRED_FUNCTION(X509_get_ext) \ ++ REQUIRED_FUNCTION(X509_get_ext_count) \ ++ REQUIRED_FUNCTION(X509_get_ext_d2i) \ ++ REQUIRED_FUNCTION(X509_get_issuer_name) \ ++ REQUIRED_FUNCTION(X509_get_serialNumber) \ ++ REQUIRED_FUNCTION(X509_get_subject_name) \ ++ FALLBACK_FUNCTION(X509_get_version) \ ++ FALLBACK_FUNCTION(X509_get_X509_PUBKEY) \ ++ FALLBACK_FUNCTION(X509_get0_notBefore) \ ++ FALLBACK_FUNCTION(X509_get0_notAfter) \ ++ FALLBACK_FUNCTION(X509_get0_pubkey_bitstr) \ ++ FALLBACK_FUNCTION(X509_get0_tbs_sigalg) \ ++ REQUIRED_FUNCTION(X509_issuer_name_hash) \ ++ REQUIRED_FUNCTION(X509_NAME_entry_count) \ ++ REQUIRED_FUNCTION(X509_NAME_ENTRY_get_data) \ ++ REQUIRED_FUNCTION(X509_NAME_ENTRY_get_object) \ ++ REQUIRED_FUNCTION(X509_NAME_free) \ ++ REQUIRED_FUNCTION(X509_NAME_get_entry) \ ++ REQUIRED_FUNCTION(X509_NAME_get_index_by_NID) \ ++ FALLBACK_FUNCTION(X509_NAME_get0_der) \ ++ REQUIRED_FUNCTION(X509_PUBKEY_get) \ ++ FALLBACK_FUNCTION(X509_PUBKEY_get0_param) \ ++ REQUIRED_FUNCTION(X509_STORE_add_cert) \ ++ REQUIRED_FUNCTION(X509_STORE_add_crl) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_free) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_get0_param) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_get1_chain) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_get_error) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_get_error_depth) \ ++ FALLBACK_FUNCTION(X509_STORE_CTX_get0_cert) \ ++ FALLBACK_FUNCTION(X509_STORE_CTX_get0_untrusted) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_init) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_new) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_set_flags) \ ++ REQUIRED_FUNCTION(X509_STORE_CTX_set_verify_cb) \ ++ REQUIRED_FUNCTION(X509_STORE_free) \ ++ REQUIRED_FUNCTION(X509_STORE_new) \ ++ REQUIRED_FUNCTION(X509_STORE_set_flags) \ ++ REQUIRED_FUNCTION(X509V3_EXT_print) \ ++ FALLBACK_FUNCTION(X509_up_ref) \ ++ REQUIRED_FUNCTION(X509_verify_cert) \ ++ REQUIRED_FUNCTION(X509_verify_cert_error_string) \ ++ REQUIRED_FUNCTION(X509_VERIFY_PARAM_set_time) \ ++ LIGHTUP_FUNCTION(EC_GF2m_simple_method) \ ++ LIGHTUP_FUNCTION(EC_GROUP_get_curve_GF2m) \ ++ LIGHTUP_FUNCTION(EC_GROUP_set_curve_GF2m) \ ++ LIGHTUP_FUNCTION(EC_POINT_get_affine_coordinates_GF2m) \ ++ LIGHTUP_FUNCTION(EC_POINT_set_affine_coordinates_GF2m) \ + + // Declare pointers to all the used OpenSSL functions +-#define PER_FUNCTION_BLOCK(fn, isRequired) extern decltype(fn)* fn##_ptr; ++#define REQUIRED_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr; ++#define NEW_REQUIRED_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr; ++#define LIGHTUP_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr; ++#define FALLBACK_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr; ++#define RENAMED_FUNCTION(fn,oldfn) extern "C" __typeof(fn)* fn##_ptr; ++#define LEGACY_FUNCTION(fn) extern "C" __typeof(fn)* fn##_ptr; + FOR_ALL_OPENSSL_FUNCTIONS +-#undef PER_FUNCTION_BLOCK ++#undef LEGACY_FUNCTION ++#undef RENAMED_FUNCTION ++#undef FALLBACK_FUNCTION ++#undef LIGHTUP_FUNCTION ++#undef NEW_REQUIRED_FUNCTION ++#undef REQUIRED_FUNCTION + + // Redefine all calls to OpenSSL functions as calls through pointers that are set + // to the functions from the libssl.so selected by the shim. +@@ -415,8 +564,13 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define DSA_free DSA_free_ptr + #define DSA_generate_key DSA_generate_key_ptr + #define DSA_generate_parameters_ex DSA_generate_parameters_ex_ptr ++#define DSA_get0_key DSA_get0_key_ptr ++#define DSA_get0_pqg DSA_get0_pqg_ptr ++#define DSA_get_method DSA_get_method_ptr + #define DSA_new DSA_new_ptr + #define DSA_OpenSSL DSA_OpenSSL_ptr ++#define DSA_set0_key DSA_set0_key_ptr ++#define DSA_set0_pqg DSA_set0_pqg_ptr + #define DSA_sign DSA_sign_ptr + #define DSA_size DSA_size_ptr + #define DSA_up_ref DSA_up_ref_ptr +@@ -474,7 +628,10 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define EVP_aes_256_ecb EVP_aes_256_ecb_ptr + #define EVP_CIPHER_CTX_cleanup EVP_CIPHER_CTX_cleanup_ptr + #define EVP_CIPHER_CTX_ctrl EVP_CIPHER_CTX_ctrl_ptr ++#define EVP_CIPHER_CTX_free EVP_CIPHER_CTX_free_ptr + #define EVP_CIPHER_CTX_init EVP_CIPHER_CTX_init_ptr ++#define EVP_CIPHER_CTX_new EVP_CIPHER_CTX_new_ptr ++#define EVP_CIPHER_CTX_reset EVP_CIPHER_CTX_reset_ptr + #define EVP_CIPHER_CTX_set_key_length EVP_CIPHER_CTX_set_key_length_ptr + #define EVP_CIPHER_CTX_set_padding EVP_CIPHER_CTX_set_padding_ptr + #define EVP_CipherFinal_ex EVP_CipherFinal_ex_ptr +@@ -489,8 +646,8 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define EVP_DigestUpdate EVP_DigestUpdate_ptr + #define EVP_get_digestbyname EVP_get_digestbyname_ptr + #define EVP_md5 EVP_md5_ptr +-#define EVP_MD_CTX_create EVP_MD_CTX_create_ptr +-#define EVP_MD_CTX_destroy EVP_MD_CTX_destroy_ptr ++#define EVP_MD_CTX_free EVP_MD_CTX_free_ptr ++#define EVP_MD_CTX_new EVP_MD_CTX_new_ptr + #define EVP_MD_size EVP_MD_size_ptr + #define EVP_PKEY_CTX_free EVP_PKEY_CTX_free_ptr + #define EVP_PKEY_CTX_new EVP_PKEY_CTX_new_ptr +@@ -505,6 +662,7 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define EVP_PKEY_set1_DSA EVP_PKEY_set1_DSA_ptr + #define EVP_PKEY_set1_EC_KEY EVP_PKEY_set1_EC_KEY_ptr + #define EVP_PKEY_set1_RSA EVP_PKEY_set1_RSA_ptr ++#define EVP_PKEY_up_ref EVP_PKEY_up_ref_ptr + #define EVP_rc2_cbc EVP_rc2_cbc_ptr + #define EVP_rc2_ecb EVP_rc2_ecb_ptr + #define EVP_sha1 EVP_sha1_ptr +@@ -514,7 +672,9 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define EXTENDED_KEY_USAGE_free EXTENDED_KEY_USAGE_free_ptr + #define GENERAL_NAMES_free GENERAL_NAMES_free_ptr + #define HMAC_CTX_cleanup HMAC_CTX_cleanup_ptr ++#define HMAC_CTX_free HMAC_CTX_free_ptr + #define HMAC_CTX_init HMAC_CTX_init_ptr ++#define HMAC_CTX_new HMAC_CTX_new_ptr + #define HMAC_Final HMAC_Final_ptr + #define HMAC_Init_ex HMAC_Init_ex_ptr + #define HMAC_Update HMAC_Update_ptr +@@ -535,6 +695,15 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define OBJ_txt2obj OBJ_txt2obj_ptr + #define OPENSSL_add_all_algorithms_conf OPENSSL_add_all_algorithms_conf_ptr + #define OPENSSL_cleanse OPENSSL_cleanse_ptr ++#define OPENSSL_init_ssl OPENSSL_init_ssl_ptr ++#define OPENSSL_sk_free OPENSSL_sk_free_ptr ++#define OPENSSL_sk_new_null OPENSSL_sk_new_null_ptr ++#define OPENSSL_sk_num OPENSSL_sk_num_ptr ++#define OPENSSL_sk_pop_free OPENSSL_sk_pop_free_ptr ++#define OPENSSL_sk_push OPENSSL_sk_push_ptr ++#define OPENSSL_sk_value OPENSSL_sk_value_ptr ++#define OpenSSL_version OpenSSL_version_ptr ++#define OpenSSL_version_num OpenSSL_version_num_ptr + #define PEM_read_bio_PKCS7 PEM_read_bio_PKCS7_ptr + #define PEM_read_bio_X509_AUX PEM_read_bio_X509_AUX_ptr + #define PEM_read_bio_X509_CRL PEM_read_bio_X509_CRL_ptr +@@ -551,22 +720,30 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define RAND_poll RAND_poll_ptr + #define RSA_free RSA_free_ptr + #define RSA_generate_key_ex RSA_generate_key_ex_ptr ++#define RSA_get0_crt_params RSA_get0_crt_params_ptr ++#define RSA_get0_factors RSA_get0_factors_ptr ++#define RSA_get0_key RSA_get0_key_ptr + #define RSA_get_method RSA_get_method_ptr ++#define RSA_meth_get_flags RSA_meth_get_flags_ptr + #define RSA_new RSA_new_ptr + #define RSA_private_decrypt RSA_private_decrypt_ptr + #define RSA_private_encrypt RSA_private_encrypt_ptr + #define RSA_public_decrypt RSA_public_decrypt_ptr + #define RSA_public_encrypt RSA_public_encrypt_ptr ++#define RSA_set0_crt_params RSA_set0_crt_params_ptr ++#define RSA_set0_factors RSA_set0_factors_ptr ++#define RSA_set0_key RSA_set0_key_ptr + #define RSA_sign RSA_sign_ptr + #define RSA_size RSA_size_ptr + #define RSA_up_ref RSA_up_ref_ptr + #define RSA_verify RSA_verify_ptr +-#define sk_free sk_free_ptr +-#define sk_new_null sk_new_null_ptr +-#define sk_num sk_num_ptr +-#define sk_pop_free sk_pop_free_ptr +-#define sk_push sk_push_ptr +-#define sk_value sk_value_ptr ++#define sk_free OPENSSL_sk_free_ptr ++#define sk_new_null OPENSSL_sk_new_null_ptr ++#define sk_num OPENSSL_sk_num_ptr ++#define sk_pop_free OPENSSL_sk_pop_free_ptr ++#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_ctrl SSL_ctrl_ptr + #define SSL_set_quiet_shutdown SSL_set_quiet_shutdown_ptr +@@ -579,7 +756,9 @@ FOR_ALL_OPENSSL_FUNCTIONS + #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_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 ++#define SSL_CTX_set_security_level SSL_CTX_set_security_level_ptr + #define SSL_CTX_set_verify SSL_CTX_set_verify_ptr + #define SSL_CTX_use_certificate SSL_CTX_use_certificate_ptr + #define SSL_CTX_use_PrivateKey SSL_CTX_use_PrivateKey_ptr +@@ -595,25 +774,26 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define SSL_get_SSL_CTX SSL_get_SSL_CTX_ptr + #define SSL_get_version SSL_get_version_ptr + #define SSL_get0_alpn_selected SSL_get0_alpn_selected_ptr ++#define SSL_is_init_finished SSL_is_init_finished_ptr + #define SSL_library_init SSL_library_init_ptr + #define SSL_load_error_strings SSL_load_error_strings_ptr + #define SSL_new SSL_new_ptr + #define SSL_read SSL_read_ptr + #define SSL_renegotiate_pending SSL_renegotiate_pending_ptr ++#define SSL_session_reused SSL_session_reused_ptr + #define SSL_set_accept_state SSL_set_accept_state_ptr + #define SSL_set_bio SSL_set_bio_ptr + #define SSL_set_connect_state SSL_set_connect_state_ptr + #define SSL_shutdown SSL_shutdown_ptr + #define SSL_state SSL_state_ptr + #define SSLeay_version SSLeay_version_ptr +-#define SSLv23_method SSLv23_method_ptr ++#define SSLeay SSLeay_ptr + #define SSL_write SSL_write_ptr +-#define TLSv1_1_method TLSv1_1_method_ptr +-#define TLSv1_2_method TLSv1_2_method_ptr +-#define TLSv1_method TLSv1_method_ptr ++#define TLS_method TLS_method_ptr + #define X509_check_issued X509_check_issued_ptr + #define X509_check_purpose X509_check_purpose_ptr + #define X509_CRL_free X509_CRL_free_ptr ++#define X509_CRL_get0_nextUpdate X509_CRL_get0_nextUpdate_ptr + #define X509_digest X509_digest_ptr + #define X509_dup X509_dup_ptr + #define X509_EXTENSION_create_by_OBJ X509_EXTENSION_create_by_OBJ_ptr +@@ -622,6 +802,10 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define X509_EXTENSION_get_data X509_EXTENSION_get_data_ptr + #define X509_EXTENSION_get_object X509_EXTENSION_get_object_ptr + #define X509_free X509_free_ptr ++#define X509_get0_notAfter X509_get0_notAfter_ptr ++#define X509_get0_notBefore X509_get0_notBefore_ptr ++#define X509_get0_pubkey_bitstr X509_get0_pubkey_bitstr_ptr ++#define X509_get0_tbs_sigalg X509_get0_tbs_sigalg_ptr + #define X509_get_default_cert_dir X509_get_default_cert_dir_ptr + #define X509_get_default_cert_dir_env X509_get_default_cert_dir_env_ptr + #define X509_get_default_cert_file X509_get_default_cert_file_ptr +@@ -632,18 +816,24 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define X509_get_issuer_name X509_get_issuer_name_ptr + #define X509_get_serialNumber X509_get_serialNumber_ptr + #define X509_get_subject_name X509_get_subject_name_ptr ++#define X509_get_X509_PUBKEY X509_get_X509_PUBKEY_ptr ++#define X509_get_version X509_get_version_ptr + #define X509_issuer_name_hash X509_issuer_name_hash_ptr + #define X509_NAME_entry_count X509_NAME_entry_count_ptr + #define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_get_data_ptr + #define X509_NAME_ENTRY_get_object X509_NAME_ENTRY_get_object_ptr + #define X509_NAME_free X509_NAME_free_ptr ++#define X509_NAME_get0_der X509_NAME_get0_der_ptr + #define X509_NAME_get_entry X509_NAME_get_entry_ptr + #define X509_NAME_get_index_by_NID X509_NAME_get_index_by_NID_ptr ++#define X509_PUBKEY_get0_param X509_PUBKEY_get0_param_ptr + #define X509_PUBKEY_get X509_PUBKEY_get_ptr + #define X509_STORE_add_cert X509_STORE_add_cert_ptr + #define X509_STORE_add_crl X509_STORE_add_crl_ptr + #define X509_STORE_CTX_free X509_STORE_CTX_free_ptr ++#define X509_STORE_CTX_get0_cert X509_STORE_CTX_get0_cert_ptr + #define X509_STORE_CTX_get0_param X509_STORE_CTX_get0_param_ptr ++#define X509_STORE_CTX_get0_untrusted X509_STORE_CTX_get0_untrusted_ptr + #define X509_STORE_CTX_get1_chain X509_STORE_CTX_get1_chain_ptr + #define X509_STORE_CTX_get_error X509_STORE_CTX_get_error_ptr + #define X509_STORE_CTX_get_error_depth X509_STORE_CTX_get_error_depth_ptr +@@ -655,6 +845,7 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define X509_STORE_new X509_STORE_new_ptr + #define X509_STORE_set_flags X509_STORE_set_flags_ptr + #define X509V3_EXT_print X509V3_EXT_print_ptr ++#define X509_up_ref X509_up_ref_ptr + #define X509_verify_cert X509_verify_cert_ptr + #define X509_verify_cert_error_string X509_verify_cert_error_string_ptr + #define X509_VERIFY_PARAM_set_time X509_VERIFY_PARAM_set_time_ptr +@@ -664,8 +855,99 @@ FOR_ALL_OPENSSL_FUNCTIONS + #define EC_POINT_get_affine_coordinates_GF2m EC_POINT_get_affine_coordinates_GF2m_ptr + #define EC_POINT_set_affine_coordinates_GF2m EC_POINT_set_affine_coordinates_GF2m_ptr + ++ ++// STACK_OF types will have been declared with inline functions to handle the pointer casting. ++// Since these inline functions are strongly bound to the OPENSSL_sk_* functions in 1.1 we need to ++// rebind things here. ++#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM ++// type-safe OPENSSL_sk_free ++#define sk_GENERAL_NAME_free(stack) OPENSSL_sk_free((OPENSSL_STACK*)(1 ? stack : (STACK_OF(GENERAL_NAME)*)0)) ++ ++// type-safe OPENSSL_sk_num ++#define sk_ASN1_OBJECT_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(ASN1_OBJECT)*)0)) ++#define sk_GENERAL_NAME_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(GENERAL_NAME)*)0)) ++#define sk_X509_NAME_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509_NAME)*)0)) ++#define sk_X509_num(stack) OPENSSL_sk_num((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509)*)0)) ++ ++// type-safe OPENSSL_sk_new_null ++#define sk_X509_new_null() (STACK_OF(X509)*)OPENSSL_sk_new_null() ++#define sk_X509_NAME_new_null() (STACK_OF(X509_NAME)*)OPENSSL_sk_new_null() ++ ++// type-safe OPENSSL_sk_push ++#define sk_X509_push(stack,value) OPENSSL_sk_push((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509)*)0), (const void*)(1 ? value : (X509*)0)) ++#define sk_X509_NAME_push(stack,value) OPENSSL_sk_push((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509_NAME)*)0), (const void*)(1 ? value : (X509_NAME*)0)) ++ ++// type-safe OPENSSL_sk_pop_free ++#define sk_X509_pop_free(stack, freefunc) OPENSSL_sk_pop_free((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509)*)0), (OPENSSL_sk_freefunc)(1 ? freefunc : (sk_X509_freefunc)0)) ++#define sk_X509_NAME_pop_free(stack, freefunc) OPENSSL_sk_pop_free((OPENSSL_STACK*)(1 ? stack : (STACK_OF(X509_NAME)*)0), (OPENSSL_sk_freefunc)(1 ? freefunc : (sk_X509_NAME_freefunc)0)) ++ ++// type-safe OPENSSL_sk_value ++#define sk_ASN1_OBJECT_value(stack, idx) (ASN1_OBJECT*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(ASN1_OBJECT)*)0), idx) ++#define sk_GENERAL_NAME_value(stack, idx) (GENERAL_NAME*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(GENERAL_NAME)*)0), idx) ++#define sk_X509_NAME_value(stack, idx) (X509_NAME*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509_NAME)*)0), idx) ++#define sk_X509_value(stack, idx) (X509*)OPENSSL_sk_value((const OPENSSL_STACK*)(1 ? stack : (const STACK_OF(X509)*)0), idx) ++#endif ++ ++ + #else // FEATURE_DISTRO_AGNOSTIC_SSL + + #define API_EXISTS(fn) true + ++#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM ++ ++#define NEED_OPENSSL_1_0 true ++ ++// Alias "future" API to the local_ version. ++#define DSA_get0_key local_DSA_get0_key ++#define DSA_get0_pqg local_DSA_get0_pqg ++#define DSA_get_method local_DSA_get_method ++#define DSA_set0_key local_DSA_set0_key ++#define DSA_set0_pqg local_DSA_set0_pqg ++#define EVP_CIPHER_CTX_free local_EVP_CIPHER_CTX_free ++#define EVP_CIPHER_CTX_new local_EVP_CIPHER_CTX_new ++#define EVP_CIPHER_CTX_reset local_EVP_CIPHER_CTX_reset ++#define EVP_PKEY_up_ref local_EVP_PKEY_up_ref ++#define HMAC_CTX_free local_HMAC_CTX_free ++#define HMAC_CTX_new local_HMAC_CTX_new ++#define OpenSSL_version local_OpenSSL_version ++#define RSA_get0_crt_params local_RSA_get0_crt_params ++#define RSA_get0_factors local_RSA_get0_factors ++#define RSA_get0_key local_RSA_get0_key ++#define RSA_meth_get_flags local_RSA_meth_get_flags ++#define RSA_set0_crt_params local_RSA_set0_crt_params ++#define RSA_set0_factors local_RSA_set0_factors ++#define RSA_set0_key local_RSA_set0_key ++#define SSL_CTX_set_security_level local_SSL_CTX_set_security_level ++#define SSL_is_init_finished local_SSL_is_init_finished ++#define X509_CRL_get0_nextUpdate local_X509_CRL_get0_nextUpdate ++#define X509_NAME_get0_der local_X509_NAME_get0_der ++#define X509_PUBKEY_get0_param local_X509_PUBKEY_get0_param ++#define X509_STORE_CTX_get0_cert local_X509_STORE_CTX_get0_cert ++#define X509_STORE_CTX_get0_untrusted local_X509_STORE_CTX_get0_untrusted ++#define X509_get0_notAfter local_X509_get0_notAfter ++#define X509_get0_notBefore local_X509_get0_notBefore ++#define X509_get0_pubkey_bitstr local_X509_get0_pubkey_bitstr ++#define X509_get0_tbs_sigalg local_X509_get0_tbs_sigalg ++#define X509_get_X509_PUBKEY local_X509_get_X509_PUBKEY ++#define X509_get_version local_X509_get_version ++#define X509_up_ref local_X509_up_ref ++ ++// Restore the old names for RENAMED_FUNCTION functions. ++#define EVP_MD_CTX_free EVP_MD_CTX_destroy ++#define EVP_MD_CTX_new EVP_MD_CTX_create ++#define OPENSSL_sk_free sk_free ++#define OPENSSL_sk_new_null sk_new_null ++#define OPENSSL_sk_num sk_num ++#define OPENSSL_sk_pop_free sk_pop_free ++#define OPENSSL_sk_push sk_push ++#define OPENSSL_sk_value sk_value ++#define TLS_method SSLv23_method ++#define OpenSSL_version_num SSLeay ++ ++#else // if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM ++ ++#define NEED_OPENSSL_1_1 true ++ ++#endif ++ + #endif // FEATURE_DISTRO_AGNOSTIC_SSL +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp +index 5429592e57..006881aa33 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.cpp +@@ -42,7 +42,7 @@ extern "C" int32_t CryptoNative_ObjSn2Nid(const char* sn) + return OBJ_sn2nid(sn); + } + +-extern "C" ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid) ++extern "C" const ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid) + { + return OBJ_nid2obj(nid); + } +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h +index 6ec1795d25..6f9445aa9f 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1.h +@@ -42,7 +42,7 @@ extern "C" int32_t CryptoNative_ObjSn2Nid(const char* sn); + /* + Direct shim to OBJ_nid2obj. + */ +-extern "C" ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid); ++extern "C" const ASN1_OBJECT* CryptoNative_ObjNid2Obj(int32_t nid); + + /* + Direct shim to ASN1_OBJECT_free. +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp +index 01a544f5e9..328b5e5935 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_asn1_print.cpp +@@ -31,12 +31,19 @@ static_assert(PAL_ASN1_STRFLGS_UTF8_CONVERT == ASN1_STRFLGS_UTF8_CONVERT, ""); + + extern "C" ASN1_STRING* CryptoNative_DecodeAsn1TypeBytes(const uint8_t* buf, int32_t len, Asn1StringTypeFlags type) + { +- if (!buf || !len) ++#if NEED_OPENSSL_1_0 ++ if (!API_EXISTS(d2i_ASN1_type_bytes) || !buf || !len) + { + return nullptr; + } + + return d2i_ASN1_type_bytes(nullptr, &buf, len, type); ++#else ++ (void)buf; ++ (void)len; ++ (void)type; ++ return nullptr; ++#endif + } + + extern "C" int32_t CryptoNative_Asn1StringPrintEx(BIO* out, ASN1_STRING* str, Asn1StringPrintFlags flags) +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in b/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in +index 6aea13f2c6..1aa48ba9d7 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_crypto_config.h.in +@@ -1,6 +1,4 @@ + #pragma once + +-#cmakedefine01 HAVE_TLS_V1_1 +-#cmakedefine01 HAVE_TLS_V1_2 + #cmakedefine01 HAVE_OPENSSL_EC2M + #cmakedefine01 HAVE_OPENSSL_ALPN +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp +index af9ce59d64..74d76a89d7 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.cpp +@@ -45,12 +45,34 @@ extern "C" int32_t CryptoNative_DsaSizeSignature(DSA* dsa) + + extern "C" int32_t CryptoNative_DsaSizeP(DSA* dsa) + { +- return BN_num_bytes(dsa->p); ++ if (dsa) ++ { ++ const BIGNUM* p; ++ DSA_get0_pqg(dsa, &p, nullptr, nullptr); ++ ++ if (p) ++ { ++ return BN_num_bytes(p); ++ } ++ } ++ ++ return -1; + } + + extern "C" int32_t CryptoNative_DsaSizeQ(DSA* dsa) + { +- return BN_num_bytes(dsa->q); ++ if (dsa) ++ { ++ const BIGNUM* q; ++ DSA_get0_pqg(dsa, nullptr, &q, nullptr); ++ ++ if (q) ++ { ++ return BN_num_bytes(q); ++ } ++ } ++ ++ return -1; + } + + extern "C" int32_t CryptoNative_DsaSign( +@@ -67,11 +89,18 @@ extern "C" int32_t CryptoNative_DsaSign( + } + + // DSA_OpenSSL() returns a shared pointer, no need to free/cache. +- if (dsa->meth == DSA_OpenSSL() && dsa->priv_key == nullptr) ++ if (DSA_get_method(dsa) == DSA_OpenSSL()) + { +- *outSignatureLength = 0; +- ERR_PUT_error(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, DSA_R_MISSING_PARAMETERS, __FILE__, __LINE__); +- return 0; ++ const BIGNUM* privKey; ++ ++ DSA_get0_key(dsa, nullptr, &privKey); ++ ++ if (!privKey) ++ { ++ *outSignatureLength = 0; ++ ERR_PUT_error(ERR_LIB_DSA, DSA_F_DSA_DO_SIGN, DSA_R_MISSING_PARAMETERS, __FILE__, __LINE__); ++ return 0; ++ } + } + + unsigned int unsignedSigLen = 0; +@@ -111,11 +140,11 @@ extern "C" int32_t CryptoNative_DsaVerify( + + extern "C" int32_t CryptoNative_GetDsaParameters( + const DSA* dsa, +- BIGNUM** p, int32_t* pLength, +- BIGNUM** q, int32_t* qLength, +- BIGNUM** g, int32_t* gLength, +- BIGNUM** y, int32_t* yLength, +- BIGNUM** x, int32_t* xLength) ++ const BIGNUM** p, int32_t* pLength, ++ const BIGNUM** q, int32_t* qLength, ++ const BIGNUM** g, int32_t* gLength, ++ const BIGNUM** y, int32_t* yLength, ++ const BIGNUM** x, int32_t* xLength) + { + if (!dsa || !p || !q || !g || !y || !x) + { +@@ -129,39 +158,28 @@ extern "C" int32_t CryptoNative_GetDsaParameters( + if (x) *x = nullptr; if (xLength) *xLength = 0; + return 0; + } +- +- *p = dsa->p; *pLength = BN_num_bytes(*p); +- *q = dsa->q; *qLength = BN_num_bytes(*q); +- *g = dsa->g; *gLength = BN_num_bytes(*g); +- *y = dsa->pub_key; *yLength = BN_num_bytes(*y); +- +- // dsa->priv_key is optional +- *x = dsa->priv_key; ++ ++ DSA_get0_pqg(dsa, p, q, g); ++ *pLength = BN_num_bytes(*p); ++ *qLength = BN_num_bytes(*q); ++ *gLength = BN_num_bytes(*g); ++ ++ DSA_get0_key(dsa, y, x); ++ *yLength = BN_num_bytes(*y); ++ // x (the private key) is optional + *xLength = (*x == nullptr) ? 0 : BN_num_bytes(*x); + + return 1; + } + +-static int32_t SetDsaParameter(BIGNUM** dsaFieldAddress, uint8_t* buffer, int32_t bufferLength) ++static BIGNUM* MakeBignum(uint8_t* buffer, int32_t bufferLength) + { +- assert(dsaFieldAddress != nullptr); +- if (dsaFieldAddress) ++ if (buffer && bufferLength) + { +- if (!buffer || !bufferLength) +- { +- *dsaFieldAddress = nullptr; +- return 1; +- } +- else +- { +- BIGNUM* bigNum = BN_bin2bn(buffer, bufferLength, nullptr); +- *dsaFieldAddress = bigNum; +- +- return bigNum != nullptr; +- } ++ return BN_bin2bn(buffer, bufferLength, nullptr); + } + +- return 0; ++ return nullptr; + } + + extern "C" int32_t CryptoNative_DsaKeyCreateByExplicitParameters( +@@ -191,10 +209,33 @@ extern "C" int32_t CryptoNative_DsaKeyCreateByExplicitParameters( + + DSA* dsa = *outDsa; + +- return +- SetDsaParameter(&dsa->p, p, pLength) && +- SetDsaParameter(&dsa->q, q, qLength) && +- SetDsaParameter(&dsa->g, g, gLength) && +- SetDsaParameter(&dsa->pub_key, y, yLength) && +- SetDsaParameter(&dsa->priv_key, x, xLength); ++ BIGNUM* bnP = MakeBignum(p, pLength); ++ BIGNUM* bnQ = MakeBignum(q, qLength); ++ BIGNUM* bnG = MakeBignum(g, gLength); ++ ++ if (!DSA_set0_pqg(dsa, bnP, bnQ, bnG)) ++ { ++ // BN_free handles NULL input ++ BN_free(bnP); ++ BN_free(bnQ); ++ BN_free(bnG); ++ return 0; ++ } ++ ++ // Control was transferred, do not free. ++ bnP = nullptr; ++ bnQ = nullptr; ++ bnG = nullptr; ++ ++ BIGNUM* bnY = MakeBignum(y, yLength); ++ BIGNUM* bnX = MakeBignum(x, xLength); ++ ++ if (!DSA_set0_key(dsa, bnY, bnX)) ++ { ++ BN_free(bnY); ++ BN_free(bnX); ++ return 0; ++ } ++ ++ return 1; + } +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h +index ede7065992..0236741ffa 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_dsa.h +@@ -87,11 +87,11 @@ Returns 1 upon success, otherwise 0. + */ + extern "C" int32_t CryptoNative_GetDsaParameters( + const DSA* dsa, +- BIGNUM** p, int32_t* pLength, +- BIGNUM** q, int32_t* qLength, +- BIGNUM** g, int32_t* gLength, +- BIGNUM** y, int32_t* yLength, +- BIGNUM** x, int32_t* xLength); ++ const BIGNUM** p, int32_t* pLength, ++ const BIGNUM** q, int32_t* qLength, ++ const BIGNUM** g, int32_t* gLength, ++ const BIGNUM** y, int32_t* yLength, ++ const BIGNUM** x, int32_t* xLength); + + /* + Sets all the parameters on the DSA instance. +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp +index 1fbadce9af..d3157ead17 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp.cpp +@@ -10,7 +10,7 @@ + + extern "C" EVP_MD_CTX* CryptoNative_EvpMdCtxCreate(const EVP_MD* type) + { +- EVP_MD_CTX* ctx = EVP_MD_CTX_create(); ++ EVP_MD_CTX* ctx = EVP_MD_CTX_new(); + if (ctx == nullptr) + { + // Allocation failed +@@ -20,7 +20,7 @@ extern "C" EVP_MD_CTX* CryptoNative_EvpMdCtxCreate(const EVP_MD* type) + int ret = EVP_DigestInit_ex(ctx, type, nullptr); + if (!ret) + { +- EVP_MD_CTX_destroy(ctx); ++ EVP_MD_CTX_free(ctx); + return nullptr; + } + +@@ -31,7 +31,7 @@ extern "C" void CryptoNative_EvpMdCtxDestroy(EVP_MD_CTX* ctx) + { + if (ctx != nullptr) + { +- EVP_MD_CTX_destroy(ctx); ++ EVP_MD_CTX_free(ctx); + } + } + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp +index 1f2e80e114..1dc218cac3 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_cipher.cpp +@@ -5,7 +5,6 @@ + #include "pal_evp_cipher.h" + + #include +-#include + + #define SUCCESS 1 + #define KEEP_CURRENT_DIRECTION -1 +@@ -19,28 +18,34 @@ CryptoNative_EvpCipherCreate(const EVP_CIPHER* type, uint8_t* key, unsigned char + extern "C" EVP_CIPHER_CTX* + CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyLength, int32_t effectiveKeyLength, unsigned char* iv, int32_t enc) + { +- std::unique_ptr ctx(new (std::nothrow) EVP_CIPHER_CTX); ++ EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); + if (ctx == nullptr) + { + // Allocation failed + return nullptr; + } + +- EVP_CIPHER_CTX_init(ctx.get()); ++ if (!EVP_CIPHER_CTX_reset(ctx)) ++ { ++ EVP_CIPHER_CTX_free(ctx); ++ return nullptr; ++ } + + // Perform partial initialization so we can set the key lengths +- int ret = EVP_CipherInit_ex(ctx.get(), type, nullptr, nullptr, nullptr, 0); ++ int ret = EVP_CipherInit_ex(ctx, type, nullptr, nullptr, nullptr, 0); + if (!ret) + { ++ EVP_CIPHER_CTX_free(ctx); + return nullptr; + } + + if (keyLength > 0) + { + // Necessary when the default key size is different than current +- ret = EVP_CIPHER_CTX_set_key_length(ctx.get(), keyLength / 8); ++ ret = EVP_CIPHER_CTX_set_key_length(ctx, keyLength / 8); + if (!ret) + { ++ EVP_CIPHER_CTX_free(ctx); + return nullptr; + } + } +@@ -48,29 +53,30 @@ CryptoNative_EvpCipherCreate2(const EVP_CIPHER* type, uint8_t* key, int32_t keyL + if (effectiveKeyLength > 0) + { + // Necessary for RC2 +- ret = EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_SET_RC2_KEY_BITS, effectiveKeyLength, nullptr); ++ ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, effectiveKeyLength, nullptr); + if (ret <= 0) + { ++ EVP_CIPHER_CTX_free(ctx); + return nullptr; + } + } + + // Perform final initialization specifying the remaining arguments +- ret = EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key, iv, enc); ++ ret = EVP_CipherInit_ex(ctx, nullptr, nullptr, key, iv, enc); + if (!ret) + { ++ EVP_CIPHER_CTX_free(ctx); + return nullptr; + } + +- return ctx.release(); ++ return ctx; + } + + extern "C" void CryptoNative_EvpCipherDestroy(EVP_CIPHER_CTX* ctx) + { + if (ctx != nullptr) + { +- EVP_CIPHER_CTX_cleanup(ctx); +- delete ctx; ++ EVP_CIPHER_CTX_free(ctx); + } + } + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp +index 384030740e..f27e93325f 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.cpp +@@ -24,5 +24,5 @@ extern "C" int32_t CryptoNative_UpRefEvpPkey(EVP_PKEY* pkey) + return 0; + } + +- return CRYPTO_add(&pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); ++ return EVP_PKEY_up_ref(pkey); + } +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp +index 10eef6809c..539dc07683 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp +@@ -7,7 +7,6 @@ + #include "pal_hmac.h" + + #include +-#include + + extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, const EVP_MD* md) + { +@@ -15,7 +14,7 @@ extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, + assert(keyLen >= 0); + assert(md != nullptr); + +- std::unique_ptr ctx(new (std::nothrow) HMAC_CTX); ++ HMAC_CTX* ctx = HMAC_CTX_new(); + if (ctx == nullptr) + { + // Allocation failed +@@ -28,23 +27,22 @@ extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, + if (keyLen == 0) + key = &_; + +- HMAC_CTX_init(ctx.get()); +- int ret = HMAC_Init_ex(ctx.get(), key, keyLen, md, nullptr); ++ int ret = HMAC_Init_ex(ctx, key, keyLen, md, nullptr); + + if (!ret) + { ++ free(ctx); + return nullptr; + } + +- return ctx.release(); ++ return ctx; + } + + extern "C" void CryptoNative_HmacDestroy(HMAC_CTX* ctx) + { + if (ctx != nullptr) + { +- HMAC_CTX_cleanup(ctx); +- delete ctx; ++ HMAC_CTX_free(ctx); + } + } + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h +index 131e148c00..570d28e70c 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.h +@@ -12,7 +12,6 @@ + + // Forward declarations - shim API must not depend on knowing layout of these types. + typedef struct hmac_ctx_st HMAC_CTX; +-typedef struct env_md_st EVP_MD; + + /** + * Creates and initializes an HMAC_CTX with the given key and EVP_MD. +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp +index 9ad896aa72..7fa6585c99 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.cpp +@@ -58,8 +58,13 @@ static int HasNoPrivateKey(RSA* rsa) + + // The method has descibed itself as having the private key external to the structure. + // That doesn't mean it's actually present, but we can't tell. +- if (meth->flags & RSA_FLAG_EXT_PKEY) ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wcast-qual" ++ if (RSA_meth_get_flags((RSA_METHOD*)meth) & RSA_FLAG_EXT_PKEY) ++#pragma clang diagnostic pop ++ { + return 0; ++ } + + // In the event that there's a middle-ground where we report failure when success is expected, + // one could do something like check if the RSA_METHOD intercepts all private key operations: +@@ -72,11 +77,27 @@ static int HasNoPrivateKey(RSA* rsa) + + // The module is documented as accepting either d or the full set of CRT parameters (p, q, dp, dq, qInv) + // So if we see d, we're good. Otherwise, if any of the rest are missing, we're public-only. +- if (rsa->d != nullptr) ++ const BIGNUM* d; ++ RSA_get0_key(rsa, nullptr, nullptr, &d); ++ ++ if (d != nullptr) ++ { + return 0; ++ } ++ ++ const BIGNUM* p; ++ const BIGNUM* q; ++ const BIGNUM* dmp1; ++ const BIGNUM* dmq1; ++ const BIGNUM* iqmp; + +- if (rsa->p == nullptr || rsa->q == nullptr || rsa->dmp1 == nullptr || rsa->dmq1 == nullptr || rsa->iqmp == nullptr) ++ RSA_get0_factors(rsa, &p, &q); ++ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); ++ ++ if (p == nullptr || q == nullptr || dmp1 == nullptr || dmq1 == nullptr || iqmp == nullptr) ++ { + return 1; ++ } + + return 0; + } +@@ -93,7 +114,7 @@ CryptoNative_RsaPrivateDecrypt(int32_t flen, const uint8_t* from, uint8_t* to, R + { + if (HasNoPrivateKey(rsa)) + { +- ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__); ++ ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__); + return -1; + } + +@@ -105,7 +126,7 @@ extern "C" int32_t CryptoNative_RsaSignPrimitive(int32_t flen, const uint8_t* fr + { + if (HasNoPrivateKey(rsa)) + { +- ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__); ++ ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_ENCRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__); + return -1; + } + +@@ -169,14 +190,14 @@ CryptoNative_RsaVerify(int32_t type, const uint8_t* m, int32_t mlen, uint8_t* si + } + + extern "C" int32_t CryptoNative_GetRsaParameters(const RSA* rsa, +- BIGNUM** n, +- BIGNUM** e, +- BIGNUM** d, +- BIGNUM** p, +- BIGNUM** dmp1, +- BIGNUM** q, +- BIGNUM** dmq1, +- BIGNUM** iqmp) ++ const BIGNUM** n, ++ const BIGNUM** e, ++ const BIGNUM** d, ++ const BIGNUM** p, ++ const BIGNUM** dmp1, ++ const BIGNUM** q, ++ const BIGNUM** dmq1, ++ const BIGNUM** iqmp) + { + if (!rsa || !n || !e || !d || !p || !dmp1 || !q || !dmq1 || !iqmp) + { +@@ -203,57 +224,40 @@ extern "C" int32_t CryptoNative_GetRsaParameters(const RSA* rsa, + return 0; + } + +- *n = rsa->n; +- *e = rsa->e; +- *d = rsa->d; +- *p = rsa->p; +- *dmp1 = rsa->dmp1; +- *q = rsa->q; +- *dmq1 = rsa->dmq1; +- *iqmp = rsa->iqmp; ++ RSA_get0_key(rsa, n, e, d); ++ RSA_get0_factors(rsa, p, q); ++ RSA_get0_crt_params(rsa, dmp1, dmq1, iqmp); + + return 1; + } + +-static int32_t SetRsaParameter(BIGNUM** rsaFieldAddress, uint8_t* buffer, int32_t bufferLength) ++static BIGNUM* MakeBignum(uint8_t* buffer, int32_t bufferLength) + { +- assert(rsaFieldAddress != nullptr); +- if (rsaFieldAddress) ++ if (buffer && bufferLength) + { +- if (!buffer || !bufferLength) +- { +- *rsaFieldAddress = nullptr; +- return 1; +- } +- else +- { +- BIGNUM* bigNum = BN_bin2bn(buffer, bufferLength, nullptr); +- *rsaFieldAddress = bigNum; +- +- return bigNum != nullptr; +- } ++ return BN_bin2bn(buffer, bufferLength, nullptr); + } + +- return 0; ++ return nullptr; + } + + extern "C" int32_t CryptoNative_SetRsaParameters(RSA* rsa, +- uint8_t* n, +- int32_t nLength, +- uint8_t* e, +- int32_t eLength, +- uint8_t* d, +- int32_t dLength, +- uint8_t* p, +- int32_t pLength, +- uint8_t* dmp1, +- int32_t dmp1Length, +- uint8_t* q, +- int32_t qLength, +- uint8_t* dmq1, +- int32_t dmq1Length, +- uint8_t* iqmp, +- int32_t iqmpLength) ++ uint8_t* n, ++ int32_t nLength, ++ uint8_t* e, ++ int32_t eLength, ++ uint8_t* d, ++ int32_t dLength, ++ uint8_t* p, ++ int32_t pLength, ++ uint8_t* dmp1, ++ int32_t dmp1Length, ++ uint8_t* q, ++ int32_t qLength, ++ uint8_t* dmq1, ++ int32_t dmq1Length, ++ uint8_t* iqmp, ++ int32_t iqmpLength) + { + if (!rsa) + { +@@ -261,13 +265,43 @@ extern "C" int32_t CryptoNative_SetRsaParameters(RSA* rsa, + return 0; + } + +- return +- SetRsaParameter(&rsa->n, n, nLength) && +- SetRsaParameter(&rsa->e, e, eLength) && +- SetRsaParameter(&rsa->d, d, dLength) && +- SetRsaParameter(&rsa->p, p, pLength) && +- SetRsaParameter(&rsa->dmp1, dmp1, dmp1Length) && +- SetRsaParameter(&rsa->q, q, qLength) && +- SetRsaParameter(&rsa->dmq1, dmq1, dmq1Length) && +- SetRsaParameter(&rsa->iqmp, iqmp, iqmpLength); ++ BIGNUM* bnN = MakeBignum(n, nLength); ++ BIGNUM* bnE = MakeBignum(e, eLength); ++ BIGNUM* bnD = MakeBignum(d, dLength); ++ ++ if (!RSA_set0_key(rsa, bnN, bnE, bnD)) ++ { ++ // BN_free handles NULL input ++ BN_free(bnN); ++ BN_free(bnE); ++ BN_free(bnD); ++ return 0; ++ } ++ ++ if (bnD != nullptr) ++ { ++ BIGNUM* bnP = MakeBignum(p, pLength); ++ BIGNUM* bnQ = MakeBignum(q, qLength); ++ ++ if (!RSA_set0_factors(rsa, bnP, bnQ)) ++ { ++ BN_free(bnP); ++ BN_free(bnQ); ++ return 0; ++ } ++ ++ BIGNUM* bnDmp1 = MakeBignum(dmp1, dmp1Length); ++ BIGNUM* bnDmq1 = MakeBignum(dmq1, dmq1Length); ++ BIGNUM* bnIqmp = MakeBignum(iqmp, iqmpLength); ++ ++ if (!RSA_set0_crt_params(rsa, bnDmp1, bnDmq1, bnIqmp)) ++ { ++ BN_free(bnDmp1); ++ BN_free(bnDmq1); ++ BN_free(bnIqmp); ++ return 0; ++ } ++ } ++ ++ return 1; + } +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h +index c4a2737ced..b075911c47 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h +@@ -114,14 +114,14 @@ Gets all the parameters from the RSA instance. + Returns 1 upon success, otherwise 0. + */ + extern "C" int32_t CryptoNative_GetRsaParameters(const RSA* rsa, +- BIGNUM** n, +- BIGNUM** e, +- BIGNUM** d, +- BIGNUM** p, +- BIGNUM** dmp1, +- BIGNUM** q, +- BIGNUM** dmq1, +- BIGNUM** iqmp); ++ const BIGNUM** n, ++ const BIGNUM** e, ++ const BIGNUM** d, ++ const BIGNUM** p, ++ const BIGNUM** dmp1, ++ const BIGNUM** q, ++ const BIGNUM** dmq1, ++ const BIGNUM** iqmp); + + /* + Sets all the parameters on the RSA instance. +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp +index 0d87a8a5f1..b0ebba0ce1 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_ssl.cpp +@@ -3,6 +3,7 @@ + // See the LICENSE file in the project root for more information. + + #include "pal_ssl.h" ++#include "openssl.h" + + #include + #include +@@ -16,16 +17,34 @@ static_assert(PAL_SSL_ERROR_ZERO_RETURN == SSL_ERROR_ZERO_RETURN, ""); + + extern "C" int32_t CryptoNative_EnsureOpenSslInitialized(); + +-extern "C" void CryptoNative_EnsureLibSslInitialized() ++#ifdef NEED_OPENSSL_1_0 ++static void EnsureLibSsl10Initialized() + { +- CryptoNative_EnsureOpenSslInitialized(); + SSL_library_init(); + SSL_load_error_strings(); + } ++#endif ++ ++extern "C" void CryptoNative_EnsureLibSslInitialized() ++{ ++ CryptoNative_EnsureOpenSslInitialized(); ++ ++ // If portable, call the 1.0 initializer when needed. ++ // If 1.0, call it statically. ++ // In 1.1 no action is required, since EnsureOpenSslInitialized does both libraries. ++#ifdef FEATURE_DISTRO_AGNOSTIC_SSL ++ if (API_EXISTS(SSL_state)) ++ { ++ EnsureLibSsl10Initialized(); ++ } ++#elif OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_1_0_RTM ++ EnsureLibSsl10Initialized(); ++#endif ++} + + extern "C" const SSL_METHOD* CryptoNative_SslV2_3Method() + { +- const SSL_METHOD* method = SSLv23_method(); ++ const SSL_METHOD* method = TLS_method(); + assert(method != nullptr); + return method; + } +@@ -51,19 +70,39 @@ Returns 1 on success, 0 on failure. + */ + static long TrySetECDHNamedCurve(SSL_CTX* ctx) + { +- long result = 0; +-#ifdef SSL_CTX_set_ecdh_auto +- result = SSL_CTX_set_ecdh_auto(ctx, 1); +-#else +- EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); +- if (ecdh != nullptr) +- { +- result = SSL_CTX_set_tmp_ecdh(ctx, ecdh); +- EC_KEY_free(ecdh); +- } ++#ifdef NEED_OPENSSL_1_0 ++ long result = 0; ++ unsigned long version = OpenSSL_version_num(); ++ ++ if (version >= OPENSSL_VERSION_1_1_0_RTM) ++ { ++ // OpenSSL 1.1+ automatically set up ECDH ++ result = 1; ++ } ++ else if (version >= OPENSSL_VERSION_1_0_2_RTM) ++ { ++#ifndef SSL_CTRL_SET_ECDH_AUTO ++#define SSL_CTRL_SET_ECDH_AUTO 94 + #endif ++ // Expanded form of SSL_CTX_set_ecdh_auto(ctx, 1) ++ result = SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, 1, nullptr); ++ } ++ else ++ { ++ EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); ++ ++ if (ecdh != nullptr) ++ { ++ result = SSL_CTX_set_tmp_ecdh(ctx, ecdh); ++ EC_KEY_free(ecdh); ++ } ++ } + + return result; ++#else ++ (void)ctx; ++ return 1; ++#endif + } + + extern "C" void CryptoNative_SetProtocolOptions(SSL_CTX* ctx, SslProtocols protocols) +@@ -80,7 +119,7 @@ extern "C" void CryptoNative_SetProtocolOptions(SSL_CTX* ctx, SslProtocols proto + return; + } + +- long protocolOptions = 0; ++ unsigned long protocolOptions = 0; + + if ((protocols & PAL_SSL_SSL2) != PAL_SSL_SSL2) + { +@@ -94,20 +133,26 @@ extern "C" void CryptoNative_SetProtocolOptions(SSL_CTX* ctx, SslProtocols proto + { + protocolOptions |= SSL_OP_NO_TLSv1; + } +-#if HAVE_TLS_V1_1 + if ((protocols & PAL_SSL_TLS11) != PAL_SSL_TLS11) + { + protocolOptions |= SSL_OP_NO_TLSv1_1; + } +-#endif +-#if HAVE_TLS_V1_2 + if ((protocols & PAL_SSL_TLS12) != PAL_SSL_TLS12) + { + protocolOptions |= SSL_OP_NO_TLSv1_2; + } ++ ++ // protocol options were specified, and there's no handler yet for TLS 1.3. ++#ifndef SSL_OP_NO_TLSv1_3 ++#define SSL_OP_NO_TLSv1_3 0x20000000U + #endif ++ protocolOptions |= SSL_OP_NO_TLSv1_3; + ++ // OpenSSL 1.0 calls this long, OpenSSL 1.1 calls it unsigned long. ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wsign-conversion" + SSL_CTX_set_options(ctx, protocolOptions); ++#pragma clang diagnostic pop + } + + extern "C" SSL* CryptoNative_SslCreate(SSL_CTX* ctx) +@@ -254,54 +299,54 @@ static ExchangeAlgorithmType MapExchangeAlgorithmType(const char* keyExchange, s + + static void GetHashAlgorithmTypeAndSize(const char* mac, + size_t macLength, +- HashAlgorithmType& dataHashAlg, +- DataHashSize& hashKeySize) ++ HashAlgorithmType* dataHashAlg, ++ DataHashSize* hashKeySize) + { + if (StringSpanEquals(mac, "MD5", macLength)) + { +- dataHashAlg = HashAlgorithmType::Md5; +- hashKeySize = DataHashSize::MD5_HashKeySize; ++ *dataHashAlg = HashAlgorithmType::Md5; ++ *hashKeySize = DataHashSize::MD5_HashKeySize; + return; + } + if (StringSpanEquals(mac, "SHA1", macLength)) + { +- dataHashAlg = HashAlgorithmType::Sha1; +- hashKeySize = DataHashSize::SHA1_HashKeySize; ++ *dataHashAlg = HashAlgorithmType::Sha1; ++ *hashKeySize = DataHashSize::SHA1_HashKeySize; + return; + } + if (StringSpanEquals(mac, "GOST94", macLength)) + { +- dataHashAlg = HashAlgorithmType::SSL_GOST94; +- hashKeySize = DataHashSize::GOST_HashKeySize; ++ *dataHashAlg = HashAlgorithmType::SSL_GOST94; ++ *hashKeySize = DataHashSize::GOST_HashKeySize; + return; + } + if (StringSpanEquals(mac, "GOST89", macLength)) + { +- dataHashAlg = HashAlgorithmType::SSL_GOST89; +- hashKeySize = DataHashSize::GOST_HashKeySize; ++ *dataHashAlg = HashAlgorithmType::SSL_GOST89; ++ *hashKeySize = DataHashSize::GOST_HashKeySize; + return; + } + if (StringSpanEquals(mac, "SHA256", macLength)) + { +- dataHashAlg = HashAlgorithmType::SSL_SHA256; +- hashKeySize = DataHashSize::SHA256_HashKeySize; ++ *dataHashAlg = HashAlgorithmType::SSL_SHA256; ++ *hashKeySize = DataHashSize::SHA256_HashKeySize; + return; + } + if (StringSpanEquals(mac, "SHA384", macLength)) + { +- dataHashAlg = HashAlgorithmType::SSL_SHA384; +- hashKeySize = DataHashSize::SHA384_HashKeySize; ++ *dataHashAlg = HashAlgorithmType::SSL_SHA384; ++ *hashKeySize = DataHashSize::SHA384_HashKeySize; + return; + } + if (StringSpanEquals(mac, "AEAD", macLength)) + { +- dataHashAlg = HashAlgorithmType::SSL_AEAD; +- hashKeySize = DataHashSize::Default; ++ *dataHashAlg = HashAlgorithmType::SSL_AEAD; ++ *hashKeySize = DataHashSize::Default; + return; + } + +- dataHashAlg = HashAlgorithmType::None; +- hashKeySize = DataHashSize::Default; ++ *dataHashAlg = HashAlgorithmType::None; ++ *hashKeySize = DataHashSize::Default; + } + + /* +@@ -340,10 +385,10 @@ Parses the Kx, Enc, and Mac values out of the SSL_CIPHER_description and + maps the values to the corresponding .NET enum value. + */ + static bool GetSslConnectionInfoFromDescription(const SSL_CIPHER* cipher, +- CipherAlgorithmType& dataCipherAlg, +- ExchangeAlgorithmType& keyExchangeAlg, +- HashAlgorithmType& dataHashAlg, +- DataHashSize& hashKeySize) ++ CipherAlgorithmType* dataCipherAlg, ++ ExchangeAlgorithmType* keyExchangeAlg, ++ HashAlgorithmType* dataHashAlg, ++ DataHashSize* hashKeySize) + { + const int descriptionLength = 256; + char description[descriptionLength] = {}; +@@ -370,8 +415,8 @@ static bool GetSslConnectionInfoFromDescription(const SSL_CIPHER* cipher, + return false; + } + +- keyExchangeAlg = MapExchangeAlgorithmType(keyExchange, keyExchangeLength); +- dataCipherAlg = MapCipherAlgorithmType(encryption, encryptionLength); ++ *keyExchangeAlg = MapExchangeAlgorithmType(keyExchange, keyExchangeLength); ++ *dataCipherAlg = MapCipherAlgorithmType(encryption, encryptionLength); + GetHashAlgorithmTypeAndSize(mac, macLength, dataHashAlg, hashKeySize); + return true; + } +@@ -396,8 +441,9 @@ extern "C" int32_t CryptoNative_GetSslConnectionInfo(SSL* ssl, + goto err; + } + +- *dataKeySize = cipher->alg_bits; +- if (GetSslConnectionInfoFromDescription(cipher, *dataCipherAlg, *keyExchangeAlg, *dataHashAlg, *hashKeySize)) ++ SSL_CIPHER_get_bits(cipher, dataKeySize); ++ ++ if (GetSslConnectionInfoFromDescription(cipher, dataCipherAlg, keyExchangeAlg, dataHashAlg, hashKeySize)) + { + return 1; + } +@@ -453,7 +499,7 @@ extern "C" int32_t CryptoNative_SslDoHandshake(SSL* ssl) + + extern "C" int32_t CryptoNative_IsSslStateOK(SSL* ssl) + { +- return SSL_state(ssl) == SSL_ST_OK; ++ return SSL_is_init_finished(ssl); + } + + extern "C" X509* CryptoNative_SslGetPeerCertificate(SSL* ssl) +@@ -517,6 +563,8 @@ CryptoNative_SslCtxSetCertVerifyCallback(SSL_CTX* ctx, SslCtxSetCertVerifyCallba + extern "C" int32_t CryptoNative_SetEncryptionPolicy(SSL_CTX* ctx, EncryptionPolicy policy) + { + const char* cipherString = nullptr; ++ bool clearSecLevel = false; ++ + switch (policy) + { + case EncryptionPolicy::RequireEncryption: +@@ -525,15 +573,23 @@ extern "C" int32_t CryptoNative_SetEncryptionPolicy(SSL_CTX* ctx, EncryptionPoli + + case EncryptionPolicy::AllowNoEncryption: + cipherString = SSL_TXT_AllIncludingNull; ++ clearSecLevel = true; + break; + + case EncryptionPolicy::NoEncryption: + cipherString = SSL_TXT_eNULL; ++ clearSecLevel = true; + break; + } + + assert(cipherString != nullptr); + ++ if (clearSecLevel) ++ { ++ // No minimum security policy, same as OpenSSL 1.0 ++ SSL_CTX_set_security_level(ctx, 0); ++ } ++ + return SSL_CTX_set_cipher_list(ctx, cipherString); + } + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp +index 3118c9aa2c..b51bb77575 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509.cpp +@@ -230,12 +230,22 @@ extern "C" X509Stack* CryptoNative_X509StoreCtxGetChain(X509_STORE_CTX* ctx) + + extern "C" X509Stack* CryptoNative_X509StoreCtxGetSharedUntrusted(X509_STORE_CTX* ctx) + { +- return ctx ? ctx->untrusted : nullptr; ++ if (ctx) ++ { ++ return X509_STORE_CTX_get0_untrusted(ctx); ++ } ++ ++ return nullptr; + } + + extern "C" X509* CryptoNative_X509StoreCtxGetTargetCert(X509_STORE_CTX* ctx) + { +- return ctx ? ctx->cert : nullptr; ++ if (ctx) ++ { ++ return X509_STORE_CTX_get0_cert(ctx); ++ } ++ ++ return nullptr; + } + + extern "C" X509VerifyStatusCode CryptoNative_X509StoreCtxGetError(X509_STORE_CTX* ctx) +@@ -302,7 +312,7 @@ extern "C" X509* CryptoNative_X509UpRef(X509* x509) + { + if (x509 != nullptr) + { +- CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509); ++ X509_up_ref(x509); + } + + return x509; +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp +index 2132a81836..cc11e654dd 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_root.cpp +@@ -2,6 +2,7 @@ + // The .NET Foundation licenses this file to you under the MIT license. + // See the LICENSE file in the project root for more information. + ++#include "pal_types.h" + #include "pal_x509_root.h" + + #include +diff --git a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs +index 47912ff085..8f870feae3 100644 +--- a/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs ++++ b/src/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/OpenSslCipher.cs +@@ -3,6 +3,7 @@ + // See the LICENSE file in the project root for more information. + + using System; ++using System.Buffers; + using System.Diagnostics; + using System.Security.Cryptography; + using Microsoft.Win32.SafeHandles; +@@ -49,6 +50,24 @@ namespace Internal.Cryptography + Debug.Assert(outputOffset >= 0); + Debug.Assert(output.Length - outputOffset >= count); + ++ // OpenSSL 1.1 does not allow partial overlap. ++ if (input == output && inputOffset != outputOffset) ++ { ++ byte[] tmp = ArrayPool.Shared.Rent(count); ++ ++ try ++ { ++ int written = CipherUpdate(input, inputOffset, count, tmp, 0); ++ Buffer.BlockCopy(tmp, 0, output, outputOffset, written); ++ return written; ++ } ++ finally ++ { ++ CryptographicOperations.ZeroMemory(tmp.AsSpan(0, count)); ++ ArrayPool.Shared.Return(tmp); ++ } ++ } ++ + return CipherUpdate(input, inputOffset, count, output, outputOffset); + } + +-- +2.20.1 + diff --git a/SOURCES/0004-Use-HMAC_CTX_free-instead-of-free-on-a-HMAC_CTX-3422.patch b/SOURCES/0004-Use-HMAC_CTX_free-instead-of-free-on-a-HMAC_CTX-3422.patch new file mode 100644 index 0000000..b19fc98 --- /dev/null +++ b/SOURCES/0004-Use-HMAC_CTX_free-instead-of-free-on-a-HMAC_CTX-3422.patch @@ -0,0 +1,30 @@ +From fc9d3560b4a84bab784574cfe9700125065713c3 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Sat, 22 Dec 2018 15:06:18 -0500 +Subject: [PATCH 4/7] Use HMAC_CTX_free() instead of free() on a HMAC_CTX* + (#34222) + +This is a leftover from before the OpenSSL 1.0/1.1 hybridization. There +was no HMAC_CTX_free() in 1.0. + +Fixes #34210 +--- + .../Unix/System.Security.Cryptography.Native/pal_hmac.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp +index 539dc07683..979750cb40 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_hmac.cpp +@@ -31,7 +31,7 @@ extern "C" HMAC_CTX* CryptoNative_HmacCreate(const uint8_t* key, int32_t keyLen, + + if (!ret) + { +- free(ctx); ++ HMAC_CTX_free(ctx); + return nullptr; + } + +-- +2.20.1 + diff --git a/SOURCES/0005-Prefer-OpenSSL-1.0.x-for-portable-builds.patch b/SOURCES/0005-Prefer-OpenSSL-1.0.x-for-portable-builds.patch new file mode 100644 index 0000000..8fbfa95 --- /dev/null +++ b/SOURCES/0005-Prefer-OpenSSL-1.0.x-for-portable-builds.patch @@ -0,0 +1,43 @@ +From 60e4274ff758af0d68ba585e7286a5cddb7c4778 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Thu, 10 Jan 2019 18:37:24 -0500 +Subject: [PATCH 5/7] Prefer OpenSSL 1.0.x for portable builds + +Future releases of .NET Core prefer OpenSSL 1.1.x. For the sake of +compatiblity, 2.x releases should prefer 1.0.x. +--- + .../opensslshim.cpp | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp +index 585f7ac23f..c98869a94e 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp ++++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.cpp +@@ -47,12 +47,6 @@ bool OpenLibrary() + libssl = dlopen(soName, RTLD_LAZY); + } + +- if (libssl == nullptr) +- { +- // Prefer OpenSSL 1.1.x +- libssl = dlopen("libssl.so.1.1", RTLD_LAZY); +- } +- + if (libssl == nullptr) + { + // Debian 9 has dropped support for SSLv3 and so they have bumped their soname. Let's try it +@@ -73,6 +67,11 @@ bool OpenLibrary() + libssl = dlopen("libssl.so.10", RTLD_LAZY); + } + ++ if (libssl == nullptr) ++ { ++ libssl = dlopen("libssl.so.1.1", RTLD_LAZY); ++ } ++ + return libssl != nullptr; + } + +-- +2.20.1 + diff --git a/SOURCES/0006-Check-for-the-specific-in-use-version-of-OpenSSL-whe.patch b/SOURCES/0006-Check-for-the-specific-in-use-version-of-OpenSSL-whe.patch new file mode 100644 index 0000000..9eedfa8 --- /dev/null +++ b/SOURCES/0006-Check-for-the-specific-in-use-version-of-OpenSSL-whe.patch @@ -0,0 +1,350 @@ +From dfa0c242cd9b329554971cf80c094e8f58d756e3 Mon Sep 17 00:00:00 2001 +From: Jeremy Barton +Date: Wed, 26 Sep 2018 15:35:35 -0700 +Subject: [PATCH 6/7] Check for the specific in-use version of OpenSSL when + working with libcurl + +Rather than check a generic 1.0/1.1, test for the specific library version that +the crypto shim has loaded. This makes things work when both libcurl +and the crypto shim are using OpenSSL 1.1 and also prevents a state where two +different copies of the library (at different patch versions) are utilized. +--- + .../Interop.Initialization.cs | 8 +-- + .../Interop.VersionInfo.cs | 44 +++++++++++- + .../Interop.OpenSslVersion.cs | 2 +- + .../src/System.Net.Http.csproj | 3 + + .../CurlHandler.SslProvider.Linux.cs | 8 +-- + .../FunctionalTests/HttpClientEKUTest.cs | 2 +- + ...ttpClientHandlerTest.ClientCertificates.cs | 14 +--- + ...ientHandlerTest.ServerCertificates.Unix.cs | 9 +-- + ...HttpClientHandlerTest.SslProtocols.Unix.cs | 3 +- + .../System.Net.Http.Functional.Tests.csproj | 3 +- + .../tests/FunctionalTests/TestHelper.cs | 69 +++++++++++++++++++ + 11 files changed, 130 insertions(+), 35 deletions(-) + +diff --git a/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.Initialization.cs b/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.Initialization.cs +index eef56ec0b3..d6bcc8df02 100644 +--- a/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.Initialization.cs ++++ b/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.Initialization.cs +@@ -26,11 +26,11 @@ internal static partial class Interop + #if !SYSNETHTTP_NO_OPENSSL + string opensslVersion = Interop.Http.GetSslVersionDescription(); + if (string.IsNullOrEmpty(opensslVersion) || +- opensslVersion.IndexOf(Interop.Http.OpenSsl10Description, StringComparison.OrdinalIgnoreCase) != -1) ++ opensslVersion.IndexOf(Interop.Http.OpenSslDescriptionPrefix, StringComparison.OrdinalIgnoreCase) != -1) + { +- // CURL uses OpenSSL which we must initialize first to guarantee thread-safety +- // Only initialize for OpenSSL/1.0, any newer versions may have mismatched +- // pointers, resulting in segfaults. ++ // CURL uses OpenSSL which we must initialize first to guarantee thread-safety. ++ // We'll wake up whatever OpenSSL we're going to run against, but might later determine that ++ // they aren't compatible. + CryptoInitializer.Initialize(); + } + #endif +diff --git a/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.VersionInfo.cs b/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.VersionInfo.cs +index 1899fd0af3..8175159b6f 100644 +--- a/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.VersionInfo.cs ++++ b/src/Common/src/Interop/Unix/System.Net.Http.Native/Interop.VersionInfo.cs +@@ -3,6 +3,7 @@ + // See the LICENSE file in the project root for more information. + + using System; ++using System.Diagnostics; + using System.Runtime.InteropServices; + + internal static partial class Interop +@@ -47,8 +48,49 @@ internal static partial class Interop + [DllImport(Libraries.HttpNative, EntryPoint = "HttpNative_GetSslVersionDescription")] + internal static extern string GetSslVersionDescription(); + +- internal const string OpenSsl10Description = "openssl/1.0"; ++ internal const string OpenSslDescriptionPrefix = "OpenSSL/"; + internal const string SecureTransportDescription = "SecureTransport"; + internal const string LibreSslDescription = "LibreSSL"; ++ ++#if !SYSNETHTTP_NO_OPENSSL ++ private static readonly Lazy s_requiredOpenSslDescription = ++ new Lazy(() => DetermineRequiredOpenSslDescription()); ++ ++ private static readonly Lazy s_hasMatchingOpenSsl = ++ new Lazy(() => RequiredOpenSslDescription == GetSslVersionDescription()); ++ ++ internal static string RequiredOpenSslDescription => s_requiredOpenSslDescription.Value; ++ internal static bool HasMatchingOpenSslVersion => s_hasMatchingOpenSsl.Value; ++ ++ private static string DetermineRequiredOpenSslDescription() ++ { ++ string versionDescription = Interop.OpenSsl.OpenSslVersionDescription(); ++ var version = versionDescription.AsSpan(); ++ ++ // OpenSSL version description looks like this: ++ // ++ // OpenSSL 1.1.1 FIPS 11 Sep 2018 ++ // ++ // libcurl's OpenSSL vtls backend ignores status in the version string. ++ // Major, minor, and fix are encoded (by libcurl) as unpadded hex ++ // (0 => "0", 15 => "f", 16 => "10"). ++ // ++ // Patch is encoded as in the way OpenSSL would do it. ++ ++ string prefix = "OpenSSL "; ++ if (version.StartsWith(prefix)) ++ { ++ version = version.Slice(prefix.Length).Trim(); ++ } ++ int end = version.IndexOf(" "); ++ if (end != -1) ++ { ++ version = version.Slice(0, end); ++ } ++ version = version.Trim(); ++ ++ return $"{OpenSslDescriptionPrefix}{version.ToString()}"; ++ } ++#endif + } + } +diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSslVersion.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSslVersion.cs +index 70805706ef..13c2339ce6 100644 +--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSslVersion.cs ++++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSslVersion.cs +@@ -12,7 +12,7 @@ internal static partial class Interop + private static Version s_opensslVersion; + + [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SSLEayVersion")] +- private static extern string OpenSslVersionDescription(); ++ internal static extern string OpenSslVersionDescription(); + + internal static Version OpenSslVersion + { +diff --git a/src/System.Net.Http/src/System.Net.Http.csproj b/src/System.Net.Http/src/System.Net.Http.csproj +index 66e5b8d5f8..34b4d22e15 100644 +--- a/src/System.Net.Http/src/System.Net.Http.csproj ++++ b/src/System.Net.Http/src/System.Net.Http.csproj +@@ -500,6 +500,9 @@ + + Common\Interop\Unix\System.Security.Cryptography.Native\Interop.Crypto.cs + ++ ++ Common\Interop\Unix\System.Security.Cryptography.Native\Interop.OpenSslVersion.cs ++ + + Common\Interop\Unix\System.Security.Cryptography.Native\Interop.Ssl.cs + +diff --git a/src/System.Net.Http/src/System/Net/Http/CurlHandler/CurlHandler.SslProvider.Linux.cs b/src/System.Net.Http/src/System/Net/Http/CurlHandler/CurlHandler.SslProvider.Linux.cs +index 55e583e137..2fdcde686d 100644 +--- a/src/System.Net.Http/src/System/Net/Http/CurlHandler/CurlHandler.SslProvider.Linux.cs ++++ b/src/System.Net.Http/src/System/Net/Http/CurlHandler/CurlHandler.SslProvider.Linux.cs +@@ -55,7 +55,7 @@ namespace System.Net.Http + + // Configure the options. Our best support is when targeting OpenSSL/1.0. For other backends, + // we fall back to a minimal amount of support, and may throw a PNSE based on the options requested. +- if (CurlSslVersionDescription.IndexOf(Interop.Http.OpenSsl10Description, StringComparison.OrdinalIgnoreCase) != -1) ++ if (Interop.Http.HasMatchingOpenSslVersion) + { + // Register the callback with libcurl. We need to register even if there's no user-provided + // server callback and even if there are no client certificates, because we support verifying +@@ -169,12 +169,12 @@ namespace System.Net.Http + { + if (certProvider != null) + { +- throw new PlatformNotSupportedException(SR.Format(SR.net_http_libcurl_clientcerts_notsupported_sslbackend, CurlVersionDescription, CurlSslVersionDescription, Interop.Http.OpenSsl10Description)); ++ throw new PlatformNotSupportedException(SR.Format(SR.net_http_libcurl_clientcerts_notsupported_sslbackend, CurlVersionDescription, CurlSslVersionDescription, Interop.Http.RequiredOpenSslDescription)); + } + + if (easy._handler.CheckCertificateRevocationList) + { +- throw new PlatformNotSupportedException(SR.Format(SR.net_http_libcurl_revocation_notsupported_sslbackend, CurlVersionDescription, CurlSslVersionDescription, Interop.Http.OpenSsl10Description)); ++ throw new PlatformNotSupportedException(SR.Format(SR.net_http_libcurl_revocation_notsupported_sslbackend, CurlVersionDescription, CurlSslVersionDescription, Interop.Http.RequiredOpenSslDescription)); + } + + if (easy._handler.ServerCertificateCustomValidationCallback != null) +@@ -187,7 +187,7 @@ namespace System.Net.Http + } + else + { +- throw new PlatformNotSupportedException(SR.Format(SR.net_http_libcurl_callback_notsupported_sslbackend, CurlVersionDescription, CurlSslVersionDescription, Interop.Http.OpenSsl10Description)); ++ throw new PlatformNotSupportedException(SR.Format(SR.net_http_libcurl_callback_notsupported_sslbackend, CurlVersionDescription, CurlSslVersionDescription, Interop.Http.RequiredOpenSslDescription)); + } + } + else +diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs +index c6badc770e..9ac90390e3 100644 +--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs ++++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientEKUTest.cs +@@ -22,7 +22,7 @@ namespace System.Net.Http.Functional.Tests + #if TargetsWindows + true; + #else +- Interop.Http.GetSslVersionDescription()?.StartsWith(Interop.Http.OpenSsl10Description, StringComparison.OrdinalIgnoreCase) ?? false; ++ TestHelper.NativeHandlerSupportsSslConfiguration(); + #endif + + private static bool CanTestCertificates => +diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs +index 78d0fdb09f..217726db64 100644 +--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs ++++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ClientCertificates.cs +@@ -319,19 +319,7 @@ namespace System.Net.Http.Functional.Tests + #if TargetsWindows + return true; + #else +- if (UseSocketsHttpHandler) +- { +- return true; +- } +- +- if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) +- { +- return false; +- } +- +- // For other Unix-based systems it's true if (and only if) the openssl backend +- // is used with libcurl. +- return (Interop.Http.GetSslVersionDescription()?.StartsWith(Interop.Http.OpenSsl10Description, StringComparison.OrdinalIgnoreCase) ?? false); ++ return TestHelper.NativeHandlerSupportsSslConfiguration(); + #endif + } + } +diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.Unix.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.Unix.cs +index d19a63f598..eb38f93615 100644 +--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.Unix.cs ++++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.ServerCertificates.Unix.cs +@@ -58,14 +58,7 @@ namespace System.Net.Http.Functional.Tests + return true; + } + +- if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) +- { +- return false; +- } +- +- // For other Unix-based systems it's true if (and only if) the openssl backend +- // is used with libcurl. +- return (Interop.Http.GetSslVersionDescription()?.StartsWith(Interop.Http.OpenSsl10Description, StringComparison.OrdinalIgnoreCase) ?? false); ++ return TestHelper.NativeHandlerSupportsSslConfiguration(); + } + } + +diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.Unix.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.Unix.cs +index 615f2cb4fa..e7631e3940 100644 +--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.Unix.cs ++++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.SslProtocols.Unix.cs +@@ -17,7 +17,6 @@ namespace System.Net.Http.Functional.Tests + public abstract partial class HttpClientHandler_SslProtocols_Test + { + private bool BackendSupportsSslConfiguration => +- UseSocketsHttpHandler || +- (Interop.Http.GetSslVersionDescription()?.StartsWith(Interop.Http.OpenSsl10Description, StringComparison.OrdinalIgnoreCase) ?? false); ++ UseSocketsHttpHandler || TestHelper.NativeHandlerSupportsSslConfiguration(); + } + } +diff --git a/src/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +index 68c87c2b6e..b3b9d2437d 100644 +--- a/src/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj ++++ b/src/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +@@ -5,6 +5,7 @@ + {C85CF035-7804-41FF-9557-48B7C948B58D} + $(DefineConstants);netcoreapp + $(DefineConstants);TargetsWindows ++ $(DefineConstants);SYSNETHTTP_NO_OPENSSL + true + + +@@ -169,4 +170,4 @@ + + + +- +\ No newline at end of file ++ +diff --git a/src/System.Net.Http/tests/FunctionalTests/TestHelper.cs b/src/System.Net.Http/tests/FunctionalTests/TestHelper.cs +index 9bf6f216d1..2e29128a92 100644 +--- a/src/System.Net.Http/tests/FunctionalTests/TestHelper.cs ++++ b/src/System.Net.Http/tests/FunctionalTests/TestHelper.cs +@@ -6,6 +6,8 @@ using System.Collections.Generic; + using System.Linq; + using System.Net.NetworkInformation; + using System.Net.Security; ++using System.Reflection; ++using System.Runtime.InteropServices; + using System.Security.Cryptography; + using System.Security.Cryptography.X509Certificates; + using System.Text; +@@ -107,5 +109,72 @@ namespace System.Net.Http.Functional.Tests + .Select(a => a.Address) + .Where(a => a.IsIPv6LinkLocal) + .FirstOrDefault(); ++ ++ public static void EnsureHttp2Feature(HttpClientHandler handler) ++ { ++ // All .NET Core implementations of HttpClientHandler have HTTP/2 enabled by default except when using ++ // SocketsHttpHandler. Right now, the HTTP/2 feature is disabled on SocketsHttpHandler unless certain ++ // AppContext switches or environment variables are set. To help with testing, we can enable the HTTP/2 ++ // feature for a specific handler instance by using reflection. ++ FieldInfo field_socketsHttpHandler = typeof(HttpClientHandler).GetField( ++ "_socketsHttpHandler", ++ BindingFlags.NonPublic | BindingFlags.Instance); ++ if (field_socketsHttpHandler == null) ++ { ++ // Not using .NET Core implementation, i.e. could be .NET Framework or UAP. ++ return; ++ } ++ ++ object _socketsHttpHandler = field_socketsHttpHandler.GetValue(handler); ++ if (_socketsHttpHandler == null) ++ { ++ // Not using SocketsHttpHandler, i.e. using WinHttpHandler or CurlHandler. ++ return; ++ } ++ ++ // Get HttpConnectionSettings object from SocketsHttpHandler. ++ Type type_SocketsHttpHandler = typeof(HttpClientHandler).Assembly.GetType("System.Net.Http.SocketsHttpHandler"); ++ FieldInfo field_settings = type_SocketsHttpHandler.GetField( ++ "_settings", ++ BindingFlags.NonPublic | BindingFlags.Instance); ++ Assert.NotNull(field_settings); ++ object _settings = field_settings.GetValue(_socketsHttpHandler); ++ Assert.NotNull(_settings); ++ ++ // Set _maxHttpVersion field to HTTP/2.0. ++ Type type_HttpConnectionSettings = typeof(HttpClientHandler).Assembly.GetType("System.Net.Http.HttpConnectionSettings"); ++ FieldInfo field_maxHttpVersion = type_HttpConnectionSettings.GetField( ++ "_maxHttpVersion", ++ BindingFlags.NonPublic | BindingFlags.Instance); ++ field_maxHttpVersion.SetValue(_settings, new Version(2, 0)); ++ } ++ ++ public static bool NativeHandlerSupportsSslConfiguration() ++ { ++#if TargetsWindows ++ return true; ++#else ++ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) ++ { ++ return false; ++ } ++ ++ // For other Unix-based systems it's true if (and only if) the currect openssl backend ++ // is used with libcurl. ++ bool hasAnyOpenSsl = ++ Interop.Http.GetSslVersionDescription()?.StartsWith(Interop.Http.OpenSslDescriptionPrefix, StringComparison.OrdinalIgnoreCase) ?? false; ++ ++ if (!hasAnyOpenSsl) ++ { ++ return false; ++ } ++ ++ // We're on an OpenSSL-based system, with an OpenSSL backend. ++ // Ask the product how it feels about this. ++ Type interopHttp = typeof(HttpClient).Assembly.GetType("Interop+Http"); ++ PropertyInfo hasMatchingOpenSslVersion = interopHttp.GetProperty("HasMatchingOpenSslVersion", BindingFlags.Static | BindingFlags.NonPublic); ++ return (bool)hasMatchingOpenSslVersion.GetValue(null); ++#endif ++ } + } + } +-- +2.20.1 + diff --git a/SOURCES/0007-Relax-the-OpenSSL-error-checking-code.patch b/SOURCES/0007-Relax-the-OpenSSL-error-checking-code.patch new file mode 100644 index 0000000..2b06932 --- /dev/null +++ b/SOURCES/0007-Relax-the-OpenSSL-error-checking-code.patch @@ -0,0 +1,28 @@ +From 15bfd45926678221a3191f092243cf88d89298e9 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Tue, 15 Jan 2019 11:00:03 -0500 +Subject: [PATCH 7/7] Relax the OpenSSL error checking code + +OpenSSL 1.0 and 1.1 have different messages for the errors, but the same +error code. So only check the error code, not the exact error message. + +This is a port of #30889. +--- + .../tests/CtorTests.cs | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs +index da6e2630c0..24c7361500 100644 +--- a/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs ++++ b/src/System.Security.Cryptography.X509Certificates/tests/CtorTests.cs +@@ -355,7 +355,6 @@ namespace System.Security.Cryptography.X509Certificates.Tests + else // Any Unix + { + Assert.Equal(0x0D07803A, ex.HResult); +- Assert.Equal("error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error", ex.Message); + } + } + +-- +2.20.1 + diff --git a/SOURCES/check-debug-symbols.py b/SOURCES/check-debug-symbols.py new file mode 100755 index 0000000..1e14800 --- /dev/null +++ b/SOURCES/check-debug-symbols.py @@ -0,0 +1,136 @@ +#!/usr/bin/python3 + +""" +Check debug symbols are present in shared object and can identify +code. + +It starts scanning from a directory and recursively scans all ELF +files found in it for various symbols to ensure all debuginfo is +present and nothing has been stripped. + +Usage: + +./check-debug-symbols /path/of/dir/to/scan/ + + +Example: + +./check-debug-symbols /usr/lib64 +""" + +# This technique was explained to me by Mark Wielaard (mjw). + +import collections +import os +import re +import subprocess +import sys + +ScanResult = collections.namedtuple('ScanResult', + 'file_name debug_info debug_abbrev file_symbols gnu_debuglink') + + +def scan_file(file): + "Scan the provided file and return a ScanResult containing results of the scan." + + # Test for .debug_* sections in the shared object. This is the main test. + # Stripped objects will not contain these. + readelf_S_result = subprocess.run(['eu-readelf', '-S', file], + stdout=subprocess.PIPE, encoding='utf-8', check=True) + has_debug_info = any(line for line in readelf_S_result.stdout.split('\n') if '] .debug_info' in line) + + has_debug_abbrev = any(line for line in readelf_S_result.stdout.split('\n') if '] .debug_abbrev' in line) + + # Test FILE symbols. These will most likely be removed by anyting that + # manipulates symbol tables because it's generally useless. So a nice test + # that nothing has messed with symbols. + def contains_file_symbols(line): + parts = line.split() + if len(parts) < 8: + return False + return \ + parts[2] == '0' and parts[3] == 'FILE' and parts[4] == 'LOCAL' and parts[5] == 'DEFAULT' and \ + parts[6] == 'ABS' and re.match(r'((.*/)?[-_a-zA-Z0-9]+\.(c|cc|cpp|cxx))?', parts[7]) + + readelf_s_result = subprocess.run(["eu-readelf", '-s', file], + stdout=subprocess.PIPE, encoding='utf-8', check=True) + has_file_symbols = any(line for line in readelf_s_result.stdout.split('\n') if contains_file_symbols(line)) + + # Test that there are no .gnu_debuglink sections pointing to another + # debuginfo file. There shouldn't be any debuginfo files, so the link makes + # no sense either. + has_gnu_debuglink = any(line for line in readelf_s_result.stdout.split('\n') if '] .gnu_debuglink' in line) + + return ScanResult(file, has_debug_info, has_debug_abbrev, has_file_symbols, has_gnu_debuglink) + +def is_elf(file): + result = subprocess.run(['file', file], stdout=subprocess.PIPE, encoding='utf-8', check=True) + return re.search('ELF 64-bit LSB (?:executable|shared object)', result.stdout) + +def scan_file_if_sensible(file): + if is_elf(file): + # print(file) + return scan_file(file) + return None + +def scan_dir(dir): + results = [] + for root, _, files in os.walk(dir): + for name in files: + result = scan_file_if_sensible(os.path.join(root, name)) + if result: + results.append(result) + return results + +def scan(file): + file = os.path.abspath(file) + if os.path.isdir(file): + return scan_dir(file) + elif os.path.isfile(file): + return scan_file_if_sensible(file) + +def is_bad_result(result): + return not result.debug_info or not result.debug_abbrev or not result.file_symbols or result.gnu_debuglink + +def print_scan_results(results, verbose): + # print(results) + for result in results: + file_name = result.file_name + found_issue = False + if not result.debug_info: + found_issue = True + print('error: missing .debug_info section in', file_name) + if not result.debug_abbrev: + found_issue = True + print('error: missing .debug_abbrev section in', file_name) + if not result.file_symbols: + found_issue = True + print('error: missing FILE symbols in', file_name) + if result.gnu_debuglink: + found_issue = True + print('error: unexpected .gnu_debuglink section in', file_name) + if verbose and not found_issue: + print('OK: ', file_name) + +def main(args): + verbose = False + files = [] + for arg in args: + if arg == '--verbose' or arg == '-v': + verbose = True + else: + files.append(arg) + + results = [] + for file in files: + results.extend(scan(file)) + + print_scan_results(results, verbose) + + if any(is_bad_result(result) for result in results): + return 1 + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/SOURCES/cli-telemetry-optout.patch b/SOURCES/cli-telemetry-optout.patch new file mode 100644 index 0000000..9b01f13 --- /dev/null +++ b/SOURCES/cli-telemetry-optout.patch @@ -0,0 +1,18 @@ +diff --git a/src/dotnet/Program.cs b/src/dotnet/Program.cs +index de1ebb9e6..6bbf479de 100644 +--- a/src/dotnet/Program.cs ++++ b/src/dotnet/Program.cs +@@ -28,6 +28,13 @@ public class Program + + public static int Main(string[] args) + { ++ // opt out of telemetry by default if the env var is unset ++ string telemetryValue = Environment.GetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT"); ++ if (String.IsNullOrEmpty(telemetryValue)) ++ { ++ Environment.SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1"); ++ } ++ + DebugHelper.HandleDebugSwitch(ref args); + + new MulticoreJitActivator().TryActivateMulticoreJit(); diff --git a/SOURCES/core-setup-4510-commit-id.patch b/SOURCES/core-setup-4510-commit-id.patch new file mode 100644 index 0000000..cf896ef --- /dev/null +++ b/SOURCES/core-setup-4510-commit-id.patch @@ -0,0 +1,48 @@ +From e02ee86364b9db3edc298a6a081004aa07473d09 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Wed, 29 Aug 2018 17:03:25 -0400 +Subject: [PATCH] Allow setting the commit id using /p:LatestCommit + +This is similar to how CommitCount is already supported. + +This lets consumers who are building outside a git repo, such as +source-build, set a commit id which is displayed by `dotnet --info` +and `strings dotnet | grep '@(#)'`. + +See: https://github.com/dotnet/source-build/issues/651 +See: https://github.com/dotnet/cli/pull/5945 +--- + dir.targets | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/dir.targets b/dir.targets +index 8d34872c6..59dc1ebde 100644 +--- a/dir.targets ++++ b/dir.targets +@@ -17,7 +17,8 @@ + + + +- ++ + + + +@@ -29,13 +30,13 @@ + + + +- ++ + ++ ConsoleToMSBuild="true"> + + + diff --git a/SOURCES/core-setup-pie.patch b/SOURCES/core-setup-pie.patch new file mode 100644 index 0000000..f2ef5ac --- /dev/null +++ b/SOURCES/core-setup-pie.patch @@ -0,0 +1,11 @@ +--- a/src/corehost/cli/exe/exe.cmake ++++ b/src/corehost/cli/exe/exe.cmake +@@ -44,6 +44,8 @@ + + add_executable(${DOTNET_HOST_EXE_NAME} ${SOURCES} ${RESOURCES}) + ++SET_TARGET_PROPERTIES(${DOTNET_HOST_EXE_NAME} PROPERTIES LINK_FLAGS -pie) ++ + if(NOT WIN32) + disable_pax_mprotect(${DOTNET_HOST_EXE_NAME}) + endif() diff --git a/SOURCES/coreclr-build-python3.patch b/SOURCES/coreclr-build-python3.patch new file mode 100644 index 0000000..1090a12 --- /dev/null +++ b/SOURCES/coreclr-build-python3.patch @@ -0,0 +1,38 @@ +From 7e0608fee5cacbf5bf7d0c3886e2fcb1a9d10754 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Wed, 9 Jan 2019 12:28:48 -0500 +Subject: [PATCH] Support building with python3 on unix (#19356) + +The windows build scripts try finding python in order of python3, +python2 and then python. The unix build scripts dont. They just try +python2 variants and then fail. This change makes brings them closer +together by letting users build using only python3. +--- + build.sh | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/build.sh b/build.sh +index a0b1742effb..14452ad5ac5 100755 +--- a/build.sh ++++ b/build.sh +@@ -7,9 +7,9 @@ export ghprbCommentBody= + + # resolve python-version to use + if [ "$PYTHON" == "" ] ; then +- if ! PYTHON=$(command -v python2.7 || command -v python2 || command -v python) ++ if ! PYTHON=$(command -v python3 || command -v python2 || command -v python) + then +- echo "Unable to locate build-dependency python2.x!" 1>&2 ++ echo "Unable to locate build-dependency python!" 1>&2 + exit 1 + fi + fi +@@ -17,7 +17,7 @@ fi + # useful in case of explicitly set option. + if ! command -v $PYTHON > /dev/null + then +- echo "Unable to locate build-dependency python2.x ($PYTHON)!" 1>&2 ++ echo "Unable to locate build-dependency python ($PYTHON)!" 1>&2 + exit 1 + fi + diff --git a/SOURCES/coreclr-cmake-python3.patch b/SOURCES/coreclr-cmake-python3.patch new file mode 100644 index 0000000..285cdc4 --- /dev/null +++ b/SOURCES/coreclr-cmake-python3.patch @@ -0,0 +1,26 @@ +From e7c6f87f54be723724a4c996d815d59b515b01a6 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Thu, 31 Jan 2019 16:09:35 -0500 +Subject: [PATCH] Update python lookup in CMakeLists.txt to match + build.(sh|cmd) (#22145) + +Use the same logic that's used in build.sh/build.cmd to lookup python: +first search for `python3`, then fall back to `python2` and finally to +`python`. +--- + CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 82c19a9cbaa..31b814f118d 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -37,7 +37,7 @@ OPTION(CLR_CMAKE_ENABLE_CODE_COVERAGE "Enable code coverage" OFF) + OPTION(CLR_CMAKE_WARNINGS_ARE_ERRORS "Warnings are errors" ON) + + # Ensure that python is present +-find_program(PYTHON NAMES python2.7 python2 python) ++find_program(PYTHON NAMES python3 python2 python) + if (PYTHON STREQUAL "PYTHON-NOTFOUND") + message(FATAL_ERROR "PYTHON not found: Please install Python 2.7.9 or later from https://www.python.org/downloads/") + endif() diff --git a/SOURCES/coreclr-mscorlib.patch b/SOURCES/coreclr-mscorlib.patch new file mode 100644 index 0000000..ca59e77 --- /dev/null +++ b/SOURCES/coreclr-mscorlib.patch @@ -0,0 +1,40 @@ +From 5164e76ce01fc36833a7f5e6fb7b1ec2f55c2262 Mon Sep 17 00:00:00 2001 +From: Omair Majid +Date: Wed, 1 Aug 2018 12:02:53 -0400 +Subject: [PATCH] Use the identified python when building + System.Private.CoreLib (#19043) + +build.sh and build.cmd contain logic to identify a working version of +python to use. System.Private.CoreLib ignores that and directly invokes +'python', which may not work, or even execute a different program. +--- + build.sh | 2 ++ + src/System.Private.CoreLib/System.Private.CoreLib.csproj | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/build.sh b/build.sh +index 091d6227caf..4002f2744c2 100755 +--- a/build.sh ++++ b/build.sh +@@ -22,6 +22,8 @@ then + exit 1 + fi + ++export PYTHON ++ + usage() + { + echo "Usage: $0 [BuildArch] [BuildType] [-verbose] [-coverage] [-cross] [-clangx.y] [-ninja] [-configureonly] [-skipconfigure] [-skipnative] [-skipmscorlib] [-skiptests] [-stripsymbols] [-ignorewarnings] [-cmakeargs] [-bindir]" +diff --git a/src/mscorlib/System.Private.CoreLib.csproj b/src/mscorlib/System.Private.CoreLib.csproj +index 9a2fc681703..0a02d3cffdf 100644 +--- a/src/mscorlib/System.Private.CoreLib.csproj ++++ b/src/mscorlib/System.Private.CoreLib.csproj +@@ -543,7 +543,7 @@ + + $(IntermediateOutputPath)..\cmake.definitions + +- ++ + + + true diff --git a/SOURCES/coreclr-pie.patch b/SOURCES/coreclr-pie.patch new file mode 100644 index 0000000..a711fc8 --- /dev/null +++ b/SOURCES/coreclr-pie.patch @@ -0,0 +1,11 @@ +--- a/src/debug/createdump/CMakeLists.txt ++++ b/src/debug/createdump/CMakeLists.txt +@@ -38,6 +38,8 @@ + main.cpp + ) + ++SET_TARGET_PROPERTIES(createdump PROPERTIES LINK_FLAGS -pie) ++ + target_link_libraries(createdump + createdump_lib + # share the PAL in the dac module diff --git a/SOURCES/corefx-32956-alpn.patch b/SOURCES/corefx-32956-alpn.patch new file mode 100644 index 0000000..88788b2 --- /dev/null +++ b/SOURCES/corefx-32956-alpn.patch @@ -0,0 +1,22 @@ +From 9b9697318e9990655ea878a28a00eda44fb615c2 Mon Sep 17 00:00:00 2001 +From: Jeremy Barton +Date: Mon, 22 Oct 2018 11:54:52 -0700 +Subject: [PATCH] Fix ALPN detection logic (for non-portable shim builds) + +--- + .../Unix/System.Security.Cryptography.Native/configure.cmake | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake b/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake +index cdc9f50f3c33..fac8c16343df 100644 +--- a/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake ++++ b/src/Native/Unix/System.Security.Cryptography.Native/configure.cmake +@@ -2,7 +2,7 @@ include(CheckLibraryExists) + include(CheckFunctionExists) + + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) +-set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY}) ++set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY}) + + check_function_exists( + EC_GF2m_simple_method diff --git a/SOURCES/corefx-optflags-support.patch b/SOURCES/corefx-optflags-support.patch new file mode 100644 index 0000000..2d0c603 --- /dev/null +++ b/SOURCES/corefx-optflags-support.patch @@ -0,0 +1,39 @@ +diff --git a/src/Native/Unix/CMakeLists.txt b/src/Native/Unix/CMakeLists.txt +index 7d804a1e54..717c2718d7 100644 +--- a/src/Native/Unix/CMakeLists.txt ++++ b/src/Native/Unix/CMakeLists.txt +@@ -25,7 +25,6 @@ add_compile_options(-fPIC) + add_compile_options(-I${CMAKE_CURRENT_SOURCE_DIR}/Common) + add_compile_options(-I${CMAKE_CURRENT_BINARY_DIR}/Common) + add_compile_options(-g) +-add_compile_options(-Werror) + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5) + add_compile_options(-Wno-unreachable-code) + endif () +diff --git a/src/Native/Unix/configure.cmake b/src/Native/Unix/configure.cmake +index f4a30ad6cb..f2db68402a 100644 +--- a/src/Native/Unix/configure.cmake ++++ b/src/Native/Unix/configure.cmake +@@ -27,6 +27,12 @@ else () + message(FATAL_ERROR "Unknown platform. Cannot define PAL_UNIX_NAME, used by RuntimeInformation.") + endif () + ++ ++set (PREVIOUS_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) ++set (CMAKE_CXX_FLAGS "") ++set (PREVIOUS_CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) ++set (CMAKE_C_FLAGS "") ++ + # We compile with -Werror, so we need to make sure these code fragments compile without warnings. + # Older CMake versions (3.8) do not assign the result of their tests, causing unused-value errors + # which are not distinguished from the test failing. So no error for that one. +@@ -698,6 +704,9 @@ endif() + + set (CMAKE_REQUIRED_LIBRARIES) + ++set (CMAKE_CXX_FLAGS "${PREVIOUS_CMAKE_CXX_FLAGS}") ++set (CMAKE_C_FLAGS "${PREVIOUS_CMAKE_C_FLAGS}") ++ + check_c_source_compiles( + " + #include diff --git a/SOURCES/corefx-rhel-runtime-ids.patch b/SOURCES/corefx-rhel-runtime-ids.patch new file mode 100644 index 0000000..9895dcd --- /dev/null +++ b/SOURCES/corefx-rhel-runtime-ids.patch @@ -0,0 +1,206 @@ +diff --git a/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json b/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json +index 7272b5de10..99fd8de923 100644 +--- a/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json ++++ b/pkg/Microsoft.NETCore.Platforms/runtime.compatibility.json +@@ -4923,6 +4923,123 @@ + "any", + "base" + ], ++ "rhel.8": [ ++ "rhel.8", ++ "rhel", ++ "linux", ++ "unix", ++ "any", ++ "base" ++ ], ++ "rhel.8-corert": [ ++ "rhel.8-corert", ++ "rhel.8", ++ "rhel-corert", ++ "rhel", ++ "linux-corert", ++ "linux", ++ "unix-corert", ++ "unix", ++ "corert", ++ "any", ++ "base" ++ ], ++ "rhel.8-x64": [ ++ "rhel.8-x64", ++ "rhel.8", ++ "rhel-x64", ++ "rhel", ++ "linux-x64", ++ "linux", ++ "unix-x64", ++ "unix", ++ "any", ++ "base" ++ ], ++ "rhel.8-x64-corert": [ ++ "rhel.8-x64-corert", ++ "rhel.8-corert", ++ "rhel.8-x64", ++ "rhel.8", ++ "rhel-x64-corert", ++ "rhel-corert", ++ "rhel-x64", ++ "rhel", ++ "linux-x64-corert", ++ "linux-corert", ++ "linux-x64", ++ "linux", ++ "unix-x64-corert", ++ "unix-corert", ++ "unix-x64", ++ "unix", ++ "corert", ++ "any", ++ "base" ++ ], ++ "rhel.8.0": [ ++ "rhel.8.0", ++ "rhel.8", ++ "rhel", ++ "linux", ++ "unix", ++ "any", ++ "base" ++ ], ++ "rhel.8.0-corert": [ ++ "rhel.8.0-corert", ++ "rhel.8.0", ++ "rhel.8-corert", ++ "rhel.8", ++ "rhel-corert", ++ "rhel", ++ "linux-corert", ++ "linux", ++ "unix-corert", ++ "unix", ++ "corert", ++ "any", ++ "base" ++ ], ++ "rhel.8.0-x64": [ ++ "rhel.8.0-x64", ++ "rhel.8.0", ++ "rhel.8-x64", ++ "rhel.8", ++ "rhel-x64", ++ "rhel", ++ "linux-x64", ++ "linux", ++ "unix-x64", ++ "unix", ++ "any", ++ "base" ++ ], ++ "rhel.8.0-x64-corert": [ ++ "rhel.8.0-x64-corert", ++ "rhel.8.0-corert", ++ "rhel.8.0-x64", ++ "rhel.8.0", ++ "rhel.8-x64-corert", ++ "rhel.8-corert", ++ "rhel.8-x64", ++ "rhel.8", ++ "rhel-x64-corert", ++ "rhel-corert", ++ "rhel-x64", ++ "rhel", ++ "linux-x64-corert", ++ "linux-corert", ++ "linux-x64", ++ "linux", ++ "unix-x64-corert", ++ "unix-corert", ++ "unix-x64", ++ "unix", ++ "corert", ++ "any", ++ "base" ++ ], + "sles": [ + "sles", + "linux", +diff --git a/pkg/Microsoft.NETCore.Platforms/runtime.json b/pkg/Microsoft.NETCore.Platforms/runtime.json +index e57332c62c..fc56341c7e 100644 +--- a/pkg/Microsoft.NETCore.Platforms/runtime.json ++++ b/pkg/Microsoft.NETCore.Platforms/runtime.json +@@ -1800,6 +1800,56 @@ + "rhel.7.5-x64-corert" + ] + }, ++ "rhel.8": { ++ "#import": [ ++ "rhel" ++ ] ++ }, ++ "rhel.8-corert": { ++ "#import": [ ++ "rhel.8", ++ "rhel-corert" ++ ] ++ }, ++ "rhel.8-x64": { ++ "#import": [ ++ "rhel.8", ++ "rhel-x64" ++ ] ++ }, ++ "rhel.8-x64-corert": { ++ "#import": [ ++ "rhel.8-corert", ++ "rhel.8-x64", ++ "rhel.8", ++ "rhel-x64-corert" ++ ] ++ }, ++ "rhel.8.0": { ++ "#import": [ ++ "rhel.8" ++ ] ++ }, ++ "rhel.8.0-corert": { ++ "#import": [ ++ "rhel.8.0", ++ "rhel.8-corert" ++ ] ++ }, ++ "rhel.8.0-x64": { ++ "#import": [ ++ "rhel.8.0", ++ "rhel.8-x64" ++ ] ++ }, ++ "rhel.8.0-x64-corert": { ++ "#import": [ ++ "rhel.8.0-corert", ++ "rhel.8.0-x64", ++ "rhel.8.0", ++ "rhel.8-x64-corert" ++ ] ++ }, + "sles": { + "#import": [ + "linux" +diff --git a/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props b/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props +index cc93f8bf91..21f6109824 100644 +--- a/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props ++++ b/pkg/Microsoft.NETCore.Platforms/runtimeGroups.props +@@ -103,6 +103,12 @@ + 7;7.0;7.1;7.2;7.3;7.4;7.5;7.6 + + ++ ++ linux ++ x64 ++ 8;8.0 ++ ++ + + linux + x64 diff --git a/SOURCES/dotnet.sh b/SOURCES/dotnet.sh new file mode 100644 index 0000000..718d895 --- /dev/null +++ b/SOURCES/dotnet.sh @@ -0,0 +1,7 @@ + +# Add dotnet tools directory to PATH +DOTNET_TOOLS_PATH="$HOME/.dotnet/tools" +case "$PATH" in + *"$DOTNET_TOOLS_PATH"* ) true ;; + * ) PATH="$PATH:$DOTNET_TOOLS_PATH" ;; +esac diff --git a/SPECS/dotnet.spec b/SPECS/dotnet.spec new file mode 100644 index 0000000..b7a3de5 --- /dev/null +++ b/SPECS/dotnet.spec @@ -0,0 +1,439 @@ +# Avoid provides/requires from private libraries +%global privlibs libhostfxr +%global privlibs %{privlibs}|libclrjit +%global privlibs %{privlibs}|libcoreclr +%global privlibs %{privlibs}|libcoreclrtraceptprovider +%global privlibs %{privlibs}|libdbgshim +%global privlibs %{privlibs}|libhostpolicy +%global privlibs %{privlibs}|libmscordaccore +%global privlibs %{privlibs}|libmscordbi +%global privlibs %{privlibs}|libsos +%global privlibs %{privlibs}|libsosplugin +%global __provides_exclude ^(%{privlibs})\\.so +%global __requires_exclude ^(%{privlibs})\\.so + +# Filter flags not supported by clang/dotnet: +# -fcf-protection is not supported by clang +# -fstack-clash-protection is not supported by clang +# -specs= is not supported by clang +# -fpie is added manually instead of via -specs +%global dotnet_cflags %(echo %optflags | sed -e 's/-fcf-protection//' | sed -e 's/-fstack-clash-protection//' | sed -re 's/-specs=[^ ]*//g') +%global dotnet_ldflags %(echo %{__global_ldflags} | sed -re 's/-specs=[^ ]*//g') + +%if 0%{?fedora} +%global use_bundled_libunwind 0 +%else +%global use_bundled_libunwind 1 +%endif + +%global simple_name dotnet + +%global host_version 2.1.8 +%global runtime_version 2.1.8 +%global sdk_version 2.1.504 + +Name: dotnet +Version: %{sdk_version} +Release: 1%{?dist} +Summary: .NET Core CLI tools and runtime +License: MIT and ASL 2.0 and BSD +URL: https://github.com/dotnet/ + +# The source is generated on a RHEL box via: +# - git clone https://github.com/dotnet/source-build +# - git checkout v%%{sdk_version} +# - set environment variables + tweak sources to build +# - ./build-source-tarball.sh dotnet-%%{sdk_version} +# - tar cvzf dotnet-%%{sdk_version}.tar.gz dotnet-%%{sdk_version} + +Source0: dotnet-v%{runtime_version}.tar.gz +Source1: check-debug-symbols.py +Source2: dotnet.sh + +# This is https://github.com/dotnet/corefx/pull/34443 +Patch1: 0001-NetFX-compatibility-fixes-for-X500DistinguishedName.patch +Patch2: 0002-Drop-pal_asn1_print-in-favor-of-the-managed-code.patch +Patch3: 0003-Add-hybrid-support-for-OpenSSL-1.0-and-1.1.patch +Patch4: 0004-Use-HMAC_CTX_free-instead-of-free-on-a-HMAC_CTX-3422.patch +Patch5: 0005-Prefer-OpenSSL-1.0.x-for-portable-builds.patch +Patch6: 0006-Check-for-the-specific-in-use-version-of-OpenSSL-whe.patch +Patch7: 0007-Relax-the-OpenSSL-error-checking-code.patch + +Patch10: corefx-optflags-support.patch +Patch11: corefx-32956-alpn.patch +Patch12: corefx-rhel-runtime-ids.patch + +Patch100: coreclr-build-python3.patch +Patch101: coreclr-cmake-python3.patch +Patch102: coreclr-mscorlib.patch +Patch103: coreclr-pie.patch + +Patch300: core-setup-4510-commit-id.patch +Patch301: core-setup-pie.patch + +Patch400: cli-telemetry-optout.patch + +ExclusiveArch: x86_64 + +BuildRequires: llvm-toolset-6.0-clang +BuildRequires: cmake +# Bootstrap SDK needs OpenSSL 1.0 to run, but we can build and then +# run with either OpenSSL 1.0 or 1.1 +%if 0%{?fedora} >= 26 || 0%{?rhel} >= 8 +BuildRequires: compat-openssl10 +%endif +BuildRequires: git +BuildRequires: glibc-langpack-en +BuildRequires: hostname +BuildRequires: krb5-devel +BuildRequires: libcurl-devel +BuildRequires: libicu-devel +%if ! %{use_bundled_libunwind} +BuildRequires: libunwind-devel +%endif +BuildRequires: llvm-toolset-6.0-lldb-devel +BuildRequires: llvm-toolset-6.0-llvm +BuildRequires: lttng-ust-devel +BuildRequires: make +BuildRequires: openssl-devel +BuildRequires: python3 +BuildRequires: strace +BuildRequires: zlib-devel + +Requires: %{simple_name}-sdk-2.1%{?_isa} >= %{sdk_version}-%{release} + +%description +.NET Core is a fast, lightweight and modular platform for creating +cross platform applications that work on Linux, macOS and Windows. + +It particularly focuses on creating console applications, web +applications and micro-services. + +.NET Core contains a runtime conforming to .NET Standards a set of +framework libraries, an SDK containing compilers and a 'dotnet' +application to drive everything. + + +%package -n %{simple_name}-host + +Version: %{host_version} +Summary: .NET command line launcher + +%description -n %{simple_name}-host +The .NET Core host is a command line program that runs a standalone +.NET core application or launches the SDK. + +.NET Core is a fast, lightweight and modular platform for creating +cross platform applications that work on Linux, Mac and Windows. + +It particularly focuses on creating console applications, web +applications and micro-services. + + +%package -n %{simple_name}-host-fxr-2.1 + +Version: %{host_version} +Summary: .NET Core command line host resolver + +# Theoretically any version of the host should work. But lets aim for the one +# provided by this package, or from a newer version of .NET Core +Requires: %{simple_name}-host%{?_isa} >= %{host_version}-%{release} + +%description -n %{simple_name}-host-fxr-2.1 +The .NET Core host resolver contains logic to resolve and select the +right version of the .NET Core SDK or runtime to use. + +.NET Core is a fast, lightweight and modular platform for creating +cross platform applications that work on Linux, Mac and Windows. + +It particularly focuses on creating console applications, web +applications and micro-services. + +%package -n %{simple_name}-runtime-2.1 + +Version: %{runtime_version} +Summary: NET Core 2.1 runtime + +Requires: %{simple_name}-host-fxr-2.1%{?_isa} >= %{host_version}-%{release} + +# libicu is dlopen()ed +Requires: libicu + +%description -n %{simple_name}-runtime-2.1 +The .NET Core runtime contains everything needed to run .NET Core applications. +It includes a high performance Virtual Machine as well as the framework +libraries used by .NET Core applications. + +.NET Core is a fast, lightweight and modular platform for creating +cross platform applications that work on Linux, Mac and Windows. + +It particularly focuses on creating console applications, web +applications and micro-services. + +%package -n %{simple_name}-sdk-2.1 + +Version: %{sdk_version} +Summary: .NET Core 2.1 Software Development Kit + +Requires: %{simple_name}-sdk-2.1.5xx%{?_isa} >= %{sdk_version}-%{release} + +%description -n %{simple_name}-sdk-2.1 +The .NET Core SDK is a collection of command line applications to +create, build, publish and run .NET Core applications. + +.NET Core is a fast, lightweight and modular platform for creating +cross platform applications that work on Linux, Mac and Windows. + +It particularly focuses on creating console applications, web +applications and micro-services. + +%package -n %{simple_name}-sdk-2.1.5xx + +Version: %{sdk_version} +Summary: .NET Core 2.1.5xx Software Development Kit + +Requires: %{simple_name}-runtime-2.1%{?_isa} >= %{runtime_version}-%{release} + +%description -n %{simple_name}-sdk-2.1.5xx +The .NET Core SDK is a collection of command line applications to +create, build, publish and run .NET Core applications. + +.NET Core is a fast, lightweight and modular platform for creating +cross platform applications that work on Linux, Mac and Windows. + +It particularly focuses on creating console applications, web +applications and micro-services. + +%prep +%setup -q -n %{simple_name}-v%{runtime_version} + +# Disable warnings +sed -i 's|skiptests|skiptests ignorewarnings|' repos/coreclr.proj + +# Fix bad hardcoded path in build +sed -i 's|/usr/share/dotnet|%{_libdir}/%{simple_name}|' src/core-setup/src/corehost/common/pal.unix.cpp + +pushd src/corefx +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 + +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +popd + +pushd src/coreclr +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +popd + +pushd src/core-setup +%patch300 -p1 +%patch301 -p1 +popd + +pushd src/cli +%patch400 -p1 +popd + +%if %{use_bundled_libunwind} +# Use bundled libunwind +sed -i 's|-DCLR_CMAKE_USE_SYSTEM_LIBUNWIND=TRUE|-DCLR_CMAKE_USE_SYSTEM_LIBUNWIND=FALSE|' repos/coreclr.proj +%endif + + +%build +scl enable llvm-toolset-6.0 - < - 2.1.504-1 +- Update to .NET Core Runtime 2.1.8 and SDK 2.1.504 +- Sync with Fedora copr spec file +- Resolves: RHBZ#1646713 + +* Fri Oct 12 2018 Omair Majid - 2.1.403-4 +- Disable telemetry via code, not just environment variable +- Resolves: rhbz#1638093 + +* Thu Oct 11 2018 Omair Majid - 2.1.403-3 +- Disable telemetry by default +- Resolves: rhbz#1638093 + +* Wed Oct 10 2018 Omair Majid - 2.1.403-2 +- Target the latest ASP.NET Core version instead of 2.1.1 +- Resolves: rhbz#1636585 + +* Thu Oct 04 2018 Omair Majid - 2.1.403-1 +- Update to .NET Core Runtime 2.1.5 and SDK 2.1.403 +- Resolves: rhbz#1634182 + +* Mon Oct 01 2018 Omair Majid - 2.1.402-5 +- Backport fix to correct order of SSL_CERT_FILE and SSL_CERT_DIR lookup +- Resolves: rhbz#1633742 + +* Thu Sep 27 2018 Omair Majid - 2.1.402-4 +- Add ~/.dotnet/tools to $PATH to make it easier to use dotnet tools +- Resolves: rhbz#1630439 + +* Tue Sep 25 2018 Omair Majid - 2.1.402-3 +- Update .NET Core Runtime 2.1.4 and SDK 2.1.402 +- Resolves: rhbz#1628997 + +* Tue Sep 11 2018 Omair Majid - 2.1.401-3 +- Use standard flags to build .NET Core +- Resolves: rhbz#1624105 + +* Tue Sep 11 2018 Omair Majid - 2.1.401-2 +- Bundle libunwind +- Resolves: rhbz#1626285 + +* Fri Aug 17 2018 Omair Majid - 2.1.401-1 +- Update .NET Core Runtime 2.1.3 and SDK 2.1.401 +- Drop upstreamed patches + +* Mon Aug 06 2018 Omair Majid - 2.1.302-1 +- Initial build. +- Un-SCLized the package. + +* Wed Jul 4 2018 Omair Majid - 2.1.302-1 +- Update to .NET Core Runtime 2.1.2 and SDK 2.1.302 + +* Wed Jun 20 2018 Omair Majid - 2.1.301-5 +- Add sdk-2.1.3xx subpackage + +* Tue Jun 19 2018 Omair Majid - 2.1.301-4 +- Rebuild to pick up new lttng-ust + +* Tue Jun 19 2018 Omair Majid - 2.1.301-3 +- Add workaround for unreadable system certificates +- Resolves: rhbz#1588099 + +* Tue Jun 19 2018 Omair Majid - 2.1.301-2 +- Add updated man pages +- Resolves: rhbz#1584790 + +* Thu Jun 14 2018 Omair Majid - 2.1.301-1 +- Update to .NET Core SDK 2.1.301 + +* Wed May 30 2018 Omair Majid - 2.1.300-7 +- Explicitly require a modified libcurl + +* Tue May 29 2018 Omair Majid - 2.1.300-6 +- Install bash completions in %%{_root_datadir} + +* Mon May 28 2018 Omair Majid - 2.1.300-5 +- Add provides for dotnet-sdk-2.1.3xx + +* Mon May 28 2018 Omair Majid - 2.1.300-4 +- Remove patch for ASP.NET Core templates. No longer needed for 2.1. + +* Fri May 25 2018 Omair Majid - 2.1.300-3 +- Remove net46 symlink + +* Thu May 24 2018 Omair Majid - 2.1.300-2 +- Rebuild to pick up updated dependencies + +* Thu May 24 2018 Omair Majid - 2.1.300-1 +- New package. Import from Fedora (DotNet SIG package).