| |
@@ -0,0 +1,724 @@
|
| |
+ From 7f5ccbde792c7fd94ec27c33861ae1c3118ecf93 Mon Sep 17 00:00:00 2001
|
| |
+ From: Filip Navara <filip.navara@gmail.com>
|
| |
+ 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 @@
|
| |
+ <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs">
|
| |
+ <Link>Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs</Link>
|
| |
+ </Compile>
|
| |
+ - <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs">
|
| |
+ - <Link>Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs</Link>
|
| |
+ - </Compile>
|
| |
+ <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs">
|
| |
+ <Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link>
|
| |
+ </Compile>
|
| |
+ 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 @@
|
| |
+ <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs">
|
| |
+ <Link>Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs</Link>
|
| |
+ </Compile>
|
| |
+ - <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs">
|
| |
+ - <Link>Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs</Link>
|
| |
+ - </Compile>
|
| |
+ <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs">
|
| |
+ <Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link>
|
| |
+ </Compile>
|
| |
+ 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 @@
|
| |
+ <Reference Include="System.Security.Cryptography.Encoding" />
|
| |
+ <Reference Include="System.Security.Cryptography.Primitives" />
|
| |
+ <Reference Include="System.Threading" />
|
| |
+ + <Reference Include="System.Text.Encoding.Extensions" />
|
| |
+ </ItemGroup>
|
| |
+ <ItemGroup Condition="'$(TargetsUnix)' == 'true'">
|
| |
+ <Reference Include="System.Runtime.Numerics" />
|
| |
+ 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 @@
|
| |
+ <Reference Include="System.Runtime.Extensions" />
|
| |
+ <Reference Include="System.Runtime.InteropServices" />
|
| |
+ <Reference Include="System.Security.Cryptography.Primitives" />
|
| |
+ + <Reference Include="System.Text.Encoding.Extensions" />
|
| |
+ </ItemGroup>
|
| |
+ <ItemGroup Condition=" '$(TargetsOSX)' == 'true' ">
|
| |
+ <Reference Include="System.Runtime.Numerics" />
|
| |
+ 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 @@
|
| |
+ <Reference Include="System.Security.Cryptography.Algorithms" />
|
| |
+ <Reference Include="System.Security.Cryptography.Encoding" />
|
| |
+ <Reference Include="System.Security.Cryptography.Primitives" />
|
| |
+ + <Reference Include="System.Text.Encoding.Extensions" />
|
| |
+ <Reference Include="System.Threading" />
|
| |
+ </ItemGroup>
|
| |
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
| |
+ 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 @@
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\PkcsFormatReader.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\SingleCertLoader.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\StorePal.cs" />
|
| |
+ - <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.OpenSslDecode.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\X509Pal.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\X509Persistence.cs" />
|
| |
+ <Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
|
| |
+ @@ -223,9 +222,6 @@
|
| |
+ <Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Name.cs">
|
| |
+ <Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Name.cs</Link>
|
| |
+ </Compile>
|
| |
+ - <Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.X509NameEntry.cs">
|
| |
+ - <Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509NameEntry.cs</Link>
|
| |
+ - </Compile>
|
| |
+ <Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Stack.cs">
|
| |
+ <Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Stack.cs</Link>
|
| |
+ </Compile>
|
| |
+ @@ -274,9 +270,6 @@
|
| |
+ <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs">
|
| |
+ <Link>Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs</Link>
|
| |
+ </Compile>
|
| |
+ - <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs">
|
| |
+ - <Link>Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs</Link>
|
| |
+ - </Compile>
|
| |
+ <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs">
|
| |
+ <Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link>
|
| |
+ </Compile>
|
| |
+ @@ -390,7 +383,6 @@
|
| |
+ <Compile Include="Internal\Cryptography\Pal.OSX\StorePal.ExportPal.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.OSX\StorePal.LoaderPal.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.OSX\X509Pal.cs" />
|
| |
+ - <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.ManagedDecode.cs" />
|
| |
+ </ItemGroup>
|
| |
+ <ItemGroup Condition=" '$(TargetsUnix)' == 'true'">
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\CertificatePolicy.cs" />
|
| |
+ @@ -398,6 +390,7 @@
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\ManagedCertificateFinder.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\ManagedX509ExtensionProcessor.cs" />
|
| |
+ <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.cs" />
|
| |
+ + <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.ManagedDecode.cs" />
|
| |
+ </ItemGroup>
|
| |
+ <ItemGroup>
|
| |
+ <Reference Include="System.Buffers" />
|
| |
+ @@ -417,6 +410,7 @@
|
| |
+ <Reference Include="System.Security.Cryptography.Algorithms" />
|
| |
+ <Reference Include="System.Security.Cryptography.Encoding" />
|
| |
+ <Reference Include="System.Security.Cryptography.Primitives" />
|
| |
+ + <Reference Include="System.Text.Encoding.Extensions" />
|
| |
+ <Reference Include="System.Threading" />
|
| |
+ </ItemGroup>
|
| |
+ <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
|
| |
+ 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
|
| |
+
|
| |
Also, sync with the 2.1 RPM.
Build: https://copr.fedorainfracloud.org/coprs/g/dotnet-sig/dotnet/build/849735/