diff --git a/eng/Versions.props b/eng/Versions.props index 7704ae5bb3b055..b7d96c21a10f90 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -140,7 +140,7 @@ 1.0.0-prerelease.22415.6 1.0.0-prerelease.22415.6 - 16.11.23-beta1.23063.1 + 16.11.27-beta1.23180.1 2.0.0-beta4.22355.1 3.0.3 2.1.0 diff --git a/src/coreclr/dlls/mscoree/CMakeLists.txt b/src/coreclr/dlls/mscoree/CMakeLists.txt index dc22c27a0957e9..785655763d5d91 100644 --- a/src/coreclr/dlls/mscoree/CMakeLists.txt +++ b/src/coreclr/dlls/mscoree/CMakeLists.txt @@ -11,7 +11,7 @@ set(CLR_SOURCES if(CLR_CMAKE_TARGET_WIN32) list(APPEND CLR_SOURCES - delayloadhook.cpp + ${CLR_SRC_NATIVE_DIR}/libs/Common/delayloadhook_windows.cpp Native.rc ) diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index e6a1f86114c4e8..76b57204df42cf 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -2311,26 +2311,17 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) "reachable or needs to be reimplemented for CoreCLR!"); } - // We're going to be working with Windows PDB format symbols. Attempt to CoCreate the symbol binder. - // CoreCLR supports not having a symbol reader installed, so CoCreate searches the PATH env var - // and then tries coreclr dll location. - // On desktop, the framework installer is supposed to install diasymreader.dll as well - // and so this shouldn't happen. - hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, NATIVE_SYMBOL_READER_DLL, IID_ISymUnmanagedBinder, (void**)&pBinder, NULL); + PathString symbolReaderPath; + hr = GetClrModuleDirectory(symbolReaderPath); if (FAILED(hr)) { - PathString symbolReaderPath; - hr = GetClrModuleDirectory(symbolReaderPath); - if (FAILED(hr)) - { - RETURN (NULL); - } - symbolReaderPath.Append(NATIVE_SYMBOL_READER_DLL); - hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, symbolReaderPath.GetUnicode(), IID_ISymUnmanagedBinder, (void**)&pBinder, NULL); - if (FAILED(hr)) - { - RETURN (NULL); - } + RETURN (NULL); + } + symbolReaderPath.Append(NATIVE_SYMBOL_READER_DLL); + hr = FakeCoCreateInstanceEx(CLSID_CorSymBinder_SxS, symbolReaderPath.GetUnicode(), IID_ISymUnmanagedBinder, (void**)&pBinder, NULL); + if (FAILED(hr)) + { + RETURN (NULL); } LOG((LF_CORDB, LL_INFO10, "M::GISUR: Created binder\n")); diff --git a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs index 85c0697114db3c..b20fa4e016073c 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Asn1/Pkcs12/PfxAsn.manual.cs @@ -2,12 +2,23 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Formats.Asn1; +using System.Security.Cryptography.Asn1.Pkcs7; using System.Security.Cryptography.Pkcs; +using Internal.Cryptography; + +#if BUILDING_PKCS +using Helpers = Internal.Cryptography.PkcsHelpers; +#endif namespace System.Security.Cryptography.Asn1.Pkcs12 { internal partial struct PfxAsn { + private const int MaxIterationWork = 300_000; + private static ReadOnlySpan EmptyPassword => ""; // don't use ReadOnlySpan.Empty because it will get confused with default. + private static ReadOnlySpan NullPassword => default; + internal bool VerifyMac( ReadOnlySpan macPassword, ReadOnlySpan authSafeContents) @@ -84,5 +95,245 @@ internal bool VerifyMac( MacData.Value.Mac.Digest.Span); } } + + internal ulong CountTotalIterations() + { + checked + { + ulong count = 0; + + // RFC 7292 section 4.1: + // the contentType field of authSafe shall be of type data + // or signedData. The content field of the authSafe shall, either + // directly (data case) or indirectly (signedData case), contain a BER- + // encoded value of type AuthenticatedSafe. + // We don't support authSafe that is signedData, so enforce that it's just data. + if (AuthSafe.ContentType != Oids.Pkcs7Data) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + ReadOnlyMemory authSafeContents = Helpers.DecodeOctetStringAsMemory(AuthSafe.Content); + AsnValueReader outerAuthSafe = new AsnValueReader(authSafeContents.Span, AsnEncodingRules.BER); // RFC 7292 PDU says BER + AsnValueReader authSafeReader = outerAuthSafe.ReadSequence(); + outerAuthSafe.ThrowIfNotEmpty(); + + bool hasSeenEncryptedInfo = false; + + while (authSafeReader.HasData) + { + ContentInfoAsn.Decode(ref authSafeReader, authSafeContents, out ContentInfoAsn contentInfo); + + ReadOnlyMemory contentData; + ArraySegment? rentedData = null; + + try + { + if (contentInfo.ContentType != Oids.Pkcs7Data) + { + if (contentInfo.ContentType == Oids.Pkcs7Encrypted) + { + if (hasSeenEncryptedInfo) + { + // We will process at most one encryptedData ContentInfo. This is the most typical scenario where + // certificates are stored in an encryptedData ContentInfo, and keys are shrouded in a data ContentInfo. + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword); + } + + ArraySegment content = DecryptContentInfo(contentInfo, out uint iterations); + contentData = content; + rentedData = content; + hasSeenEncryptedInfo = true; + count += iterations; + } + else + { + // Not a common scenario. It's not data or encryptedData, so they need to go through the + // regular PKCS12 loader. + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword); + } + } + else + { + contentData = Helpers.DecodeOctetStringAsMemory(contentInfo.Content); + } + + AsnValueReader outerSafeBag = new AsnValueReader(contentData.Span, AsnEncodingRules.BER); + AsnValueReader safeBagReader = outerSafeBag.ReadSequence(); + outerSafeBag.ThrowIfNotEmpty(); + + while (safeBagReader.HasData) + { + SafeBagAsn.Decode(ref safeBagReader, contentData, out SafeBagAsn bag); + + // We only need to count iterations on PKCS8ShroudedKeyBag. + // * KeyBag is PKCS#8 PrivateKeyInfo and doesn't do iterations. + // * CertBag, either for x509Certificate or sdsiCertificate don't do iterations. + // * CRLBag doesn't do iterations. + // * SecretBag doesn't do iteations. + // * Nested SafeContents _can_ do iterations, but Windows ignores it. So we will ignore it too. + if (bag.BagId == Oids.Pkcs12ShroudedKeyBag) + { + AsnValueReader pkcs8ShroudedKeyReader = new AsnValueReader(bag.BagValue.Span, AsnEncodingRules.BER); + EncryptedPrivateKeyInfoAsn.Decode( + ref pkcs8ShroudedKeyReader, + bag.BagValue, + out EncryptedPrivateKeyInfoAsn epki); + + count += IterationsFromParameters(epki.EncryptionAlgorithm); + } + } + } + finally + { + if (rentedData.HasValue) + { + CryptoPool.Return(rentedData.Value); + } + } + } + + if (MacData.HasValue) + { + if (MacData.Value.IterationCount < 0) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + count += (uint)MacData.Value.IterationCount; + } + + return count; + } + } + + private static ArraySegment DecryptContentInfo(ContentInfoAsn contentInfo, out uint iterations) + { + EncryptedDataAsn encryptedData = EncryptedDataAsn.Decode(contentInfo.Content, AsnEncodingRules.BER); + + if (encryptedData.Version != 0 && encryptedData.Version != 2) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + // The encrypted contentInfo can only wrap a PKCS7 data. + if (encryptedData.EncryptedContentInfo.ContentType != Oids.Pkcs7Data) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + if (!encryptedData.EncryptedContentInfo.EncryptedContent.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + iterations = IterationsFromParameters(encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm); + + // This encryptData is encrypted with more rounds than we are willing to process. Bail out of the whole thing. + if (iterations > MaxIterationWork) + { + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword); + } + + int encryptedValueLength = encryptedData.EncryptedContentInfo.EncryptedContent.Value.Length; + byte[] destination = CryptoPool.Rent(encryptedValueLength); + int written = 0; + + try + { + try + { + written = PasswordBasedEncryption.Decrypt( + in encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm, + EmptyPassword, + default, + encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span, + destination); + } + catch + { + // If empty password didn't work, try null password. + written = PasswordBasedEncryption.Decrypt( + in encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm, + NullPassword, + default, + encryptedData.EncryptedContentInfo.EncryptedContent.Value.Span, + destination); + } + } + finally + { + if (written == 0) + { + // This means the decryption operation failed and destination could contain + // partial data. Clear it to be hygienic. + CryptographicOperations.ZeroMemory(destination); + } + } + + return new ArraySegment(destination, 0, written); + } + + private static uint IterationsFromParameters(in AlgorithmIdentifierAsn algorithmIdentifier) + { + switch (algorithmIdentifier.Algorithm) + { + case Oids.PasswordBasedEncryptionScheme2: + if (!algorithmIdentifier.Parameters.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + PBES2Params pbes2Params = PBES2Params.Decode(algorithmIdentifier.Parameters.Value, AsnEncodingRules.BER); + + // PBES2 only defines PKBDF2 for now. See RFC 8018 A.4 + if (pbes2Params.KeyDerivationFunc.Algorithm != Oids.Pbkdf2) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + if (!pbes2Params.KeyDerivationFunc.Parameters.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + Pbkdf2Params pbkdf2Params = Pbkdf2Params.Decode(pbes2Params.KeyDerivationFunc.Parameters.Value, AsnEncodingRules.BER); + + if (pbkdf2Params.IterationCount < 0) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + return (uint)pbkdf2Params.IterationCount; + + // PBES1 + case Oids.PbeWithMD5AndDESCBC: + case Oids.PbeWithMD5AndRC2CBC: + case Oids.PbeWithSha1AndDESCBC: + case Oids.PbeWithSha1AndRC2CBC: + case Oids.Pkcs12PbeWithShaAnd3Key3Des: + case Oids.Pkcs12PbeWithShaAnd2Key3Des: + case Oids.Pkcs12PbeWithShaAnd128BitRC2: + case Oids.Pkcs12PbeWithShaAnd40BitRC2: + if (!algorithmIdentifier.Parameters.HasValue) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + PBEParameter pbeParameters = PBEParameter.Decode( + algorithmIdentifier.Parameters.Value, + AsnEncodingRules.BER); + + if (pbeParameters.IterationCount < 0) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + + return (uint)pbeParameters.IterationCount; + + default: + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs b/src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs new file mode 100644 index 00000000000000..7500212fe27d9c --- /dev/null +++ b/src/libraries/Common/src/System/Security/Cryptography/KdfWorkLimiter.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System.Security.Cryptography +{ + // Places KDF work limits on the current thread. + internal static class KdfWorkLimiter + { + [ThreadStatic] + private static State? t_state; + + // Entry point: sets the iteration limit to a new value. + internal static void SetIterationLimit(ulong workLimit) + { + Debug.Assert(t_state == null, "This method is not intended to be called recursively."); + State state = new State(); + state.RemainingAllowedWork = workLimit; + t_state = state; + } + + internal static bool WasWorkLimitExceeded() + { + Debug.Assert(t_state != null, "This method should only be called within a protected block."); + return t_state.WorkLimitWasExceeded; + } + + // Removes any iteration limit on the current thread. + internal static void ResetIterationLimit() + { + t_state = null; + } + + // Records that we're about to perform some amount of work. + // Overflows if the work count is exceeded. + internal static void RecordIterations(int workCount) + { + RecordIterations((long)workCount); + } + + // Records that we're about to perform some amount of work. + // Overflows if the work count is exceeded. + internal static void RecordIterations(long workCount) + { + State? state = t_state; + if (state == null) + { + return; + } + + bool success = false; + + if (workCount < 0) + { + throw new CryptographicException(); + } + + try + { + if (!state.WorkLimitWasExceeded) + { + state.RemainingAllowedWork = checked(state.RemainingAllowedWork - (ulong)workCount); + success = true; + } + } + finally + { + // If for any reason we failed, mark the thread as "no further work allowed" and + // normalize to CryptographicException. + if (!success) + { + state.RemainingAllowedWork = 0; + state.WorkLimitWasExceeded = true; + throw new CryptographicException(); + } + } + } + + private sealed class State + { + internal ulong RemainingAllowedWork; + internal bool WorkLimitWasExceeded; + } + } +} diff --git a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs index 800b4f335e892c..4bf056ffd5f4f9 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs @@ -393,6 +393,7 @@ internal static unsafe int Encrypt( Debug.Assert(pwdTmpBytes!.Length == 0); } + KdfWorkLimiter.RecordIterations(iterationCount); using (var pbkdf2 = new Rfc2898DeriveBytes(pwdTmpBytes, salt.ToArray(), iterationCount, prf)) { derivedKey = pbkdf2.GetBytes(keySizeBytes); diff --git a/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs b/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs index 1bd7c53bb2b44a..8e482b931c7646 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Pkcs12Kdf.cs @@ -147,6 +147,7 @@ private static void Derive( I = IRented.AsSpan(0, ILen); } + KdfWorkLimiter.RecordIterations(iterationCount); IncrementalHash hash = IncrementalHash.CreateHash(hashAlgorithm); try diff --git a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs index 8525ed8c1b2974..e9feee002f6ec8 100644 --- a/src/libraries/Common/tests/System/Net/Http/TestHelper.cs +++ b/src/libraries/Common/tests/System/Net/Http/TestHelper.cs @@ -158,7 +158,7 @@ public static X509Certificate2 CreateServerSelfSignedCertificate(string name = " X509Certificate2 cert = req.CreateSelfSigned(start, end); if (PlatformDetection.IsWindows) { - cert = new X509Certificate2(cert.Export(X509ContentType.Pfx)); + cert = new X509Certificate2(cert.Export(X509ContentType.Pfx), (string?)null); } return cert; diff --git a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs index 4e9e5e20612a94..b08655e6f1d10b 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/X509Certificates/RevocationResponder.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using System.Web; +using Xunit; namespace System.Security.Cryptography.X509Certificates.Tests.Common { @@ -29,6 +30,7 @@ private readonly Dictionary _crlPaths public string UriPrefix { get; } public bool RespondEmpty { get; set; } + public AiaResponseKind AiaResponseKind { get; set; } public TimeSpan ResponseDelay { get; set; } public DelayedActionsFlag DelayedActions { get; set; } @@ -181,13 +183,13 @@ private void HandleRequest(HttpListenerContext context, ref bool responded) Thread.Sleep(ResponseDelay); } - byte[] certData = RespondEmpty ? Array.Empty() : authority.GetCertData(); + byte[] certData = RespondEmpty ? Array.Empty() : GetCertDataForAiaResponseKind(AiaResponseKind, authority); responded = true; context.Response.StatusCode = 200; - context.Response.ContentType = "application/pkix-cert"; + context.Response.ContentType = AiaResponseKindToContentType(AiaResponseKind); context.Response.Close(certData, willBlock: true); - Trace($"Responded with {certData.Length}-byte certificate from {authority.SubjectName}."); + Trace($"Responded with {certData.Length}-byte {AiaResponseKind} from {authority.SubjectName}."); return; } @@ -295,6 +297,41 @@ private static HttpListener OpenListener(out string uriPrefix) } } + private static string AiaResponseKindToContentType(AiaResponseKind kind) + { + if (kind == AiaResponseKind.Cert) + { + return "application/pkix-cert"; + } + else if (kind == AiaResponseKind.Pkcs12) + { + return "application/x-pkcs12"; + } + else + { + Assert.True(false, $"Unknown value AiaResponseKind.`{kind}`."); + return null; + } + } + + private static byte[] GetCertDataForAiaResponseKind(AiaResponseKind kind, CertificateAuthority authority) + { + if (kind == AiaResponseKind.Cert) + { + return authority.GetCertData(); + } + else if (kind == AiaResponseKind.Pkcs12) + { + using X509Certificate2 cert = new X509Certificate2(authority.GetCertData()); + return cert.Export(X509ContentType.Pkcs12); + } + else + { + Assert.True(false, $"Unknown value AiaResponseKind.`{kind}`."); + return null; + } + } + private static bool TryGetOcspRequestBytes(HttpListenerRequest request, string prefix, out byte[] requestBytes) { requestBytes = null; @@ -425,4 +462,10 @@ public enum DelayedActionsFlag : byte Aia = 0b100, All = 0b11111111 } + + public enum AiaResponseKind + { + Cert = 0, + Pkcs12 = 1, + } } diff --git a/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs b/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs index 8ed9938ac835fb..97ac551b1cc87d 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Common/SqlUDTStorage.cs @@ -182,6 +182,9 @@ public override object ConvertXmlToObject(XmlReader xmlReader, XmlRootAttribute? } } Type type = (typeName == null) ? _dataType : Type.GetType(typeName)!; + + TypeLimiter.EnsureTypeIsAllowed(type); + object Obj = System.Activator.CreateInstance(type, true)!; Debug.Assert(xmlReader is DataTextReader, "Invalid DataTextReader is being passed to customer"); ((IXmlSerializable)Obj).ReadXml(xmlReader); diff --git a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs index d42609fed6b5cf..4b425eaea464e5 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/RestrictedTypeHandlingTests.cs @@ -242,6 +242,59 @@ public void DataTable_HonorsGloballyDefinedAllowList() } } + [Fact] + public void DataTable_HonorsGloballyDefinedAllowListForSqlTypes() + { + // Arrange + + DataTable table = new DataTable("MyTable"); + table.Columns.Add("MyNullableColumn", typeof(MyCustomNullable1)); + table.Rows.Add(new MyCustomNullable1()); + table.AcceptChanges(); + + var asXml = @$" + + + + + + + + + + + + + + + + + + false + + +"; + + // Act & assert + // Deserialization should fail since MyCustomNullable2 is not on the allow list, + // even though MyCustomNullable1 is on the allow list. + + try + { + AppDomain.CurrentDomain.SetData(AppDomainDataSetDefaultAllowedTypesKey, new Type[] + { + typeof(MyCustomNullable1) + }); + + table = new DataTable(); + Assert.Throws(() => table.ReadXml(new StringReader(asXml))); + } + finally + { + AppDomain.CurrentDomain.SetData(AppDomainDataSetDefaultAllowedTypesKey, null); + } + } + [Fact] public void DataColumn_ConvertExpression_SubjectToAllowList_Success() { @@ -401,6 +454,20 @@ private sealed class MyCustomClass { } + public sealed class MyCustomNullable1 : INullable + { + public static MyCustomNullable1 Null { get; } = new MyCustomNullable1(); + + public bool IsNull => false; + } + + public sealed class MyCustomNullable2 : INullable + { + public static MyCustomNullable2 Null { get; } = new MyCustomNullable2(); + + public bool IsNull => false; + } + public sealed class MyXmlSerializableClass : IXmlSerializable { public XmlSchema GetSchema() diff --git a/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj b/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj index 33a9aa8c1dc0cb..9c219ec9ef564c 100644 --- a/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj +++ b/src/libraries/System.Formats.Tar/src/System.Formats.Tar.csproj @@ -33,7 +33,9 @@ + + @@ -47,7 +49,6 @@ - diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index 65315b006d918f..36cbdab8a7cc78 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -368,9 +368,17 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b // If the path can be extracted in the specified destination directory, returns the full path with sanitized file name. Otherwise, returns null. private static string? GetSanitizedFullPath(string destinationDirectoryFullPath, string path) { + destinationDirectoryFullPath = PathInternal.EnsureTrailingSeparator(destinationDirectoryFullPath); + string fullyQualifiedPath = Path.IsPathFullyQualified(path) ? path : Path.Combine(destinationDirectoryFullPath, path); string normalizedPath = Path.GetFullPath(fullyQualifiedPath); // Removes relative segments - string sanitizedPath = Path.Join(Path.GetDirectoryName(normalizedPath), ArchivingUtils.SanitizeEntryFilePath(Path.GetFileName(normalizedPath))); + string? fileName = Path.GetFileName(normalizedPath); + if (string.IsNullOrEmpty(fileName)) // It's a directory + { + fileName = PathInternal.DirectorySeparatorCharAsString; + } + + string sanitizedPath = Path.Join(Path.GetDirectoryName(normalizedPath), ArchivingUtils.SanitizeEntryFilePath(fileName)); return sanitizedPath.StartsWith(destinationDirectoryFullPath, PathInternal.StringComparison) ? sanitizedPath : null; } diff --git a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj index ad1e7316f99462..063d064a0cb8db 100644 --- a/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj +++ b/src/libraries/System.Formats.Tar/tests/System.Formats.Tar.Tests.csproj @@ -13,6 +13,7 @@ + diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs new file mode 100644 index 00000000000000..b5a1f111aa6a46 --- /dev/null +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Base.cs @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +namespace System.Formats.Tar.Tests; + +public abstract class TarFile_ExtractToDirectory_Tests : TarTestsBase +{ + // TarEntryFormat, TarEntryType, string fileName + public static IEnumerable GetExactRootDirMatchCases() + { + var allValidFormats = new TarEntryFormat[] { TarEntryFormat.V7, TarEntryFormat.Ustar, TarEntryFormat.Pax, TarEntryFormat.Gnu }; + + foreach (TarEntryFormat format in allValidFormats) + { + yield return new object[] + { + format, + TarEntryType.Directory, + "" // Root directory + }; + yield return new object[] + { + format, + TarEntryType.Directory, + "./" // Slash dot root directory + }; + yield return new object[] + { + format, + TarEntryType.Directory, + "directory", + }; + yield return new object[] + { + format, + GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, format), + "file.txt" + }; + } + + var formatsThatHandleLongFileNames = new TarEntryFormat[] { TarEntryFormat.Pax, TarEntryFormat.Gnu }; + var longFileNames = new string[] + { + // Long path with many short segment names and a filename + "folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/file.txt", + // Long path with single long segment name and a filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfoldername/file.txt", + // Long path with single long leaf filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfilename.txt", + }; + + foreach (TarEntryFormat format in formatsThatHandleLongFileNames) + { + foreach (string filePath in longFileNames) + { + yield return new object[] { format, TarEntryType.RegularFile, filePath }; + } + } + + var longFolderNames = new string[] + { + // Long path with many short segment names and a filename + "folderfolder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder/folder", + // Long path with single long segment name and a filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfoldername/folder", + // Long path with single long leaf filename + "veryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryveryverylongfoldername" + }; + + foreach (TarEntryFormat format in formatsThatHandleLongFileNames) + { + foreach (string folderPath in longFolderNames) + { + yield return new object[] { format, TarEntryType.Directory, folderPath }; + } + } + } +} diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index ab90f0043bc7d9..3cec81f62a501f 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -9,7 +9,7 @@ namespace System.Formats.Tar.Tests { - public class TarFile_ExtractToDirectory_Stream_Tests : TarTestsBase + public class TarFile_ExtractToDirectory_Stream_Tests : TarFile_ExtractToDirectory_Tests { [Fact] public void NullStream_Throws() @@ -204,5 +204,170 @@ public void PaxNameCollision_DedupInExtendedAttributes() Assert.True(File.Exists(path1)); Assert.True(Path.Exists(path2)); } + + [Theory] + [MemberData(nameof(GetExactRootDirMatchCases))] + public void ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws(TarEntryFormat format, TarEntryType entryType, string fileName) + { + ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal(format, entryType, fileName, inverted: false); + ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal(format, entryType, fileName, inverted: true); + } + + [Fact] + public void ExtractToDirectory_ExactRootDirMatch_Directory_Relative_Throws() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + // Relative segments should not change the final destination folder + string dirPath1 = Path.Join(entryFolderPath, "..", "folder"); + string dirPath2 = Path.Join(entryFolderPath, "..", "folder" + Path.DirectorySeparatorChar); + + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath1, linkTargetPath: null); + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath2, linkTargetPath: null); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void ExtractToDirectory_ExactRootDirMatch_HardLinks_Throws(TarEntryFormat format) + { + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.HardLink, inverted: false); + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.HardLink, inverted: true); + } + + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void ExtractToDirectory_ExactRootDirMatch_SymLinks_Throws(TarEntryFormat format) + { + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.SymbolicLink, inverted: false); + ExtractToDirectory_ExactRootDirMatch_Links_Throws(format, TarEntryType.SymbolicLink, inverted: true); + } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public void ExtractToDirectory_ExactRootDirMatch_SymLinks_TargetOutside_Throws() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string linkPath = Path.Join(entryFolderPath, "link"); + + // Links target outside the destination path should not be allowed + // Ensure relative segments do not go around this restriction + string linkTargetPath1 = Path.Join(entryFolderPath, "..", entryFolderName); + string linkTargetPath2 = Path.Join(entryFolderPath, "..", entryFolderName + Path.DirectorySeparatorChar); + + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath1); + ExtractRootDirMatch_Verify_Throws(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath2); + } + + private void ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal(TarEntryFormat format, TarEntryType entryType, string fileName, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string filePath = Path.Join(entryFolderPath, fileName); + + ExtractRootDirMatch_Verify_Throws(format, entryType, destinationFolderPath, filePath, linkTargetPath: null); + } + + private void ExtractToDirectory_ExactRootDirMatch_Links_Throws(TarEntryFormat format, TarEntryType entryType, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + // link entry file path: folder/link (does not match destination, should not be extracted) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + // link entry file path: folderSibling/link (does not match destination, should not be extracted) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + string linkTargetFileName = "file.txt"; + string linkFileName = "link"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + string linkPath = Path.Join(entryFolderPath, linkFileName); + string linkTargetPath = Path.Join(destinationFolderPath, linkTargetFileName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + File.Create(linkTargetPath).Dispose(); + + ExtractRootDirMatch_Verify_Throws(format, entryType, destinationFolderPath, linkPath, linkTargetPath); + } + + private void ExtractRootDirMatch_Verify_Throws(TarEntryFormat format, TarEntryType entryType, string destinationFolderPath, string entryFilePath, string linkTargetPath) + { + using MemoryStream archive = new(); + using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) + { + TarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, entryFilePath); + MemoryStream dataStream = null; + if (entryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) + { + dataStream = new MemoryStream(); + dataStream.Write(new byte[] { 0x1 }); + entry.DataStream = dataStream; + } + if (entryType is TarEntryType.SymbolicLink or TarEntryType.HardLink) + { + entry.LinkName = linkTargetPath; + } + writer.WriteEntry(entry); + if (dataStream != null) + { + dataStream.Dispose(); + } + } + archive.Position = 0; + + Assert.Throws(() => TarFile.ExtractToDirectory(archive, destinationFolderPath, overwriteFiles: false)); + Assert.False(File.Exists(entryFilePath), $"File should not exist: {entryFilePath}"); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs index d7502d940e94e6..a765f4f911eb77 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs @@ -11,7 +11,7 @@ namespace System.Formats.Tar.Tests { - public class TarFile_ExtractToDirectoryAsync_Stream_Tests : TarTestsBase + public class TarFile_ExtractToDirectoryAsync_Stream_Tests : TarFile_ExtractToDirectory_Tests { [Fact] public async Task ExtractToDirectoryAsync_Cancel() @@ -269,5 +269,170 @@ public async Task PaxNameCollision_DedupInExtendedAttributesAsync() Assert.True(File.Exists(path1)); Assert.True(Path.Exists(path2)); } + + [Theory] + [MemberData(nameof(GetExactRootDirMatchCases))] + public async Task ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Async(TarEntryFormat format, TarEntryType entryType, string fileName) + { + await ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal_Async(format, entryType, fileName, inverted: false); + await ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal_Async(format, entryType, fileName, inverted: true); + } + + [Fact] + public async Task ExtractToDirectory_ExactRootDirMatch_Directory_Relative_Throws_Async() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + // Relative segments should not change the final destination folder + string dirPath1 = Path.Join(entryFolderPath, "..", "folder"); + string dirPath2 = Path.Join(entryFolderPath, "..", "folder" + Path.DirectorySeparatorChar); + + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath1, linkTargetPath: null); + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, dirPath2, linkTargetPath: null); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task ExtractToDirectory_ExactRootDirMatch_HardLinks_Throws_Async(TarEntryFormat format) + { + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.HardLink, inverted: false); + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.HardLink, inverted: true); + } + + [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task ExtractToDirectory_ExactRootDirMatch_SymLinks_Throws_Async(TarEntryFormat format) + { + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.SymbolicLink, inverted: false); + await ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(format, TarEntryType.SymbolicLink, inverted: true); + } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public async Task ExtractToDirectory_ExactRootDirMatch_SymLinks_TargetOutside_Throws_Async() + { + string entryFolderName = "folder"; + string destinationFolderName = "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string linkPath = Path.Join(entryFolderPath, "link"); + + // Links target outside the destination path should not be allowed + // Ensure relative segments do not go around this restriction + string linkTargetPath1 = Path.Join(entryFolderPath, "..", entryFolderName); + string linkTargetPath2 = Path.Join(entryFolderPath, "..", entryFolderName + Path.DirectorySeparatorChar); + + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath1); + await ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat.Ustar, TarEntryType.Directory, destinationFolderPath, linkPath, linkTargetPath2); + } + + private async Task ExtractToDirectory_ExactRootDirMatch_RegularFile_And_Directory_Throws_Internal_Async(TarEntryFormat format, TarEntryType entryType, string fileName, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + + string filePath = Path.Join(entryFolderPath, fileName); + + await ExtractRootDirMatch_Verify_Throws_Async(format, entryType, destinationFolderPath, filePath, linkTargetPath: null); + } + + private Task ExtractToDirectory_ExactRootDirMatch_Links_Throws_Async(TarEntryFormat format, TarEntryType entryType, bool inverted) + { + // inverted == false: + // destination: folderSibling/ + // entry folder: folder/ (does not match destination) + // link entry file path: folder/link (does not match destination, should not be extracted) + + // inverted == true: + // destination: folder/ + // entry folder: folderSibling/ (does not match destination) + // link entry file path: folderSibling/link (does not match destination, should not be extracted) + + string entryFolderName = inverted ? "folderSibling" : "folder"; + string destinationFolderName = inverted ? "folder" : "folderSibling"; + + string linkTargetFileName = "file.txt"; + string linkFileName = "link"; + + using TempDirectory root = new TempDirectory(); + + string entryFolderPath = Path.Join(root.Path, entryFolderName); + string destinationFolderPath = Path.Join(root.Path, destinationFolderName); + + string linkPath = Path.Join(entryFolderPath, linkFileName); + string linkTargetPath = Path.Join(destinationFolderPath, linkTargetFileName); + + Directory.CreateDirectory(entryFolderPath); + Directory.CreateDirectory(destinationFolderPath); + File.Create(linkTargetPath).Dispose(); + + return ExtractRootDirMatch_Verify_Throws_Async(format, entryType, destinationFolderPath, linkPath, linkTargetPath); + } + + private async Task ExtractRootDirMatch_Verify_Throws_Async(TarEntryFormat format, TarEntryType entryType, string destinationFolderPath, string entryFilePath, string linkTargetPath) + { + await using MemoryStream archive = new(); + await using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) + { + TarEntry entry = InvokeTarEntryCreationConstructor(format, entryType, entryFilePath); + MemoryStream dataStream = null; + if (entryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) + { + dataStream = new MemoryStream(); + await dataStream.WriteAsync(new byte[] { 0x1 }); + entry.DataStream = dataStream; + } + if (entryType is TarEntryType.SymbolicLink or TarEntryType.HardLink) + { + entry.LinkName = linkTargetPath; + } + await writer.WriteEntryAsync(entry); + if (dataStream != null) + { + await dataStream.DisposeAsync(); + } + } + archive.Position = 0; + + await Assert.ThrowsAsync(() => TarFile.ExtractToDirectoryAsync(archive, destinationFolderPath, overwriteFiles: false)); + Assert.False(File.Exists(entryFilePath), $"File should not exist: {entryFilePath}"); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 601fa85c3a23a9..48b7e23df4681c 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -464,7 +464,7 @@ protected void CheckConversionType(TarEntry entry, TarEntryFormat expectedFormat Assert.Equal(expectedType, entry.GetType()); } - protected TarEntryType GetTarEntryTypeForTarEntryFormat(TarEntryType entryType, TarEntryFormat format) + protected static TarEntryType GetTarEntryTypeForTarEntryFormat(TarEntryType entryType, TarEntryFormat format) { if (format is TarEntryFormat.V7) { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs index 8704cfb77ec671..4cccf0f0fd70c3 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs @@ -63,7 +63,7 @@ public static IEnumerable SslStream_StreamToStream_Authentication_Succ using (X509Certificate2 clientCert = Configuration.Certificates.GetClientCertificate()) { yield return new object[] { new X509Certificate2(serverCert), new X509Certificate2(clientCert) }; - yield return new object[] { new X509Certificate(serverCert.Export(X509ContentType.Pfx)), new X509Certificate(clientCert.Export(X509ContentType.Pfx)) }; + yield return new object[] { new X509Certificate(serverCert.Export(X509ContentType.Pfx), (string)null, X509KeyStorageFlags.DefaultKeySet), new X509Certificate(clientCert.Export(X509ContentType.Pfx), (string)null, X509KeyStorageFlags.DefaultKeySet) }; } } diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index 0a0c735457a584..06d730d4986ae8 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -1,4 +1,8 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.33602.30 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{94B59BA0-491F-4B59-ADFF-A057EC3EC835}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}" @@ -41,17 +45,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{E1AEBD5D-AE4 EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 - Checked|Any CPU = Checked|Any CPU - Checked|x64 = Checked|x64 - Checked|x86 = Checked|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.ActiveCfg = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.Build.0 = Debug|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x64.ActiveCfg = Debug|x64 @@ -64,12 +74,12 @@ Global {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x64.Build.0 = Release|x64 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.ActiveCfg = Release|x86 {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.Build.0 = Release|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 - {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -82,12 +92,12 @@ Global {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x64.Build.0 = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.ActiveCfg = Release|Any CPU {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.Build.0 = Release|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU - {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.Build.0 = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|Any CPU.Build.0 = Debug|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -100,12 +110,12 @@ Global {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x64.Build.0 = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.ActiveCfg = Release|Any CPU {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Release|x86.Build.0 = Release|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x64.Build.0 = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.ActiveCfg = Debug|Any CPU - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A}.Checked|x86.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.Build.0 = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU + {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -118,12 +128,12 @@ Global {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x64.Build.0 = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.ActiveCfg = Release|Any CPU {1B248B4C-7584-4C04-850A-A50EB592052C}.Release|x86.Build.0 = Release|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x64.Build.0 = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.ActiveCfg = Debug|Any CPU - {1B248B4C-7584-4C04-850A-A50EB592052C}.Checked|x86.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.Build.0 = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|Any CPU.Build.0 = Debug|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -136,12 +146,12 @@ Global {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x64.Build.0 = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.ActiveCfg = Release|Any CPU {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Release|x86.Build.0 = Release|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|Any CPU.Build.0 = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x64.Build.0 = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.ActiveCfg = Debug|Any CPU - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40}.Checked|x86.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.Build.0 = Debug|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -154,12 +164,12 @@ Global {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x64.Build.0 = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.ActiveCfg = Release|Any CPU {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.Build.0 = Release|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU - {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -172,12 +182,12 @@ Global {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x64.Build.0 = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.ActiveCfg = Release|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.Build.0 = Release|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU - {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -190,12 +200,12 @@ Global {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x64.Build.0 = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.ActiveCfg = Release|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.Build.0 = Release|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.Build.0 = Debug|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -208,12 +218,12 @@ Global {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x64.Build.0 = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.ActiveCfg = Release|Any CPU {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.Build.0 = Release|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU - {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.Build.0 = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU + {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -226,12 +236,12 @@ Global {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x64.Build.0 = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.ActiveCfg = Release|Any CPU {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Release|x86.Build.0 = Release|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|Any CPU.Build.0 = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x64.Build.0 = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.ActiveCfg = Debug|Any CPU - {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1}.Checked|x86.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.Build.0 = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU + {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -244,12 +254,12 @@ Global {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x64.Build.0 = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.ActiveCfg = Release|Any CPU {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Release|x86.Build.0 = Release|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|Any CPU.Build.0 = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x64.Build.0 = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.ActiveCfg = Debug|Any CPU - {EA8DBC12-60BC-433E-ABFF-A89DFA795283}.Checked|x86.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -262,12 +272,12 @@ Global {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x64.Build.0 = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.ActiveCfg = Release|Any CPU {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.Build.0 = Release|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU - {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -280,12 +290,12 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x64.Build.0 = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.ActiveCfg = Release|Any CPU {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.Build.0 = Release|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU - {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.Build.0 = Debug|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -298,12 +308,12 @@ Global {866D295E-424A-4747-9417-CD7746936138}.Release|x64.Build.0 = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.ActiveCfg = Release|Any CPU {866D295E-424A-4747-9417-CD7746936138}.Release|x86.Build.0 = Release|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU - {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -316,12 +326,12 @@ Global {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x64.Build.0 = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.ActiveCfg = Release|Any CPU {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.Build.0 = Release|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU - {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU + {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -334,20 +344,19 @@ Global {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x64.Build.0 = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.ActiveCfg = Release|Any CPU {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Release|x86.Build.0 = Release|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|Any CPU.Build.0 = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x64.Build.0 = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.ActiveCfg = Debug|Any CPU - {0B5FD0C2-367D-4AD6-8001-80AD79B2441C}.Checked|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {94B59BA0-491F-4B59-ADFF-A057EC3EC835} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} - {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} + {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {9C2C2B5C-5E75-4935-8A4A-DE3D3A5DBBC1} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {EA8DBC12-60BC-433E-ABFF-A89DFA795283} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} @@ -355,14 +364,12 @@ Global {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {866D295E-424A-4747-9417-CD7746936138} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} - {4859BEE3-34B7-48E7-83D4-1ADD8B8F3B3A} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} {0B5FD0C2-367D-4AD6-8001-80AD79B2441C} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} - {1B248B4C-7584-4C04-850A-A50EB592052C} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {90CDAD9F-3ACC-43B0-9696-0C849FCD8C40} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} - {768B77B0-EA45-469D-B39E-545EB72F5A43} = {E1AEBD5D-AE4E-4F61-B9ED-AEF950B0CC33} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{94b59ba0-491f-4b59-adff-a057ec3ec835}*SharedItemsImports = 5 + EndGlobalSection EndGlobal diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs index e75b25eab45d73..aebe94581377b5 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ElementsMarshalling.cs @@ -160,6 +160,25 @@ public NonBlittableElementsMarshalling( protected abstract InvocationExpressionSyntax GetUnmanagedValuesSource(TypePositionInfo info, StubCodeContext context); protected abstract InvocationExpressionSyntax GetManagedValuesDestination(TypePositionInfo info, StubCodeContext context); + protected IEnumerable DeclareLastIndexMarshalledIfNeeded( + TypePositionInfo info, + StubCodeContext context) + { + // We need to declare the last index marshalled variable if the collection is not multi-dimensional. + // If it is multidimensional, we will just clear each allocated span. + if (UsesLastIndexMarshalled(info, context)) + { + yield return LocalDeclarationStatement( + VariableDeclaration( + PredefinedType(Token(SyntaxKind.IntKeyword)), + SingletonSeparatedList( + VariableDeclarator( + Identifier(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)), + null, + EqualsValueClause(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))))))); + } + } + protected StatementSyntax GenerateByValueOutMarshalStatement(TypePositionInfo info, StubCodeContext context) { // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection. @@ -180,8 +199,10 @@ protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCo // ReadOnlySpan = // Span = + // .Clear() // << marshal contents >> - return Block( + var statements = new List() + { LocalDeclarationStatement(VariableDeclaration( GenericName( Identifier(TypeNames.System_ReadOnlySpan), @@ -198,14 +219,27 @@ protected StatementSyntax GenerateMarshalStatement(TypePositionInfo info, StubCo VariableDeclarator( Identifier(nativeSpanIdentifier)) .WithInitializer(EqualsValueClause( - GetUnmanagedValuesDestination(info, context)))))), - GenerateContentsMarshallingStatement( + GetUnmanagedValuesDestination(info, context)))))) + }; + // If it is a multidimensional array, we will just clear each allocated span. + if (!UsesLastIndexMarshalled(info, context)) + { + // .Clear() + statements.Add(ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeSpanIdentifier), + IdentifierName("Clear"))))); + } + statements.Add(GenerateContentsMarshallingStatement( info, context, MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(MarshallerHelpers.GetManagedSpanIdentifier(info, context)), IdentifierName("Length")), StubCodeContext.Stage.Marshal)); + return Block(statements); } public StatementSyntax GenerateUnmarshalStatement(TypePositionInfo info, StubCodeContext context) @@ -315,13 +349,42 @@ protected StatementSyntax GenerateByValueOutUnmarshalStatement(TypePositionInfo StubCodeContext.Stage.Unmarshal)); } + private Dictionary<(TypePositionInfo, StubCodeContext), bool> _usesLastIndexMarshalledCache = new(); + + protected bool UsesLastIndexMarshalled(TypePositionInfo info, StubCodeContext context) + { + var cleanupContext = context with { CurrentStage = StubCodeContext.Stage.Cleanup }; + if (_usesLastIndexMarshalledCache.TryGetValue((info, cleanupContext), out bool result)) + return result; + bool usesLastIndexMarshalled = !(ShouldCleanupAllElements(info, context) || !GenerateElementStages(info, cleanupContext, out _, out _, StubCodeContext.Stage.Cleanup).Any()); + _usesLastIndexMarshalledCache.Add((info, cleanupContext), usesLastIndexMarshalled); + return usesLastIndexMarshalled; + } + + protected static bool ShouldCleanupAllElements(TypePositionInfo info, StubCodeContext context) + { + // AdditionalTemporaryStateLivesAcrossStages implies that it is an outer collection + // Out parameters means that the contents are created by the P/Invoke and assumed to have successfully created all elements + return !context.AdditionalTemporaryStateLivesAcrossStages || info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out || info.RefKind == RefKind.Out; + } + protected StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, StubCodeContext context) { string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + ExpressionSyntax indexConstraintName; + if (ShouldCleanupAllElements(info, context)) + { + indexConstraintName = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeSpanIdentifier), + IdentifierName("Length")); + } + else + { + indexConstraintName = IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)); + } + StatementSyntax contentsCleanupStatements = GenerateContentsMarshallingStatement(info, context, - MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, - IdentifierName(MarshallerHelpers.GetNativeSpanIdentifier(info, context)), - IdentifierName("Length")), + indexConstraintName, StubCodeContext.Stage.Cleanup); if (contentsCleanupStatements.IsKind(SyntaxKind.EmptyStatement)) @@ -342,21 +405,22 @@ protected StatementSyntax GenerateElementCleanupStatement(TypePositionInfo info, contentsCleanupStatements); } - protected StatementSyntax GenerateContentsMarshallingStatement( + private List GenerateElementStages( TypePositionInfo info, StubCodeContext context, - ExpressionSyntax lengthExpression, - params StubCodeContext.Stage[] stagesToGeneratePerElement) + out LinearCollectionElementMarshallingCodeContext elementSetupSubContext, + out TypePositionInfo localElementInfo, + params StubCodeContext.Stage[] stages) { string managedSpanIdentifier = MarshallerHelpers.GetManagedSpanIdentifier(info, context); string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); - var elementSetupSubContext = new LinearCollectionElementMarshallingCodeContext( + elementSetupSubContext = new LinearCollectionElementMarshallingCodeContext( StubCodeContext.Stage.Setup, managedSpanIdentifier, nativeSpanIdentifier, context); - TypePositionInfo localElementInfo = _elementInfo with + localElementInfo = _elementInfo with { InstanceIdentifier = info.InstanceIdentifier, RefKind = info.IsByRef ? info.RefKind : info.ByValueContentsMarshalKind.GetRefKindForByValueContentsKind(), @@ -365,11 +429,22 @@ protected StatementSyntax GenerateContentsMarshallingStatement( }; List elementStatements = new(); - foreach (StubCodeContext.Stage stage in stagesToGeneratePerElement) + foreach (StubCodeContext.Stage stage in stages) { var elementSubContext = elementSetupSubContext with { CurrentStage = stage }; - elementStatements.AddRange(_elementMarshaller.Generate(localElementInfo, elementSubContext)); + elementStatements.AddRange( _elementMarshaller.Generate(localElementInfo, elementSubContext)); } + return elementStatements; + + } + + protected StatementSyntax GenerateContentsMarshallingStatement( + TypePositionInfo info, + StubCodeContext context, + ExpressionSyntax lengthExpression, + params StubCodeContext.Stage[] stagesToGeneratePerElement) + { + var elementStatements = GenerateElementStages(info, context, out var elementSetupSubContext, out var localElementInfo, stagesToGeneratePerElement); if (elementStatements.Any()) { @@ -384,8 +459,16 @@ protected StatementSyntax GenerateContentsMarshallingStatement( } // Iterate through the elements of the native collection to marshal them - return MarshallerHelpers.GetForLoop(lengthExpression, elementSetupSubContext.IndexerIdentifier) - .WithStatement(marshallingStatement); + ForStatementSyntax forLoop = MarshallerHelpers.GetForLoop(lengthExpression, elementSetupSubContext.IndexerIdentifier) + .WithStatement(Block(marshallingStatement)); + // If we're tracking LastIndexMarshalled, increment that too + if (context.CurrentStage == StubCodeContext.Stage.Marshal && UsesLastIndexMarshalled(info, context)) + { + forLoop = forLoop.AddIncrementors( + PrefixUnaryExpression(SyntaxKind.PreIncrementExpression, + IdentifierName(MarshallerHelpers.GetLastIndexMarshalledIdentifier(info, context)))); + } + return forLoop; } return EmptyStatement(); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs index 98213f4f7dd257..1ad3747d654b4b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -147,6 +147,11 @@ public static string GetNumElementsIdentifier(TypePositionInfo info, StubCodeCon return context.GetAdditionalIdentifier(info, "numElements"); } + public static string GetLastIndexMarshalledIdentifier(TypePositionInfo info, StubCodeContext context) + { + return context.GetAdditionalIdentifier(info, "lastIndexMarshalled"); + } + internal static bool CanUseCallerAllocatedBuffer(TypePositionInfo info, StubCodeContext context) { return context.SingleFrameSpansNativeContext && (!info.IsByRef || info.RefKind == RefKind.In); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs index 20707af44ed66b..c3c9026783839c 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatefulMarshallingStrategy.cs @@ -311,7 +311,7 @@ internal sealed class StatefulLinearCollectionBlittableElementsMarshalling : Bli public StatefulLinearCollectionBlittableElementsMarshalling( ICustomTypeMarshallingStrategy innerMarshaller, MarshallerShape shape, TypeSyntax managedElementType, TypeSyntax unmanagedElementType, ExpressionSyntax numElementsExpression) - : base (managedElementType, unmanagedElementType) + : base(managedElementType, unmanagedElementType) { _innerMarshaller = innerMarshaller; _shape = shape; @@ -451,7 +451,7 @@ public StatefulLinearCollectionNonBlittableElementsMarshalling( IMarshallingGenerator elementMarshaller, TypePositionInfo elementInfo, ExpressionSyntax numElementsExpression) - : base (unmanagedElementType, elementMarshaller, elementInfo) + : base(unmanagedElementType, elementMarshaller, elementInfo) { _innerMarshaller = innerMarshaller; _shape = shape; @@ -480,6 +480,7 @@ public IEnumerable GenerateCleanupStatements(TypePositionInfo i IdentifierName(ShapeMemberNames.Free)), ArgumentList())); } + public IEnumerable GenerateGuaranteedUnmarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateGuaranteedUnmarshalStatements(info, context); public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context) @@ -500,6 +501,7 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i // ReadOnlySpan = .GetManagedValuesSource() // Span = .GetUnmanagedValuesDestination() + // .Clear() // << marshal contents >> yield return GenerateMarshalStatement(info, context); } @@ -507,8 +509,8 @@ public IEnumerable GenerateMarshalStatements(TypePositionInfo i public IEnumerable GenerateNotifyForSuccessfulInvokeStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateNotifyForSuccessfulInvokeStatements(info, context); public IEnumerable GeneratePinnedMarshalStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinnedMarshalStatements(info, context); public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GeneratePinStatements(info, context); - public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) => _innerMarshaller.GenerateSetupStatements(info, context); - + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + => DeclareLastIndexMarshalledIfNeeded(info, context).Concat(_innerMarshaller.GenerateSetupStatements(info, context)); public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) { string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs index aa09b9d8d3d01e..906712e7a02655 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StatelessMarshallingStrategy.cs @@ -514,7 +514,7 @@ public StatelessLinearCollectionNonBlittableElementsMarshalling( IMarshallingGenerator elementMarshaller, TypePositionInfo elementInfo, ExpressionSyntax numElementsExpression) - : base (unmanagedElementType, elementMarshaller, elementInfo) + : base(unmanagedElementType, elementMarshaller, elementInfo) { _marshallerTypeSyntax = marshallerTypeSyntax; _nativeTypeSyntax = nativeTypeSyntax; @@ -530,6 +530,12 @@ public IEnumerable GenerateCleanupStatements(TypePositionInfo i if (!elementCleanup.IsKind(SyntaxKind.EmptyStatement)) { + if (!UsesLastIndexMarshalled(info, context)) + { + // numElementsIdentifier is declared in setup + string numElementsIdentifier = MarshallerHelpers.GetNumElementsIdentifier(info, context); + yield return ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(numElementsIdentifier), _numElementsExpression)); + } yield return elementCleanup; } } @@ -621,6 +627,11 @@ public IEnumerable GenerateSetupStatements(TypePositionInfo inf { InstanceIdentifier = numElementsIdentifier }, context); + + foreach (var statement in DeclareLastIndexMarshalledIfNeeded(info, context)) + { + yield return statement; + } } public IEnumerable GenerateUnmarshalCaptureStatements(TypePositionInfo info, StubCodeContext context) => Array.Empty(); diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs new file mode 100644 index 00000000000000..17586de9cef39c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs @@ -0,0 +1,539 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using SharedTypes; +using Xunit; + +namespace LibraryImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class MarshallingFails + { + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void Utf8StringSpan(ReadOnlySpan s); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void Utf8StringArray(string[] s); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void MarshalSingleDimensionalArray( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStruct), ElementIndirectionDepth = 1)] + BoolStruct[] c); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void MarshalMultidimensionalArray_CheckOuterArrayIsIndexTracked( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStructArray), ElementIndirectionDepth = 1)] + BoolStruct[][] c); + + [LibraryImport("DoesNotExist", StringMarshalling = StringMarshalling.Utf8)] + public static partial void MarshalMultidimensionalArray_CheckInnerArraysAreCleared( + [MarshalUsing(typeof(EnforceClearedMemoryCleanup), ElementIndirectionDepth = 2)] + BoolStruct[][] c); + + [LibraryImport("DoesNotExist")] + public static partial void MarshalArray_Ref( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStruct), ElementIndirectionDepth = 1)] + [MarshalUsing(ConstantElementCount = 10)] + ref BoolStruct[] c); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "negate_bool_struct_array_out")] + public static partial void NegateBoolsOut( + BoolStruct[] boolStruct, + int numValues, + [MarshalUsing(typeof(EnforceAllElementsCleanedUpBoolStruct), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(numValues))] + out BoolStruct[] pBoolStructOut); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "negate_bool_struct_array_out_2d")] + public static partial void NegateBoolsOut2D( + BoolStruct[][] boolStruct, + int length, + int[] widths, + [MarshalUsing(typeof(EnforceAllElementsCleanedUpBoolStruct), ElementIndirectionDepth = 2)] + [MarshalUsing(CountElementName = nameof(widths), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(length))] + out BoolStruct[][] pBoolStructOut); + + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "fill_range_array")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool FillRangeArray( + [MarshalUsing(typeof(EnforceAllElementsCleanedUpIntStruct), ElementIndirectionDepth = 1)] + [Out] + IntStructWrapper[] array, + int length, + int start); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "fill_range_array_2d")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool FillRangeArray2D( + [MarshalUsing(typeof(EnforceAllElementsCleanedUpIntStruct), ElementIndirectionDepth = 2)] + [MarshalUsing(CountElementName = nameof(widths), ElementIndirectionDepth = 1)] + [Out] + IntStructWrapper[][] array, + int length, + int[] widths, + int start); + + [LibraryImport(NativeExportsNE_Binary, EntryPoint = "negate_bool_struct_array_ref")] + public static partial void NegateBoolsRef( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStruct), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(numValues))] + ref BoolStruct[] boolStruct, + int numValues); + + [LibraryImport("DoesNotExist", EntryPoint = "negate_bool_struct_array_ref_2d")] + public static partial void NegateBoolsRef2D_LastElementMarshalling( + [MarshalUsing(typeof(EnforceLastElementMarshalledCleanupBoolStructArray), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(length))] + ref BoolStruct[][] boolStruct, + int length); + + [LibraryImport("DoesNotExist", EntryPoint = "negate_bool_struct_array_ref_2d")] + public static partial void NegateBoolsRef2D_ClearMarshalling( + [MarshalUsing(typeof(EnforceClearedMemoryCleanup), ElementIndirectionDepth = 2)] + [MarshalUsing(CountElementName = nameof(widths), ElementIndirectionDepth = 1)] + [MarshalUsing(CountElementName = nameof(length))] + ref BoolStruct[][] boolStruct, + int length, + int[] widths); + } + } + + public class CollectionMarshallingFails + { + [Fact] + public void UTFStringConversionFailures() + { + bool threw = false; + try + { + var a = new string[] { new string((char)0xaaaa, 1_000_000_000), "Hello" }; // Conversion of the very long string to utf8 is going to fail + NativeExportsNE.MarshallingFails.Utf8StringSpan(a); + } + catch (ArgumentException) { threw = true; } + catch (OutOfMemoryException) { threw = true; } + Assert.True(threw); + + threw = false; + try + { + var a = new string[] { new string((char)0xaaaa, 1_000_000_000), "Hello" }; // Conversion of the very long string to utf8 is going to fail + NativeExportsNE.MarshallingFails.Utf8StringArray(a); + } + catch (ArgumentException) { threw = true; } + catch (OutOfMemoryException) { threw = true; } + Assert.True(threw); + } + + private T[][] GetMultiDimensionalArray(int dim1, int dim2) + { + var arr = new T[dim1][]; + for (int i = 0; i < dim1; i++) + { + arr[i] = new T[dim2]; + } + return arr; + } + + [Fact] + public void SingleDimensionalArray_EnsureLastIndexArrayIsTracked() + { + var arr = new BoolStruct[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStruct.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.MarshalSingleDimensionalArray(arr); + }); + } + } + + [Fact] + public void MultidimensionalArray_CheckOuterArrayIsIndexTracked() + { + var arr = GetMultiDimensionalArray(10, 10); + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStructArray.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.MarshalMultidimensionalArray_CheckOuterArrayIsIndexTracked(arr); + }); + } + } + + [Fact] + public void MultidimensionalArray_CheckInnerArraysAreCleared() + { + var arr = GetMultiDimensionalArray(10, 10); + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceClearedMemoryCleanup.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.MarshalMultidimensionalArray_CheckInnerArraysAreCleared(arr); + }); + } + } + + [Fact] + public void SingleDimensionalOutArray_EnsureAllCleaned() + { + var arr = new BoolStruct[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 10; + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsOut(arr, arr.Length, out var boolsOut); + }); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 10; + NativeExportsNE.MarshallingFails.NegateBoolsOut(arr, arr.Length, out var boolsOut); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void MultiDimensionalOutArray_EnsureAllCleaned() + { + var arr = GetMultiDimensionalArray(10, 10); + var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 100; + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsOut2D(arr, arr.Length, widths, out BoolStruct[][] boolsOut); + }); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpBoolStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpBoolStruct.ExpectedCleanupNumber = 100; + NativeExportsNE.MarshallingFails.NegateBoolsOut2D(arr, arr.Length, widths, out BoolStruct[][] boolsOut); + EnforceAllElementsCleanedUpBoolStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void SingleDimensionalOutAttributedArray_EnsureAllCleaned() + { + var arr = new IntStructWrapper[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 10; + Assert.Throws(() => + NativeExportsNE.MarshallingFails.FillRangeArray(arr, 10, 0) + ); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 10; + NativeExportsNE.MarshallingFails.FillRangeArray(arr, 0, 9); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void MultiDimensionalOutAttributedArray_EnsureAllCleaned() + { + var arr = GetMultiDimensionalArray(10, 10); + var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(throwOn); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 100; + Assert.Throws(() => + NativeExportsNE.MarshallingFails.FillRangeArray2D(arr, 10, widths, 0) + ); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + // Run without throwing - this is okay only because the native code doesn't actually use the array, it creates a whole new one + EnforceAllElementsCleanedUpIntStruct.ThrowOnNthUnmarshalledElement(-1); + EnforceAllElementsCleanedUpIntStruct.ExpectedCleanupNumber = 100; + NativeExportsNE.MarshallingFails.FillRangeArray2D(arr, 10, widths, 0); + EnforceAllElementsCleanedUpIntStruct.AssertAllHaveBeenCleaned(); + } + + [Fact] + public void SingleDimensionalRefArray_EnsureLastIndexArrayIsTracked() + { + var arr = new BoolStruct[10]; + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStruct.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsRef(ref arr, arr.Length); + }); + } + } + + [Fact] + public void MultiDimensionalRefArray_EnsureOuterArrayLastIndexArrayIsTracked() + { + var arr = GetMultiDimensionalArray(10, 10); + foreach (var throwOn in new int[] { 0, 1, 5, 9 }) + { + EnforceLastElementMarshalledCleanupBoolStructArray.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsRef2D_LastElementMarshalling(ref arr, arr.Length); + }); + } + } + + [Fact] + public void MultiDimensionalRefArray_EnsureInnerArraysAreCleared() + { + var arr = GetMultiDimensionalArray(10, 10); + var widths = new int[10] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }; + foreach (var throwOn in new int[] { 0, 1, 45, 99 }) + { + EnforceClearedMemoryCleanup.ThrowOnNthMarshalledElement(throwOn); + Assert.Throws(() => + { + NativeExportsNE.MarshallingFails.NegateBoolsRef2D_ClearMarshalling(ref arr, arr.Length, widths); + }); + } + } + } + + /// + /// Use to ensure that the generated code frees N elements. Make sure to set to the number of elements that are expected to be freed, then after calling the LibraryImport method, call . + /// + [CustomMarshaller(typeof(IntStructWrapper), MarshalMode.ElementOut, typeof(EnforceAllElementsCleanedUpIntStruct))] + static unsafe class EnforceAllElementsCleanedUpIntStruct + { + private static MarshallingExceptionManager s_IntStructWrapperMarshalling = new(0, default); + + public static void ThrowOnNthMarshalledElement(int n) + { + s_IntStructWrapperMarshalling.ThrowOnNthMarshalledElement(n); + } + public static void ThrowOnNthUnmarshalledElement(int n) + { + s_IntStructWrapperMarshalling.ThrowOnNthUnmarshalledElement(n); + } + + public static IntStructWrapper ConvertToManaged(nint unmanaged) => s_IntStructWrapperMarshalling.ConvertToManaged(unmanaged); + + /// + /// The number of elements that are expected to be cleaned up / freed. + /// + public static int ExpectedCleanupNumber { get; set; } = 0; + + public static void AssertAllHaveBeenCleaned(int remaining = 0) + { + if (ExpectedCleanupNumber - remaining != 0) + s_IntStructWrapperMarshalling.Throw($"Incorrected number of elements freed. Expected {ExpectedCleanupNumber - remaining} more elements to be freed."); + } + + public static void Free(nint obj) + { + if (ExpectedCleanupNumber-- < 0) + s_IntStructWrapperMarshalling.Throw($"Freed too many objects"); + } + } + + /// + /// Use to ensure that the generated code frees N elements. Make sure to set to the number of elements that are expected to be freed, then after calling the LibraryImport method, call . + /// + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementOut, typeof(EnforceAllElementsCleanedUpBoolStruct))] + internal static class EnforceAllElementsCleanedUpBoolStruct + { + private static MarshallingExceptionManager s_BoolStructMarshalling = new(0, default); + + public static void ThrowOnNthMarshalledElement(int n) + { + s_BoolStructMarshalling.ThrowOnNthMarshalledElement(n); + } + public static void ThrowOnNthUnmarshalledElement(int n) + { + s_BoolStructMarshalling.ThrowOnNthUnmarshalledElement(n); + } + + public static BoolStruct ConvertToManaged(nint unmanaged) => s_BoolStructMarshalling.ConvertToManaged(unmanaged); + + /// + /// The number of elements that are expected to be cleaned up / freed. + /// + public static int ExpectedCleanupNumber { get; set; } = 0; + + public static void AssertAllHaveBeenCleaned(int remaining = 0) + { + if (ExpectedCleanupNumber - remaining != 0) + s_BoolStructMarshalling.Throw($"Incorrected number of elements freed. Expected {ExpectedCleanupNumber - remaining} more elements to be freed."); + } + + public static void Free(nint obj) + { + if (ExpectedCleanupNumber-- < 0) + s_BoolStructMarshalling.Throw($"Freed too many objects"); + } + } + + /// + /// Use to ensure that the generated code only frees elements that have been marshalled. It will create a dummy pointer for marshalled elements, + /// throw an exception when marshaling the Nth element, and ensure all freed memory is the dummy pointer. This will not properly marshal elements, + /// so the pinvoke should not be run if it will access marshalled objects. Make sure to call ThrowOnNthMarshalledElement such that marshalling + /// the array will fail before the pinvoke is run. + /// + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementRef, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementOut, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + [CustomMarshaller(typeof(char), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStruct))] + static class EnforceLastElementMarshalledCleanupBoolStruct + { + private static MarshallingExceptionManager s_BoolStructMarshalling = new(_dummyPtr, default); + + public static void ThrowOnNthMarshalledElement(int n) => s_BoolStructMarshalling.ThrowOnNthMarshalledElement(n); + + static nint _dummyPtr => 0xA1FA1FA; + + public static nint ConvertToUnmanaged(BoolStruct managed) => s_BoolStructMarshalling.ConvertToUnmanaged(managed); + + public static void Free(nint obj) + { + if (obj != _dummyPtr) + s_BoolStructMarshalling.Throw($"Freed unmarshalled pointer: {obj}"); + } + + public static nint ConvertToUnmanaged(char managed) => throw new NotImplementedException(); + + public static BoolStruct ConvertToManaged(nint unmanaged) => throw new NotImplementedException(); + } + + /// + /// Use to ensure that the generated code only frees elements that have been marshalled. It will create a dummy pointer for marshalled elements, + /// throw an exception when marshaling the Nth element, and ensure all freed memory is the dummy pointer. This will not properly marshal elements, + /// so the pinvoke should not be run if it will access marshalled objects. Make sure to call ThrowOnNthMarshalledElement such that marshalling + /// the array will fail before the pinvoke is run. + /// + [CustomMarshaller(typeof(BoolStruct[]), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStructArray))] + [CustomMarshaller(typeof(BoolStruct[]), MarshalMode.ElementRef, typeof(EnforceLastElementMarshalledCleanupBoolStructArray))] + static class EnforceLastElementMarshalledCleanupBoolStructArray + { + private static MarshallingExceptionManager s_BoolStructArrayMarshalling = new(_dummyPtr, default); + + public static void ThrowOnNthMarshalledElement(int n) => s_BoolStructArrayMarshalling.ThrowOnNthMarshalledElement(n); + + static nint _dummyPtr => 0xA1FA1FA; + + public static nint ConvertToUnmanaged(BoolStruct[] managed) => s_BoolStructArrayMarshalling.ConvertToUnmanaged(managed); + + public static void Free(nint obj) + { + if (obj != _dummyPtr) + s_BoolStructArrayMarshalling.Throw($"Freed unmarshalled pointer: {obj}"); + } + + public static BoolStruct[] ConvertToManaged(nint unmanaged) => throw new NotImplementedException(); + } + + + /// + /// Use to ensure that an array is cleared before elements are marshalled. It will create a dummy pointer for marshalled elements, throw an exception when marshaling the Nth element, + /// and ensure all freed memory is either the dummy pointer or null. This will not properly marshal elements, so the pinvoke should not be run if it will access marshalled objects. + /// Make sure to call ThrowOnNthMarshalledElement such that marshalling the array will fail before the pinvoke is run. + /// + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementIn, typeof(EnforceClearedMemoryCleanup))] + [CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementRef, typeof(EnforceClearedMemoryCleanup))] + static class EnforceClearedMemoryCleanup + { + private static MarshallingExceptionManager s_exceptionManager = new(_dummyPtr, default); + + public static void ThrowOnNthMarshalledElement(int n) => s_exceptionManager.ThrowOnNthMarshalledElement(n); + + public static int ThrowOnElementNumber { get; set; } = -1; + + static nint _dummyPtr => 0xA1FA1FA; + + public static nint ConvertToUnmanaged(BoolStruct managed) => s_exceptionManager.ConvertToUnmanaged(managed); + + public static BoolStruct ConvertToManaged(nint unmanaged) => throw new NotImplementedException(); + + public static void Free(nint obj) + { + if (obj != _dummyPtr && obj != 0) + s_exceptionManager.Throw($"Freed unmarshalled pointer: {obj}"); + } + } + + internal class MarshallingExceptionManager + { + private int _marshalledCount = 0; + private int _unmarshalledCount = 0; + private int _throwOnMarshallingElement = -1; + private int _throwOnUnmarshallingElement = -1; + private readonly nint _marshalledValue; + private readonly TManaged _unmarshalledValue; + + public MarshallingExceptionManager(nint marshalledValue, TManaged unmarshalledValue) + { + _marshalledValue = marshalledValue; + _unmarshalledValue = unmarshalledValue; + } + + /// + /// Force marshalling to fail on the nth element. + /// + /// + public void ThrowOnNthMarshalledElement(int n) + { + _marshalledCount = 0; + _throwOnMarshallingElement = n; + } + + /// + /// Force unmarshalling to fail on the nth element. + /// + public void ThrowOnNthUnmarshalledElement(int n) + { + _unmarshalledCount = 0; + _throwOnUnmarshallingElement = n; + } + + public nint ConvertToUnmanaged(TManaged managed) + { + if (_marshalledCount++ == _throwOnMarshallingElement) + { + _marshalledCount = 0; + _throwOnMarshallingElement = -1; + throw new ArgumentException("Marshalling failed"); + } + return _marshalledValue; + } + + public TManaged ConvertToManaged(nint unmanaged) + { + if (_unmarshalledCount++ == _throwOnUnmarshallingElement) + { + _unmarshalledCount = 0; + _throwOnUnmarshallingElement = -1; + throw new ArgumentException("Unmarshalling failed"); + } + return _unmarshalledValue; + } + public void Throw(string message) => throw new InvalidMarshallingException(message); + + [Serializable] + private sealed class InvalidMarshallingException : Exception + { + public InvalidMarshallingException(string? message) : base(message) + { + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj index 485c95540f8f17..ae35ddbf18fbaa 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/LibraryImportGenerator.Tests.csproj @@ -1,10 +1,11 @@ - + $(NetCoreAppCurrent) true true false None + true diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs index b5c393d3b10fb1..342e2917fa6ae5 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs @@ -128,6 +128,27 @@ public static byte FillRange([DNNE.C99Type("struct int_struct_wrapper*")] IntStr return 1; } + [UnmanagedCallersOnly(EntryPoint = "fill_range_array_2d")] + [DNNE.C99DeclCode("struct int_struct_wrapper;")] + public static byte FillRange2D([DNNE.C99Type("struct int_struct_wrapper**")] IntStructWrapperNative** numValues, int length, int* widths, int start) + { + if (numValues == null) + { + return 0; + } + + for (int i = 0; i < length; i++) + { + numValues[i] = (IntStructWrapperNative*)Marshal.AllocCoTaskMem(sizeof(IntStructWrapperNative) * widths[i]); + for (int j = 0; j < widths[i]; j++, start++) + { + numValues[i][j] = new IntStructWrapperNative { value = start }; + } + } + + return 1; + } + [UnmanagedCallersOnly(EntryPoint = "double_values")] [DNNE.C99DeclCode("struct int_struct_wrapper { int value; };")] public static void DoubleValues([DNNE.C99Type("struct int_struct_wrapper*")] IntStructWrapperNative* numValues, int length) @@ -291,6 +312,25 @@ public static void NegateBoolStructsRef( } } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_ref_2d")] + [DNNE.C99DeclCode("struct bool_struct;")] + public static void NegateBoolStructsRef2D( + [DNNE.C99Type("struct bool_struct**")] BoolStructMarshaller.BoolStructNative*** array, + int length, + int* widths) + { + for (int i = 0; i < length; i++) + { + for (int j = 0; j < widths[i]; j++) + { + BoolStructMarshaller.BoolStructNative boolStruct = *(array[i][j]); + (*array)[i][j].b1 = (byte)(boolStruct.b1 != 0 ? 0 : 1); + (*array)[i][j].b2 = (byte)(boolStruct.b2 != 0 ? 0 : 1); + (*array)[i][j].b3 = (byte)(boolStruct.b3 != 0 ? 0 : 1); + } + } + } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_out")] [DNNE.C99DeclCode("struct bool_struct;")] public static void NegateBoolStructsOut( @@ -301,6 +341,21 @@ public static void NegateBoolStructsOut( *outArray = NegateBoolStructsImpl(array, length); } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_out_2d")] + [DNNE.C99DeclCode("struct bool_struct;")] + public static void NegateBoolStructsOut2D( + [DNNE.C99Type("struct bool_struct**")] BoolStructMarshaller.BoolStructNative** array, + int length, + int* widths, + [DNNE.C99Type("struct bool_struct***")] BoolStructMarshaller.BoolStructNative*** outArray) + { + *outArray = (BoolStructMarshaller.BoolStructNative**)Marshal.AllocCoTaskMem(sizeof(BoolStructMarshaller.BoolStructNative**) * length); + for (int i = 0; i < length; i++) + { + (*outArray)[i] = NegateBoolStructsImpl(array[i], widths[i]); + } + } + [UnmanagedCallersOnly(EntryPoint = "negate_bool_struct_array_return")] [DNNE.C99DeclCode("struct bool_struct;")] [return: DNNE.C99Type("struct bool_struct*")] diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx index 7055b2beec656b..008e12e8d08687 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/Resources/Strings.resx @@ -283,4 +283,7 @@ The key in the enveloped message is not valid or could not be decoded. + + PKCS12 (PFX) without a supplied password has exceeded maximum allowed iterations. See https://go.microsoft.com/fwlink/?linkid=2233907 for more information. + diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj index bc67ba45ef1db6..e66b1b69b1b8a3 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/System.Security.Cryptography.Pkcs.csproj @@ -1,13 +1,14 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.1;netstandard2.0;$(NetFrameworkMinimum) + $(DefineConstants);BUILDING_PKCS true true $(NoWarn);CA5384 true - false - 1 + true + 2 Provides support for PKCS and CMS algorithms. Commonly Used Types: @@ -618,6 +619,8 @@ System.Security.Cryptography.Pkcs.EnvelopedCms Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + new X509Certificate(blob); + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountNotExceedingDefaultLimit(string name, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = iterationCount; + _ = blob; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + X509Certificate cert = Import(pfxInfo.Blob); + Assert.True(cert.Subject == "CN=test" || cert.Subject == "CN=potato"); + }, name).Dispose(); + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueTwo_ActsAsDefaultLimit_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = password; + _ = iterationCount; + _ = blob; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -2); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + CryptographicException ce = Assert.Throws(() => Import(pfxInfo.Blob)); + Assert.Contains("2233907", ce.Message); + }, name).Dispose(); + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueZero_IterationCountNotExceedingDefaultLimit_Throws(string name, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = iterationCount; + _ = blob; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", 0); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + CryptographicException ce = Assert.Throws(() => Import(pfxInfo.Blob)); + Assert.Contains("2233907", ce.Message); + }, name).Dispose(); + } + + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountExceedingDefaultLimit_MemberData), MemberType = typeof(PfxIterationCountTests))] + public void Import_AppDomainDataWithValueMinusOne_IterationCountExceedingDefaultLimit(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = password; + _ = blob; + _ = iterationCount; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + RemoteExecutor.Invoke((certName) => + { + AppDomain.CurrentDomain.SetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit", -1); + + PfxInfo pfxInfo = s_certificatesDictionary[certName]; + + if (OperatingSystem.IsWindows()) + { + // Opting-out with AppDomain data value -1 will still give us error because cert is beyond Windows limit. + // But we will get the CryptoThrowHelper+WindowsCryptographicException. + PfxIterationCountTests.VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(pfxInfo.Blob)); + } + else + { + Assert.NotNull(Import(pfxInfo.Blob)); + } + }, name).Dispose(); + } + + public static readonly Dictionary s_certificatesDictionary + = PfxIterationCountTests.s_Certificates.ToDictionary((c) => c.Name); + } + + public class PfxIterationCountTests_CustomLimit_X509Certificate2 : PfxIterationCountTests_CustomAppDomainDataLimit + { + internal override X509Certificate Import(byte[] blob) => new X509Certificate2(blob); + } + + public class PfxIterationCountTests_CustomLimit_X509Certificate2Collection : PfxIterationCountTests_CustomAppDomainDataLimit + { + internal override X509Certificate Import(byte[] blob) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(blob); + return collection[0]; + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs new file mode 100644 index 00000000000000..15a39d05755b3d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public class PfxIterationCountTests_X509Certificate : PfxIterationCountTests + { + internal override X509Certificate Import(byte[] blob) + => new X509Certificate(blob); + + internal override X509Certificate Import(byte[] blob, string password) + => new X509Certificate(blob, password); + + internal override X509Certificate Import(byte[] blob, SecureString password) + => new X509Certificate(blob, password); + + internal override X509Certificate Import(string fileName) + => new X509Certificate(fileName); + + internal override X509Certificate Import(string fileName, string password) + => new X509Certificate(fileName, password); + + internal override X509Certificate Import(string fileName, SecureString password) + => new X509Certificate(fileName, password); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs new file mode 100644 index 00000000000000..6e4697f406548d --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public class PfxIterationCountTests_X509Certificate2 : PfxIterationCountTests + { + internal override X509Certificate Import(byte[] blob) + => new X509Certificate2(blob); + + internal override X509Certificate Import(byte[] blob, string password) + => new X509Certificate2(blob, password); + + internal override X509Certificate Import(byte[] blob, SecureString password) + => new X509Certificate2(blob, password); + + internal override X509Certificate Import(string fileName) + => new X509Certificate2(fileName); + + internal override X509Certificate Import(string fileName, string password) + => new X509Certificate2(fileName, password); + + internal override X509Certificate Import(string fileName, SecureString password) + => new X509Certificate2(fileName, password); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs new file mode 100644 index 00000000000000..40b8ac11da8f43 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.X509Certificate2Collection.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public class PfxIterationCountTests_X509Certificate2Collection : PfxIterationCountTests + { + internal override X509Certificate Import(byte[] blob) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(blob); + return collection[0]; + } + + internal override X509Certificate Import(byte[] blob, string password) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(blob, password, X509KeyStorageFlags.DefaultKeySet); + return collection[0]; + } + + // X509Certificate2Collection.Import does not support SecureString so we just make this work. + internal override X509Certificate Import(byte[] blob, SecureString password) + => new X509Certificate2(blob, password); + + internal override X509Certificate Import(string fileName) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(fileName); + return collection[0]; + } + + internal override X509Certificate Import(string fileName, string password) + { + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Import(fileName, password, X509KeyStorageFlags.DefaultKeySet); + return collection[0]; + } + + // X509Certificate2Collection.Import does not support SecureString so we just make this work. + internal override X509Certificate Import(string fileName, SecureString password) + => new X509Certificate2(fileName, password); + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs new file mode 100644 index 00000000000000..18ab1381a026f7 --- /dev/null +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxIterationCountTests.cs @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.XUnitExtensions; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + public abstract partial class PfxIterationCountTests + { + private const long DefaultIterationLimit = 600_000; + internal abstract X509Certificate Import(byte[] blob); + internal abstract X509Certificate Import(byte[] blob, string password); + internal abstract X509Certificate Import(byte[] blob, SecureString password); + internal abstract X509Certificate Import(string fileName); + internal abstract X509Certificate Import(string fileName, string password); + internal abstract X509Certificate Import(string fileName, SecureString password); + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData))] + public void Import_IterationCounLimitNotExceeded_Succeeds(string name, bool usesPbes2, byte[] blob, long iterationCount) + { + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) + { + X509Certificate cert = Import(blob); + Assert.True(cert.Subject == "CN=test" || cert.Subject == "CN=potato"); + } + } + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))] + public void Import_IterationCountLimitExceeded_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + _ = password; + _ = iterationCount; + + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + CryptographicException ce = Assert.Throws(() => Import(blob)); + Assert.Contains("2233907", ce.Message); + } + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_IterationCountExceedingDefaultLimit_MemberData))] + public void ImportWithPasswordOrFileName_IterationCountLimitExceeded(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + using (TempFileHolder tempFile = new TempFileHolder(blob)) + { + string fileName = tempFile.FilePath; + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) + { + Assert.NotNull(Import(blob, password)); + Assert.NotNull(Import(blob, PfxTests.GetSecureString(password))); + + Assert.NotNull(Import(fileName)); + Assert.NotNull(Import(fileName, password)); + Assert.NotNull(Import(fileName, PfxTests.GetSecureString(password))); + } + else + { + if (OperatingSystem.IsWindows()) + { + // Specifying password or importing from file will still give us error because cert is beyond Windows limit. + // But we will get the CryptoThrowHelper+WindowsCryptographicException. + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(blob, password)); + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(blob, PfxTests.GetSecureString(password))); + + // Using a file will do as above as well. + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(fileName)); + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(fileName, password)); + VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(() => Import(fileName, PfxTests.GetSecureString(password))); + } + } + } + } + + internal static void VerifyThrowsCryptoExButDoesNotThrowPfxWithoutPassword(Action action) + { + CryptographicException ce = Assert.ThrowsAny(action); + Assert.DoesNotContain("2233907", ce.Message); + } + + [ConditionalTheory] + [MemberData(nameof(GetCertsWith_NonNullOrEmptyPassword_MemberData))] + public void Import_NonNullOrEmptyPasswordExpected_Throws(string name, string password, bool usesPbes2, byte[] blob, long iterationCount) + { + if (usesPbes2 && !PfxTests.Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + CryptographicException ce = Assert.ThrowsAny(() => Import(blob)); + + if (PfxTests.IsPkcs12IterationCountAllowed(iterationCount, PfxTests.DefaultIterations)) + { + Assert.NotNull(Import(blob, password)); + Assert.NotNull(Import(blob, PfxTests.GetSecureString(password))); + + + using (TempFileHolder tempFile = new TempFileHolder(blob)) + { + string fileName = tempFile.FilePath; + Assert.NotNull(Import(fileName, password)); + Assert.NotNull(Import(fileName, PfxTests.GetSecureString(password))); + } + } + } + + internal static readonly List s_Certificates = GetCertificates(); + + internal static List GetCertificates() + { + List certificates = new List(); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12NoPassword2048RoundsHex), null, 2048 * 3, true, TestData.Pkcs12NoPassword2048RoundsHex.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12OpenSslOneCertDefaultEmptyPassword), "", 2048 * 3, true, TestData.Pkcs12OpenSslOneCertDefaultEmptyPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12OpenSslOneCertDefaultNoMac), null, 2048, true, TestData.Pkcs12OpenSslOneCertDefaultNoMac.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12NoPasswordRandomCounts), null, 938, true, TestData.Pkcs12NoPasswordRandomCounts)); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12WindowsDotnetExportEmptyPassword), "", 6000, false, TestData.Pkcs12WindowsDotnetExportEmptyPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12MacosKeychainCreated), null, 4097, false, TestData.Pkcs12MacosKeychainCreated.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12BuilderSaltWithMacNullPassword), null, 120000, true, TestData.Pkcs12BuilderSaltWithMacNullPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12Builder3DESCBCWithNullPassword), null, 30000, false, TestData.Pkcs12Builder3DESCBCWithNullPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12Builder3DESCBCWithEmptyPassword), "", 30000, false, TestData.Pkcs12Builder3DESCBCWithEmptyPassword.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12WindowsWithCertPrivacyPasswordIsOne), "1", 4000, false, TestData.Pkcs12WindowsWithCertPrivacyPasswordIsOne.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12WindowsWithoutCertPrivacyPasswordIsOne), "1", 4000, false, TestData.Pkcs12WindowsWithoutCertPrivacyPasswordIsOne.HexToByteArray())); + certificates.Add(new PfxInfo( + nameof(TestData.Pkcs12NoPassword600KPlusOneRoundsHex), null, 600_001 * 3, true, TestData.Pkcs12NoPassword600KPlusOneRoundsHex.HexToByteArray())); + + return certificates; + } + + public static IEnumerable GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData() + { + foreach (PfxInfo p in s_Certificates.Where( + c => c.IterationCount <= DefaultIterationLimit && + string.IsNullOrEmpty(c.Password))) + { + yield return new object[] { p.Name, p.UsesPbes2, p.Blob, p.IterationCount }; + } + } + + public static IEnumerable GetCertsWith_IterationCountExceedingDefaultLimit_MemberData() + { + foreach (PfxInfo p in s_Certificates.Where(c => c.IterationCount > DefaultIterationLimit)) + { + yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount }; + } + } + + public static IEnumerable GetCertsWith_NonNullOrEmptyPassword_MemberData() + { + foreach(PfxInfo p in s_Certificates.Where(c => !string.IsNullOrEmpty(c.Password))) + { + yield return new object[] { p.Name, p.Password, p.UsesPbes2, p.Blob, p.IterationCount }; + } + } + } + + public class PfxInfo + { + internal string Name { get; set; } + internal string? Password { get; set; } + internal long IterationCount { get; set; } + internal bool UsesPbes2 { get; set; } + internal byte[] Blob { get; set; } + + internal PfxInfo(string name, string? password, long iterationCount, bool usesPbes2, byte[] blob) + { + Name = name; + Password = password; + IterationCount = iterationCount; + UsesPbes2 = usesPbes2; + Blob = blob; + } + } +} diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs index b7d8b6de5116ac..cfc261776a6959 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs @@ -1,14 +1,28 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.XUnitExtensions; using System.Collections.Generic; +using System.Reflection; +using System.Text; using Test.Cryptography; +using Microsoft.DotNet.RemoteExecutor; using Xunit; +using System.Linq; namespace System.Security.Cryptography.X509Certificates.Tests { public static class PfxTests { + private const long UnspecifiedIterations = -2; + private const long UnlimitedIterations = -1; + internal const long DefaultIterations = 600_000; + private const long DefaultIterationsWindows = 600_000; + + // We don't know for sure this is a correct Windows version when this support was added but + // we know for a fact lower versions don't support it. + public static bool Pkcs12PBES2Supported => !PlatformDetection.IsWindows || PlatformDetection.IsWindows10Version1703OrGreater; + public static IEnumerable BrainpoolCurvesPfx { get @@ -448,6 +462,65 @@ public static void CollectionPerphemeralImport_HasKeyName() } } + + [ConditionalTheory] + [MemberData(memberName: nameof(PfxIterationCountTests.GetCertsWith_IterationCountNotExceedingDefaultLimit_AndNullOrEmptyPassword_MemberData), MemberType = typeof(PfxIterationCountTests))] + public static void TestIterationCounter(string name, bool usesPbes2, byte[] blob, int iterationCount) + { + _ = iterationCount; + + MethodInfo method = typeof(X509Certificate).GetMethod("GetIterationCount", BindingFlags.Static | BindingFlags.NonPublic); + GetIterationCountDelegate target = method.CreateDelegate(); + + if (usesPbes2 && !Pkcs12PBES2Supported) + { + throw new SkipTestException(name + " uses PBES2 which is not supported on this version."); + } + + try + { + long count = (long)target(blob); + Assert.Equal(iterationCount, count); + } + catch (Exception e) + { + throw new Exception($"There's an error on certificate {name}, see inner exception for details", e); + } + } + + internal static bool IsPkcs12IterationCountAllowed(long iterationCount, long allowedIterations) + { + if (allowedIterations == UnlimitedIterations) + { + return true; + } + + if (allowedIterations == UnspecifiedIterations) + { + allowedIterations = DefaultIterations; + } + + Assert.True(allowedIterations >= 0); + + return iterationCount <= allowedIterations; + } + + // This is a horrible way to produce SecureString. SecureString is deprecated and should not be used. + // This is only reasonable because it is a test driver. + internal static SecureString? GetSecureString(string password) + { + if (password == null) + return null; + + SecureString secureString = new SecureString(); + foreach (char c in password) + { + secureString.AppendChar(c); + } + + return secureString; + } + // Keep the ECDsaCng-ness contained within this helper method so that it doesn't trigger a // FileNotFoundException on Unix. private static void AssertEccAlgorithm(ECDsa ecdsa, string algorithmId) @@ -476,5 +549,7 @@ private static X509Certificate2 Rewrap(this X509Certificate2 c) c.Dispose(); return newC; } + + internal delegate ulong GetIterationCountDelegate(ReadOnlySpan pkcs12); } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs index 89882f4de5a33c..753bec3b88b6bd 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/RevocationTests/AiaTests.cs @@ -53,6 +53,41 @@ public static void EmptyAiaResponseIsIgnored() } } + [Theory] + [InlineData(AiaResponseKind.Pkcs12, true)] + [InlineData(AiaResponseKind.Cert, false)] + public static void AiaAcceptsCertTypesAndIgnoresNonCertTypes(AiaResponseKind aiaResponseKind, bool mustIgnore) + { + CertificateAuthority.BuildPrivatePki( + PkiOptions.AllRevocation, + out RevocationResponder responder, + out CertificateAuthority root, + out CertificateAuthority intermediate, + out X509Certificate2 endEntity, + pkiOptionsInSubject: false, + testName: Guid.NewGuid().ToString()); + + using (responder) + using (root) + using (intermediate) + using (endEntity) + using (X509Certificate2 rootCert = root.CloneIssuerCert()) + { + responder.AiaResponseKind = aiaResponseKind; + + using (ChainHolder holder = new ChainHolder()) + { + X509Chain chain = holder.Chain; + chain.ChainPolicy.CustomTrustStore.Add(rootCert); + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.VerificationTime = endEntity.NotBefore.AddMinutes(1); + chain.ChainPolicy.UrlRetrievalTimeout = DynamicRevocationTests.s_urlRetrievalLimit; + + Assert.NotEqual(mustIgnore, chain.Build(endEntity)); + } + } + } + [Fact] [SkipOnPlatform(PlatformSupport.MobileAppleCrypto, "CA store is not available")] public static void DisableAiaOptionWorks() diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj index a284d8edf478ca..84f30311a63b8e 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj @@ -49,6 +49,11 @@ + + + + + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs index 4ce70ccbf4412b..a6efa3a1f19173 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TempFileHolder.cs @@ -20,6 +20,13 @@ public TempFileHolder(ReadOnlySpan content) } } + public TempFileHolder(byte[] content) + { + FilePath = Path.GetTempFileName(); + + File.WriteAllBytes(FilePath, content); + } + public void Dispose() { try diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs index 92d8606e3093b4..0e0202fa119df0 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs @@ -2943,5 +2943,1221 @@ internal static DSAParameters GetDSA1024Params() "MAoGCCqGSM49BAMCA0cAMEQCIHafyKHQhv+03DaOJpuotD+jNu0Nc9pUI9OA8pUY\n" + "3+qJAiBsqKjtc8LuGtUoqGvxLLQJwJ2QNY/qyEGtaImlqTYg5w==\n" + "-----END CERTIFICATE-----"; + + public static readonly byte[] PfxWithNoPassword = ( + "308205DB0201033082059706092A864886F70D010701A0820588048205843082" + + "0580308202F106092A864886F70D010701A08202E2048202DE308202DA308202" + + "D6060B2A864886F70D010C0A0102A08202AE308202AA3024060A2A864886F70D" + + "010C010330160410286B4EFF0202AFE16583E50C3EB8F38F020207D004820280" + + "C3452B3850AE69FCC0AC426FF3A0421477813259C128D643452219EEF71EBCAB" + + "5E7054B7A195E3F945222864CA37D8F67DDFA9136A93CD7FEAD86F00D4179F1C" + + "557253253C6235295499729C564DE2CE30E131C0D9B3E1BDBB211F8FA9E78B7B" + + "088C63137DF44CF50C293E082E7C57A8D0CB0404D1F5B9D1491F4EF9045181D3" + + "8D528C61F49EB3F1CF11ABB60270CBC10AC4BAF115A5AB52EA22FE4406743695" + + "7DDC1BFEE0C6BDC097BDF092AC6D11CABAE497FC10564E7E7797BC6028CBD75B" + + "1A2339329D439F6557B3CEB77489467FC8990EE832D48E2FF65A7BCB20E2DBBD" + + "F81C762F688E2EE43822CF9DEDE11914DD982FAB2AC141496D912396F6F67E3C" + + "D04D0617F8EC2BE6D35AF9860C384DB8C21FD0B00494FA3188983E6200DE90B3" + + "E6E662C5B07AB202A1B9C3F10F03B88E677EC7BDC2873AA4DFF873DCD714AD39" + + "42C33E63442A855C709F58063D836F8CA77DB9D208F3DB2552D7AC611409E8BA" + + "942BE520D9B4951AB844892D123DF550BA4F22D255069AD77E6C14D730128FAD" + + "3736551CDBEED2022417A948B1BD2567C39DFB561F251C45D2F4B5711B4AC82A" + + "09226403432FEEEEAC5F54590CC2EC7925768651ACF42C32A114ED133718FB1A" + + "9FB0DCC35C10640226F7587BD4EA67C10EF963113D03988C82B3A0B43B1B60ED" + + "BE0A7CBCB6422CD9695BF206A190E8EA6F87E2FABB33549081EFA7A8B04CA044" + + "9DF52E133556781511CDFCBDC55B487DA51C8D476FB635896FD0C71754B2EEE9" + + "A395F355F4A56CCB8CE75D65F73AE8DE80215EA7CA9129FD90EC48ECF26828A6" + + "0E471FA5F34471AD1C21AD200E16C4E4E99FA55B5CF75BC4BF68D1A975E8276F" + + "5EBD47EEB21DB06092F51AEE6BDAA2CDBC9387620A2B3983247E9AA93252D49A" + + "3115301306092A864886F70D01091531060404000000003082028706092A8648" + + "86F70D010706A0820278308202740201003082026D06092A864886F70D010701" + + "3024060A2A864886F70D010C010330160410127070F8C0D10011CBE0CC8489A3" + + "0C71020207D080820238C151B340B678AE8CAD6C6B11E0661E91FD1F4107F0DB" + + "687F039362D88AFF382E3557A75157D8A6D93F0777AD41D7520D32916677699A" + + "EC3DAEE462344BF18410EE07E83811EC26569FF9CD8D13A77F387D6E7C5C21C1" + + "6BC9936DB1B8AB614A8B4B6F9975E4A0A5DFCE29EF14E833FB2526805901A782" + + "724AF6BA2A80E93A4C4BA07B1C1319169E200A4B7AB100AE2CA135512919120A" + + "1D1AB57EF6DED00144F87D051391676D205196ABB4B211698BF137436D6E39D6" + + "719737B66AD2E76D5766D36E87108D79145021C77328A9F2ADDF44EC2A95EEA3" + + "86DCA32FB53D0AA92FB5C5BB7B49CB1F1755ABF195C7274702681C616C21BB05" + + "817B5FD344FC25CC6145A4FFE36F4D5BC131434E6C44BD14769EB08FBDA0D1A0" + + "6DCF2D061FA4A2FCC45A30125680507AACEE7903ABA0C1D36395925A82741797" + + "CF93A11F249D7E7D8228F8F6AFD03FB317D1F2BDB319C0AEF15E19E9DB1067B1" + + "A6CC12CA458C33BAB31C3F275C45A956F71CFF939F393EC7D20E13B397E64263" + + "702B54DD228D0E1275B39A77B3B1A28EFD5C7DF2643CAF7AAF8574988CDF4112" + + "E057F715331F6E75462E6C948BFB92C5BC81B84FBB47FB97AEB3D8C228388B94" + + "CDFA0E2A48F05A32EA9F2CDFAE2B0CEFF815531B148C358ECE1D23F7B793A1FF" + + "ECE491E990BDF231756600B87FA2F7F3AD2C2AA2F6DB42FC6D62766F28F60436" + + "FFA4993C87BE6631D7CE6C06C5B7AE7218450C504ADB401B9FBA5FB2FC6A8289" + + "B42D51B4E1AF159AE7F3A63BA8644C8C5A99F108FC25A27DE54E268AF8A259D9" + + "F6E3303B301F300706052B0E03021A0414AF311074EBABE699402460BFFFE14E" + + "4D7314FCB4041469835268466D1390373566F7034C4736346CD17D020207D0").HexToByteArray(); + + internal static readonly byte[] Pkcs12NoPasswordRandomCounts = + Convert.FromBase64String(@" + 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 + mSdzI1U6Td0CASo="); + + internal const string Pkcs12NoPassword2048RoundsHex = + "308209CF0201033082098506092A864886F70D010701A0820976048209723082" + + "096E308203E206092A864886F70D010706A08203D3308203CF020100308203C8" + + "06092A864886F70D010701305706092A864886F70D01050D304A302906092A86" + + "4886F70D01050C301C040887A8C4D7DB154CC402020800300C06082A864886F7" + + "0D02090500301D060960864801650304012A041028529AA9F7079F5031C52A23" + + "8A23CD4780820360ED47A5097F8A6C7B6EDD1989CD19C67B8A59DBF6CD22F7B8" + + "36A4B8D9BAAD54666FA9F022CDF366BC1B4A47604C4A0B67C09F2DBB8F75D185" + + "B62DF310817E24FE71A47246831C58670A27A5693CAFC52EB730B7BC0CF00145" + + "A9E4D6784D3A49C524546415EA6448D991C5C83FACAA4C1FECF198DA5B8CA9B1" + + "09346B723238359CC18D1CC28B185AA3860B082086F9FD909F3BA3D94C9238BB" + + "CF8AF18C0A56E6A88E7E0F4F15675770C812F805604743B1E8E683FFEB3FA4C9" + + "9D2C6B00A858050DCFE12C0DB3471B678657C7E28C074277165D714FC4A6E193" + + "C118C676FD2B2F97B36D8EDAFC3332609F192EF98D3ACAF1EDBCB03A2DBB9B0C" + + "8AEF748A5BF66F1EDD9C7C8A81638D644F9ADC99DDD6BC7FA7FDEDFF044D47C1" + + "6F62280D80526D05F17D5DBB44209A3F27CF88B881227D5685DB6BAA22914D0C" + + "E0B01D9997F9A429B4294940BA75FBB08C7C7EEFCD77B7BAD0DBF3E418F4B551" + + "ACAEC537DDA914DD0BE933181A86B433640C1E10609D96D093544D119727D1F8" + + "49060303189EA33B8FF8950493909B0963EA4BC8999BE78D2D2F1315F96B24C1" + + "DE6A925C0DE3C862788B2AFC56BF343E63E1274D0B8652C6C49033E1B21AA283" + + "0AB2A1406291D215B799D8CB5CB6CA0D3B0458C51EBFB01207E96DA04FDE7C24" + + "F32E48A0B4E48EDE150B13D8B2B1D3B736BC4BA54F800DA9F980F7CB9F23B7DF" + + "8C343F980ADB0752E2978D4C1069337A631E15D945D8EB858FA6D1548C230269" + + "21D0413F13FD4C94A1BB8897040AC3CBF13DF42FFCA7D0CF76FF08C68893E45A" + + "061700E4BC3B005FDF4E8A04323B98D07ED037E4A341E49E43F2D2BABB0CE6B9" + + "4D260BF720A7B864DFB12B22D28F4992C91A16E30346252191EB60A06C23BB6E" + + "1FEAABFFCCD57C0A2516E8015E9B329C97D99704E653EBE04BBF26199B11A2B7" + + "E30FCBCD2C57A1389B0747E1B9896C6CED2C86D721DEE424120E0347A05B57F9" + + "19FA1FA334512C1EA43205E5B1A56BD1F490C5EC3CFEA17CF1E8EC4686DD6150" + + "0C420D03E6E807491B24ECB6E64F210BC8029399C153E62705E80FF358E1A705" + + "DE3EC20DD3AB6651EB51E7F7F2729ECB9BEF94B9E1A685555DC075453072AA06" + + "5C8C821033DB91D1DE64CB085E09721580FB01AEE2C105E62177D88E25B4EA54" + + "4605636CA3261107DF7CB8FB2661CBA0B855726F8F3F087B95EB257B523B007B" + + "45B9C71E030FBDCF3082058406092A864886F70D010701A08205750482057130" + + "82056D30820569060B2A864886F70D010C0A0102A08205313082052D30570609" + + "2A864886F70D01050D304A302906092A864886F70D01050C301C04083D689F19" + + "C613307C02020800300C06082A864886F70D02090500301D0609608648016503" + + "04012A04107F45F9CB7E9F7A54479C6B260310BF0E048204D0C37C420A86E386" + + "22F3EA79EFDA069F9A0542207ACC6EC2B7D497D06C2F0E20FC362F637C032D86" + + "72B9A0A393F0DE872B19668D37C35CBA4DA6407D80A1A61998BEDBB01713D41D" + + "741C5D4A03B877B2CB6F66295B3C7E3955AEE9F8BA250086355CA8D340850825" + + "28F3544F9DFFD19D764DA15E6D178E7D8D843E0E8FB0FBF5CD9D6203644FD6D7" + + "88754AF0372BEC11938406A27D76EFEC6974F92982F2F2D212256DF3122CE631" + + "7C079B14D9B14D8E8AE31EBFB76754DB6D5497DC3F7DEDB73DC2E65F722BB3DE" + + "D1D217628DDC42EFD646501B8B8E085996D87F11E3B29B85FBAD0AADF71A391D" + + "92F11DA38286F7C57D12F3923D334D3EE186098B88A77869514DE08FF1D09675" + + "4D6FB2978CDFCE051F7A0AF5E27BC8B0DDFD9230FB292EDF4F8893BA7C1CF8C1" + + "B91B527E13B93D0B32E7A130D829D928281655FF93A60220194777EA4903B577" + + "EE7D12FD585D69ECBE52192BC9A0731444122C13ACD45926DFE13E7F151BBC71" + + "2787DE41A1319B974DF20F0E28A2B8C247553C6A98B52F545723ED67F36DB626" + + "7BEDBE8198AEADF2AE0B177F3F2B61A53AD5EBD99F10BBF8F578AEBC780EF766" + + "F512118263A7775BBAB8D1E7D2B8E55892A59BA4E4DA74C63A90319589096AED" + + "516AC29F6DD666BE867C6E411F0A63D8EBF0A4F8F591D8E16F106DE0A63F001D" + + "373B0A72B3BFBFE27B1463F8A01CF5A4BC81988DCEE84A76ACFF3F27BB205708" + + "848F0555686E0A650280EFC7517BB433742961DE1E0B08D43EC64BBB6B2847A0" + + "01FAA219D470E553A8BA05479DDB4B3C0FE50BE45C7126084AD249B521733477" + + "473B687BBB75D47C3AEF41C72BF7612FB4ED8D9EF51CBEAD26279AE07C3A8151" + + "7E65FC8A77712D8EEE8994F1632157C3F1403DB0FD2A95C0A89D323BD9205AF0" + + "E228DABEA7EEA182B8D257BEF9D704CA0E9FAB1027F49BCB8D75C2969447EC4D" + + "59EE74B762092664AB68DB5390C8E76AD91399DA5473222DF32C96D519FDB21E" + + "3D2EB1C6D98B3A3525D1E92504E29A0DFCE59B0B982D0A8EB845A8BA4DF22CEF" + + "CEEED25773E51C5C1FC0F96A697E24995342FF82D7573479D342B7E41AD2FBEC" + + "BB6F728F8D3D964C09F9FD39239B58AA91269DEA87755C6CAF9F6F876A1EBCBF" + + "9983DF2D6BBFF81D180435B65DE95C7BD41062F123B7CCF31897CC7028F6DDED" + + "EA747F069AECA55637B9848674AB1CC4A61944C274B500E37924F7E394DCCECB" + + "93052BCA45AD66851E9CDD4194470BC2F91667C6E1F696B89A219C45CDAF1752" + + "CC8D95875EF343E90765CA366CDFC55F6D72D2590FBC47BFFA9F45BAD5C4D50B" + + "A89F117F20A934D84C972A15AC4DE8F7D105B1E0AE214BFCA16BC44C4D4A096E" + + "699057ECB1E3D9D6933CC8AB9D9E93A5194BB39FE289E6FC121A564FC049C99D" + + "6B6BFE5B11E8292CEF1E4E80453F805D5BA49BB26EBD84847F1CF238335005FE" + + "2552A972DF84618E59201798DC1FAB60188DCBF18C6B30CEC921D40B76B9BBD7" + + "458819427D0444A2421D69CE1E23D335EB6C327F8145DD3FF25EE740F7896A24" + + "AEAB3E65FA9209C18BCE8A1D28EEF053611170E3B1CB43F583D6084AD40C0035" + + "E053CC6133E67B18F12D508BA43B79E1B2D1EA0CC2B91002BFA2D286DB6CDEB3" + + "796449B33D6DA4E47CD326B8C123228E68D822DF1B8A50520EAB8A2319227415" + + "4F4EA2C604A2274AB881D6B4EC36E0C3F5104A0BBE51E061E4F09A425F797BA7" + + "545D45CB4567A39D923125302306092A864886F70D0109153116041444BBC698" + + "3FD4DB3AD40E15D39784227F2A2E60A330413031300D06096086480165030402" + + "010500042053B736831F5398BCA4DD020714A2E9B46FA9BE273F81DB5A13D27F" + + "482282DE4B04089ECC39D621BAA9ED02020800"; + + internal const string Pkcs12NoPassword600KPlusOneRoundsHex = + "308209D20201033082098706092A864886F70D010701A0820978048209743082" + + "0970308203E306092A864886F70D010706A08203D4308203D0020100308203C9" + + "06092A864886F70D010701305806092A864886F70D01050D304B302A06092A86" + + "4886F70D01050C301D04082BF1679DE99B425702030927C1300C06082A864886" + + "F70D02090500301D060960864801650304012A0410E60AE5FBE308F1D6E6820E" + + "18F85D357380820360E334B918A3971F37CFCEAAEFC215BD0773462CEF830E5F" + + "73D28190E78FA023A2EB377952BEE5927A0FBAF841C96059E4B0111880DCD6CE" + + "619B4B07DCE651642F29AE978AFD15EABE55D5E2AC94439294F15F4E4A304D88" + + "54B04555E30D251D7BD6B53F0584C5293E78F9427861EBF90BA0E41C00A4210D" + + "5208DD27C45E5C964988F00206399AA256D19103E391765F0E4E89319AA8FDAA" + + "F79856ECF1E6F5DDC9629E778446A0DB25FCF541D4815E66967124BB751ADF2F" + + "10DD658BCD76CD7854561E161FDF4300F84C5E04B91B3FE52436BBE2D7DFA2D1" + + "5D9C6E853D4F221F833FF85A985DA2010050FDC17B6013DF16B71B1FE181401B" + + "447A7CD78ADB894F310119600EBD79872CEE05254F141FF4AE317B4B19089943" + + "1FF692246DDC9D042C517FBD389EE2AC9A8DDD7214BBC010FD7A90A325DE4224" + + "D833A55B8118C5BBB003304956C98A4CC1A91EEF29BBE6DCC4F5353EE53065B4" + + "2B0011E291B81C9A8D43CF436F2A47DEB40C21547CA2E416A61740E9DC5107A0" + + "1913612DB720770788894EC2531BE2676F3CB9AE5C73D5AF35261F41D474A565" + + "0DCCE0A9A63EA6A4BE80E0726EF4C1A5805DC8888330D2973402BD0BB4017BA9" + + "D83355DB97A9EDD04D727A1A3FF796267E56494E2A89B0705EEF88805BB23D98" + + "05207982C2B43CD3FB83E8C65EAAB0DA8E5FB85D9821CACA20BD21311BF0E3EC" + + "4F309375D7AC89E9B32B1B2EFB51D45FD5F88AA066A05A775311857A192B7DFB" + + "200FF7F276C284655E30164543A53B3463BF6F8B037452544BA86764B4ACE00D" + + "F2C26B18D9F457153585432201F578F74BFE9A4F8010C3B4973C865CE175485A" + + "3EEE47538C73EDF5E3DB34D814B6525351D03648948561760CCE3F4DFE423ACA" + + "78E1F82C78476528BD35C8D02C17AD41E9796F048BFC4CCC15FE11139C1A104E" + + "469368C654FEFE69139014ED6B30E6CAB30DC7FCF1490BC91C50F1716CF348FA" + + "7EED577F7AE25219163BC1BF378271F9E676CB99227BBAE64FF8D9BBA2FBA69C" + + "6A045CD70675809F9C3EC1DD30A4542C36E4B5B52F982E8369300C7D036144E8" + + "004804F186F2F54385BBD5ADE939F2CEABA8D785DF62D54348CA76D94669C350" + + "07BE6C9A9A9CB263A9A098157B39C6B8E1368D9D7F9D9524D5CD3B9FA1EFEB9D" + + "44AFA24F2536C3A70E19DF07B7B0A68385D8572753A251648534B953717CAEBE" + + "19EABF8E36F039A2503082058506092A864886F70D010701A082057604820572" + + "3082056E3082056A060B2A864886F70D010C0A0102A08205323082052E305806" + + "092A864886F70D01050D304B302A06092A864886F70D01050C301D04088064D4" + + "32AC75560902030927C1300C06082A864886F70D02090500301D060960864801" + + "650304012A041028618CDEA80BF226578A2DA0DEFB48F9048204D070F86CDE3E" + + "25FB88321EB1D0B9E8BA8736C1954E7EC2AD3BB3B4DBFAF6ECE268FF693008CA" + + "DF785473709F6ECE9AA8F93019C5EEF6E557DD5587C3B3A85B77A3FB1871F58B" + + "0316B4A4210BC2856E5B4AF46B3BFD114AD8FEC7195CAA4D8FF578EC0A945A63" + + "1000981A56525F8AFC6F140F5DEE2193C7DE62579890ACAAF056A32CC6E7CCFE" + + "2839DAF60FD881C0D34BC450DD7F0F9378A695F27F547A73044444163670294E" + + "578FEAF5627865F297147ECBD16E45C128697063D16FF4A773ECFE2978124C06" + + "A7728C6495CC35C957A635F213D237C8D64B425ECEE868CD1B901CCBC3AADC1D" + + "CDFBB433195EDA5CBC6C11D048D7DB7C5A0443828483DADA0C63FC4FB3234A3A" + + "6F749428F371121389BE52DD5F9532B8CB86E096ABAEF67865ED7A6D9AA0AFB3" + + "98361237819188AE5592D65B450A9F99191D1E4007FA4C7067E55B495A224435" + + "E6FBB891D5CC84D929166B807C8114E26D6125C7B19B0ECAF55676F61127A75B" + + "56740D00BA582A4412301E3220EE58FC1A55B578EFB90F398B9940CC23581A29" + + "804244A0C37D4661113DF6B43FD77CE00B0E9C4AACB28292FB20DCB12FA461B1" + + "07E853C057867C5ADC6C8D21A812B05A20ADD09F6E6ABEFDC45DD1CF7C64D7AA" + + "0408CA24D1B7014F2C960E8ADD356FD13B75448287677B23F48F7B527380709D" + + "4ABB09A5EB3100068F55CC4A194166BE75F32C52F3031F69EECD36A5400C0769" + + "E5C5DFAB81F1480C916872169EC34B49646C9AAC76909EB8B49CFB9ADF07ACB7" + + "5B051AFF623955F1CB0D5E11154576497306D92CF1A19C02D0B10D219C956DBB" + + "47DA7F24C554D0AA6D71C5DB4E966606B863445F39DD955AA062DF78BCD0C509" + + "000BA379A4BA1FEAB5A9D3EB5FF40B3C85C9450B1E06F79A2670DE7EA799B741" + + "28B67A2B1062391F78B00958497948F8F1133096EEE10E761080CC55928D1F13" + + "AF835DC7098181CA2D27DEEC292C40CB969AF15BC8F82E31A224BB24F04BDDD1" + + "49C57688FC1867E6CA995A4D8B2D72FEA76ADB9E36775EC6994EC346150B26F7" + + "40491EA804C176D9C8852308AF4849A88F2D1C93E948C848D22B0122CFB5C7C7" + + "E848DE044480DCBB6E282285BD00CC8445E6992190B13764337CD226613F2CF5" + + "EB5750A7FBE079B68FD3950E8D3CAC9E579BAC61AA7D52F9F4194C4DA59F07BE" + + "40EAB8F3104D0C70E92AA0273DD3C0CE1901BC9780B5762C833974D193539627" + + "61AD01E3BF23C6C7941372CD042BB05A897E18519C497236DF21ADBFD5507414" + + "E50725AAE16A5078464719FA61C426BA4DF9B42EC2D84824F2505E5745446BF4" + + "CDD8444FEC1E505665C46339054D8CFD6A54CA9C1275C96BBFAF456BEB77491F" + + "71D2D002B2F7805D44DFDAE37C0C4FAD680A7B0DB89AD006208FE01284050AE3" + + "3A21CF566FD2627B1A86A1C2402658083B08998D37234B00CAD3C1F91A54CDA8" + + "57A777BCE878E9902297E4A8128AA2D7D58AD5F491717F9B3C10775F55783641" + + "D052BBF2B69B15D5CB78488731C091E5B7D3EF768D8CA1F2089F30ACBE014566" + + "F566A69CDC09268F2D25B9E9E60FF08742EDE0E85735FB4D4FAD8464B163542F" + + "CE3BBEA4F6DC2869F48B8212013226BDC8B520F74349E85244C7DE0D84F9C4AC" + + "DF8B7C5929267A2CF2AAB77FA7C46BC6A983FC70991002EDCBCDC647ECF289E1" + + "BA930216325D5919290260BA192E8F3E1EF136D4BA18DABF7F2A6F87701EEF98" + + "B66CEF645CA90BF8B75AEC3125302306092A864886F70D010915311604143809" + + "23C6F251CF50C47C7670DEE626FD1708A70E30423031300D0609608648016503" + + "04020105000420AD0EB570ACFB8357A8E99B17672353CFBA69C76FFE5B6BC113" + + "05577F12AE24040408D04E60444B79672302030927C1"; + + internal const string Pkcs12OpenSslOneCertDefaultEmptyPassword = + "308209CF0201033082098506092A864886F70D010701A0820976048209723082" + + "096E308203E206092A864886F70D010706A08203D3308203CF020100308203C8" + + "06092A864886F70D010701305706092A864886F70D01050D304A302906092A86" + + "4886F70D01050C301C04088FC6C10979E6D39802020800300C06082A864886F7" + + "0D02090500301D060960864801650304012A04109EF63F4518B8635FE54FA2D5" + + "2EC0C19880820360B9DEB42B1F8B8F4E58C9CB35F871A99821775275D604A14B" + + "498689CCFA1D8855C1BCB7C07528145C3D77903BCC27E9133041782018D6C1DE" + + "F094328772836DB17E5271F0A0B7D8A9BAAFA1086E95483DA5CE8519B4B911ED" + + "88FF0FC47AEB5924180D8B35083C5B3B44D2C8B7DBB2ECF5FAC710862B090D5F" + + "801932A0E56286DF0CAA10D7CB8243B88D7C2F619D06B233DF6D16060D392F28" + + "2C564ED685ED8227619694ED34050B76C8E28ED38B69C0AF9672060545C81B99" + + "EB6463BA8A786422322180C31D64FCEA249DB78C51CA5B84DBD8522A8AF531EC" + + "930A0A03BFA5CC7F84EE9F98819784D8E22237D524369F02D620B5AAD9C336C4" + + "737285305DC53A8C383453E0D278450CAE3DB2807DE4B0D5C6BAE4BE40370ACC" + + "5CB8D03644E553B0E98FDAAAAC00FDFDD102CF8ED916E22E686F30B575660B4B" + + "3C5BE7A1D3CC1D5217A8614F3BC80727671B13E5776988F7784A7E886C23C733" + + "A0C6A633D7FE8D7EC9ED9B2706B40373940BA8F9BD1BB7F8CD700384D06EC809" + + "21EE29DC45CD7D6EBFA1BBDECFAAA26AFDACB9E8C86450EF404BD3B60716E2E5" + + "1E943E1E1E595113C0EE3687493F252110ADCD4A44562BB3E2A6C682500C6591" + + "F72542BF6953BDB94CA977925B636DCEA6A6BA634CE8E4A44387CD20566DD120" + + "E3096E99ABF83D88D12F6CC4117E422460414DD0F89982A080FBCA7669568865" + + "0E9A07087EAC27753AA5E0AB126093CC9391B7510541820C6DBFF07B790F6DD9" + + "699530BCF5286C9537A9024C0778BBB854EA5A9034B293A78F4FBD2F3C572538" + + "2C703E8CCDFC7C54CB28005E4C511F8C8EEE84E65415CD46680547A7B7BB72BE" + + "CE5432EB1C6EFEF308092C35667BEB7509594F75A6D06D35C5C12FBF1C331E59" + + "6A5BC1E4DA753E319254068B7EC7824BD8389E5379773D14BF664D1A75991CD3" + + "E4AD815CC9A131FA66765530E55362983D4AC316D055BE68E8052101EB36980F" + + "2E72F5A3442BC1302F1E9A721C7A8D7B56A6DB36477712FAB04F1C17F073F8B5" + + "279B441E35BBC7986E67C1D9C8AB6DB30AC045ADDEBACC29BE1AB6FC57EA41C0" + + "5F7CC21BD1AACC1D7B9F2B5155893CC11D512A6DFA5FCE72BEA259D381B57019" + + "6ABE1C186B1B445B1B0B03DA596C3A5AC0252D026CB3F5DE42C06E81AA7A7029" + + "F249EFDA7581862AA29FE1F4E8ECD9F1BFB673119ADB0D369A28A2E3962BC265" + + "3BB1453BBDDE09CF3082058406092A864886F70D010701A08205750482057130" + + "82056D30820569060B2A864886F70D010C0A0102A08205313082052D30570609" + + "2A864886F70D01050D304A302906092A864886F70D01050C301C0408CB7AC3CE" + + "BA6EA01002020800300C06082A864886F70D02090500301D0609608648016503" + + "04012A04100E253ECAD79E0856D73A2CE9A3D48101048204D0D617F9EFF71270" + + "B09B3287BD6014E3DE6C8AD23BA19156ADE125B0324CA30B758DB8EEA9689A25" + + "1586E6E50A0C3A5DD975A2BAA6B571FF1C9C78E361F0ADBF4E9B4F7BB57B2728" + + "621E3B113C5ED339ABB89AD31F803AE2C976C1F0B96ADD7D2FD54E27C490D3AE" + + "220202531960B57B029379188C3613D6B1AD6F03526E1BB23AEC273C8F6E017C" + + "01358356EEB8D1273B5B114129DBAD60E367D70C92B65D38D0EB56130864F708" + + "3A43B7E3118362D21CD032D21CE94E6266809A69087313767E0D9BE736333AB2" + + "9D737E313302C6BEC5124023A22C395EF4A0AD165D344B329A09E5E4593F4848" + + "323FAE51B283EF0DBDFB951BDE62A0C7FC2E6419A412E86680F6414E154DA560" + + "2B4B46B836AABB3DEA03B1FB12110DCC6BA1C0FFE902CA892E4827955E1488B7" + + "AACA0FA0EBE8B8ADDF425CD9AA65B407503D0089D74B809310C737923386B86D" + + "DA357654C4A60285C31BF9C2BA22862D7774EE2FD8AA92008F678CBA8260F04A" + + "561081FA8818CC384307AD0AB4C3BFF86D1BEECC136D0595CC6E816B51C0888D" + + "EB4251FDFA5C02FC6D9EE0C60114406FB7391A149756497A2D88207075E2A528" + + "E021B68820F68F89F4F6A5709A18D440E09B5BF239D4ED36E8C3358DC7890033" + + "D9A0761A0A062734B709144A5B1CE9296480E66E0800B62FAA881F70AB89823C" + + "D513BAC42346758EB3EC982B7F8B4808DCCEB64CF854A18FB0E2D0D3B29FDF63" + + "B60C21A614621183F643BA56BBD0713AA5444EABD1415FF9CC2ACA80B70256CA" + + "CB059949760257128AFCAD51E8B9F574DCEA9BBA42344BACA4D96F7EFAA5AF64" + + "EF01119D34E971D4837C3633C202FA47892C59B37A88310F9CD2C523F0A4F952" + + "BF925A80F2DF0A813283739416DA1885EB3DE5AF04FE6C828C1AEEACBBDA7B82" + + "A00F3505A56C88FBA0537B1B4F7B7F54C1551A5F5279DEB9DFCA2C2EEEBF1D75" + + "F60DE8777703B7AB67411E5DD4478E7430E34CF1D0E0FBA7AFB124D40FA3E04E" + + "5D737D9C1CFF0F8B1CE7E2D4F99C340BB4360FCC285610A44247021BF1CD338A" + + "DBD4C9CFE0C1685AED1A4EE01CD34A9BD446F0E69F16EB395A6AF8E4710A13A2" + + "75D2B102AE38DC0204A6331155E70A0B73440759FCB89CC5E0A2012082696A16" + + "7B97FD90FFE53349D9883FACECC2B7237B28468C6637ABDC47EB595B82662703" + + "C9A8BB3AD8B7DEFFA323EBA092C8BEC5CCE3C5BDD10AABAA872A7620B4888351" + + "EDAC82D0E7DB5585C5B8119E300F8CF8B24C62EB397B9069038AFD69FBF1305D" + + "83FF499E203873F45559868DCFD813A5FB5BF4EC695A7463C6B0A2A8487B09FE" + + "B58BDC0BBBAA377909DC88F03FC3E058D80E22E54840E8803BCB78440C44E6E0" + + "1A17519F78C2C89D965C9B984C96FCFE5DB22ABE51241F88A15BF0DF20936072" + + "EBCDFA465182F41A0025E877A308045D09FF988F122AE2639EC14601ACA00E59" + + "81C3E1B6C8123B8EBB2CF9936D9CF3C4A0A8A694E26E9FF6EED0B0544BEA6F08" + + "EEF5FFA27DC0FA3D169F51C42DCBC65C3BA935F6EEF2D78DD352206C0F5E0F92" + + "AB8A4284D67088C0587443242035C23786BD0A3C48452ECB44F4E07422DDC849" + + "099587763991C299C5BFE8BD14D6904516B31254C1176F191962B81FB5BF16AF" + + "B0E25980A0D069D9FABB11A053FA5D8CC71F7F825A2C96A87D7A6F21FC6D8DA5" + + "059F848F6AB5B85A04D1257218EE480444148F4B0A1BEA8CB4622A96EB9B4EE2" + + "A76F14B1CE25EDCFA23125302306092A864886F70D01091531160414B524C1AA" + + "CC976B19833DCC9739FEE5B240AD3A0030413031300D06096086480165030402" + + "010500042029A4ACD27A78AA6BF3B9114E19D1315E76BD450EDFDFE88F4E5E98" + + "2DDBFC734B0408D154718FB757EF5102020800"; + + internal const string Pkcs12OpenSslOneCertDefaultNoMac = + "308209180201033082091106092A864886F70D010701A0820902048208FE3082" + + "08FA3082036E06092A864886F70D010701A082035F0482035B30820357308203" + + "53060B2A864886F70D010C0A0103A082031B30820317060A2A864886F70D0109" + + "1601A082030704820303308202FF308201E7A00302010202146543F3FA4FA3B8" + + "75A1BFDDB3CC23ECBFEA736A00300D06092A864886F70D01010B0500300F310D" + + "300B06035504030C0474657374301E170D3233303432303137323530385A170D" + + "3234303431393137323530385A300F310D300B06035504030C04746573743082" + + "0122300D06092A864886F70D01010105000382010F003082010A0282010100D6" + + "C77692CB15D98788AF8C00AA0C626AE45015C8300364C0303F09A1D48DFF5599" + + "A3B8DEC49365E28274E2E33288ECE042322CF8B2697E760D0FB4E8894C209859" + + "9D7BCB39DE74596638D11C87F8245EB245AA0FFDDABC45F804158776B6A1980F" + + "13F4C87F2BDFADEFDA91C3628544BF5F328E5F1215B5F277F6C7B89413720B22" + + "9FA9DFD132A7CC187F88154D6C091841461D2E7C35F75C1A40BB99EDC3C3873D" + + "51C2F68F804F58C0A4FCBA8001F6B92825581B4A9391C6A770614F6BD82B39AF" + + "13094EE7E49DCAB7FA2C751533B358C874148BAB88B915FC99BB8C8F907A4317" + + "3FA14F3B26EF4FE5B014D107DF73E5A2FC0E9ED651CB376A78CB1177E5D83B02" + + "03010001A3533051301D0603551D0E0416041479B60678BEFC1E3784E8A780B2" + + "30A7E826DFD627301F0603551D2304183016801479B60678BEFC1E3784E8A780" + + "B230A7E826DFD627300F0603551D130101FF040530030101FF300D06092A8648" + + "86F70D01010B050003820101000ED62D8DCEF486F04C6047AB0C2CB25FDF1923" + + "7E46D1AD9C16139B8C0A0236EDB46582AE45EDF2E242947A81AEE2AF4BA9AA9B" + + "3297FDD76B1C7F235288802DA590213B4A5E7986B828E072665D2855860B86F8" + + "F625F2BF6111938C54563DBE8AAD21DA2A883F901CC2D7CD08DB113F3468384C" + + "388A6B07E4C301839D4F0E8BD38920FEEA4DCAC3ED817BE1D0F3BBAC45E772C5" + + "41B0819DA4F0EBAFB952C082A57714758394C07416EAB0B53ACBEFD2F2E2138E" + + "B91CE02F4F8E008C976CDBED10340B79B9F9FF8CC94C65EAC274C4A08E1347B0" + + "21268E581CDF1730AE9DF3B959508262DED10B040A1D8346F0F544A2BBBA7454" + + "C2B2A7218B21B64D82B8C04A0F3125302306092A864886F70D01091531160414" + + "D222A8E9C8CF876416F9A2132202326C1AE63C203082058406092A864886F70D" + + "010701A0820575048205713082056D30820569060B2A864886F70D010C0A0102" + + "A08205313082052D305706092A864886F70D01050D304A302906092A864886F7" + + "0D01050C301C0408E0AF915D08BBD72002020800300C06082A864886F70D0209" + + "0500301D060960864801650304012A04100CA536131D2DDA95F84830C4E47E84" + + "4A048204D0075FAF61AAE642CAE276A7AED857DEB08094880EA949F763F54DA3" + + "B1C0CED0D383B3B305F5D4C033B33BCFA08385F58BE862048F739B59C30AB3C2" + + "1B8C877D2056D27CD1A015AB8EAF86725CB5F2892C667CC02DE0AB215D4859F4" + + "A4DFF4C6B8187B4DB5DD2BE8217482148D0135E1B6B7784E7C8515FF4155D662" + + "5E742D45D3DDDA357BB7FAA90601773C96468F2E023242CD6B087CD0C504C124" + + "8D747BF0465F33EA2904682678CFE57B4FC9DD8162230F7C6980B399D793B796" + + "08668B7FEF17430E128AADFAF37F7610924845327A631F51B4AFDBA3D08C2408" + + "8C6059FE0495003E210F53E616CAAD669954A7E517DFF203746DA1A6693BD23F" + + "3DFF096DF050DB68AF7E4213F2A40D03C274C3E1F224B66A3481001C445E99DF" + + "F5EAE97A9E7C34D035A89DDAAF982794E2BAB630EB61F96399B891F460463052" + + "CD6176E6561DDC60C9FE476D125758AD3EAF9747818A4F963181928E79FC667D" + + "396EFFD95CFF25DEAC00E0B1A4092E0F0AF9132116A78C75B3306469F64B536B" + + "FD6130B756899A7FBC79EB11BB0F124A8BF08AD818923ED9D1F93A79C1C1DEC6" + + "58B8859794A3C02F9299901F4303CFFBECD354BB77FB5BF63146B8F85C4C0F81" + + "85A7A6C8A28C51C33340DBB2204AFC70D4D79AD2C35514E4BEB413D519A12288" + + "29E7195A730A1A65FF9585E32F91F232DA23BDEB2DFDBEA5377AB9E053198899" + + "B140F816979D53F738601782C7CC24E881CF337F5CF50C24EBE2ADAD74FCD523" + + "2E620B8F144252BEE0B0FCC08AB239526B1DBE7F6C3D1FC8184F60B8B30C64F9" + + "B42F5B674C475A4D088C81C8D9102118273C6DB632CF7E127E037D6B317DE6FA" + + "C7B2752F1173851E3C099F40F207B0EF57BF80C73C224B70D0D975C15A8A2193" + + "2E34EF1113C48EB8258968B37D2358216E6302192C6FB6A68B325D7B731CDABC" + + "4D1FE7A4EA25AF60F5B224FB8BC0A3DB8ABED63FC1B91FB43AA4ACCDB32B46F8" + + "1441CBE62B1C38A4FC1E76E2419579890A10906044E18CC1D06A1866EAE98B78" + + "2BC5503BE5E24638C79FD804809F69D8019B77F498A36CEAF1582DAE245CE949" + + "BE493751FDD232A02AEF72DAF9B527AA29BF8C0B0384DB29BECE1A1E3B81E681" + + "00C047A22E73ADD5ED5B19BD922279BF8E0D4834B69408B5A9844B8421D6420B" + + "3BA243BEFBC2AFA74DA94D34B58BD827D59025438EF4E982E0BFA133F5EDB181" + + "FB5E3723CAF8BF0AFDDF20DF75A433850DFBBDAAB3FA7B61962A66A0AEEC1476" + + "B12A016CCC2B12C16AA8547D46B33F3B6008A65C165125BAD61345D9777E40DF" + + "232190FB47934E3B935B963DDE4717F4F4D1E932D1D7020226C0A2472327E16A" + + "F8E16DCEF37C52E58A65FA44842E5A323DD768322DD0F22BA1CDF9E54A3C3ABB" + + "7010A9E4C3D856719CD025C1EC7AE2DBCB8DE8ED68AC542797978C47310BB3B4" + + "D34A4244B3D0D01338A2EF8A43DF1180C01BA03AB9A382C888912BBBE541F8A8" + + "7C0CDE2EC2405F67AC22049410E2AFD9A8E4B8A836055C399A5422DB375A7520" + + "99A947C933DEFFC26532F399D08978443C6D040FD29C5842B6E0A8235D44012C" + + "6783AA66ACA31FCCA155AD6429BEDCABA71398B287AFFCE96AC8ECC36CD222C6" + + "7140E144656A0D8FCBDDBF5E96390DBB7C7C093EEBD8DFF0BDB68568BFE77D7A" + + "A7A3B6C94CD9737B8FF3C4F9684062E175AE9EB8DAB5B8956EAFB3A5EC84C9C7" + + "376F5F4B588E60875F3654A15899FD3734455366083125302306092A864886F7" + + "0D01091531160414D222A8E9C8CF876416F9A2132202326C1AE63C20"; + + internal const string Pkcs12WindowsDotnetExportEmptyPassword = + "30820A06020103308209C206092A864886F70D010701A08209B3048209AF3082" + + "09AB3082060C06092A864886F70D010701A08205FD048205F9308205F5308205" + + "F1060B2A864886F70D010C0A0102A08204FE308204FA301C060A2A864886F70D" + + "010C0103300E0408865AFCE404C9F4C7020207D0048204D89F814ACB055451B7" + + "7FF858162304D57C3B3393283C3DE8F81B4A2264501B47665EDF7A830B064DA5" + + "DBCBB95A1DE88E07E50681AA732A800FC006617317B0D461450EB0A8CAF73F7A" + + "26B96510A47BE05034301B33954B6DC2E581D00369DACC98C189FE2ABCDEF057" + + "3E5A04D0199EC35F0D401CF314F714D6720220315E13ACE3B982258A94642407" + + "88BF9899E4B631B577293E8C8BA288D459DD6B158AB1C8C585D8ECAD23E3F49A" + + "99EE4B64027DB0A5E5241EC4F2B7D614A2F213F50CB97BCC8C64E1194CE6103E" + + "E21CEB1F83C8A8C4D3CB4F0E76CC8482F34AB8F3D42386E061C72C4A9D040076" + + "09C86331483F0E19A3C94BD2848E708C4B6D07DFF70F839BD7D39A269B4985C2" + + "025FC6230D08999B5121C71FD9E11E5CDB694C6C5C1EEC5D92E9296A8BA59902" + + "82666A494BDFA916EE9FDA34EA64A0877868DDB61A5F63E3EFC54DE52629A2E3" + + "FEB9D302331C4693711AA3B3C8DBEC5E44F4EF28E40C6B2C6F3C6861F270C87A" + + "210F5BAD2C05E43D2D93D5D349D7A60A5002E11F78E402294E77C946DA9F8F59" + + "F51E6BFFD1E322D95E3E49CEC25FE338F579B910B70268EAE76763A368125663" + + "E0B14F84C502A70EDF05D9C4A2257742E2F52C80E01A6A9FFC21E2E231DD94A0" + + "93D2819AF8261C7A2DB6659CC3FB237B8992FDA7242836A9F549555FDF55208D" + + "1E5E2B13B18D776A606941C9DE54B560101289141BD864160EB2C382DEC0AF28" + + "B9037FF80ECBD0189F1A2D22CC395637AF046D62E90220EE6630957422EFAD6F" + + "2F6FDF425B8B9F713368CCA5D3CE9C12DD6EF61B12074FAFAF87F3E59A42D8FF" + + "41BC8CAF09B5E79E3AFAD9832DED992F7A8441307379DA4225EBA0ED9E357664" + + "615FB53B349EB5AB1C2EF450B6338442D938A0D9C52CE38862015F11F1F805C5" + + "426E4AA33E6FF964A4E7F39F8088DB8A98821E737D1D974A70E3CEEC960B733F" + + "68A8C1A243F438DD6D4DD25924251242711343E6767359AF38655455D3058110" + + "73CC04DC656DFDDF7C3E30614D994C315E2CFAF63307C0327753817BDAA08C92" + + "5307B136DAC0BB5FA128AC7879501D00269E7C7B779DD5624F81C28040A2FE42" + + "0FED94C6086AB945D4A81F6F9547B73BF03A0F6E8E36FA629B7730A42D574EA1" + + "D6DD37AD7624AED6A5667500A3CC2CA45333A8E2872B390950EEBAFA7D98C3DC" + + "D16CD6F932C21D3C302DE8B161B85AC67A524855664A3473A541EAA9336E2FF6" + + "B4978BCCBE0C4D7D874EC424AA450B5C2802BD1DA7FF07493F947D2F0E202D3D" + + "6D43F57DA836EAED898B280BB374A23AD10E0F4399F549A76B166F80D0CF4ACA" + + "AEA53B7A7A13E85162FB48F54A7930D564E99F6345B030106D625FF92EC96E89" + + "921442A0F248C1681757D1C8638EEA75A1A5A2CA74F4DD8EE1EF114A56E040FD" + + "6DB11B4C6B542D8294C08B0C65B02DB59D883F52B3A5F0165E37EEA7999BBEF3" + + "669510A206A533F5A82DC52D4F6B54977D5F8AE493AE49BA10663862CF1B8675" + + "D42F8DC6BA3D748CFAF4DD75C870D782CC00F4D463EAF06E2BAFED47748225F5" + + "1756D089EDD71C090CD87225EE9D501848E4682460A23ABE5A4D0589ADA5105B" + + "14439ECAA937517FCDB35CA6BCEBD1190E71A793979F070B37A9AB2D003A00CD" + + "38D8EF194207FE53FD95D7C43F7C58718F0CE80588DB13B6828A1984D9DEBF0C" + + "1072FD2171AF46156A1685CD841830212B7C78CC1A40C9F92DB0017DCE853E1A" + + "83A9FDF792AD2935750D74298EC8051C3181DF301306092A864886F70D010915" + + "3106040401000000305B06092A864886F70D010914314E1E4C007B0037003000" + + "4200410033004500340036002D0033004200410036002D003400360033003000" + + "2D0039004200380043002D003200410039004200380034003300390041004200" + + "320032007D306B06092B0601040182371101315E1E5C004D006900630072006F" + + "0073006F0066007400200045006E00680061006E006300650064002000430072" + + "007900700074006F0067007200610070006800690063002000500072006F0076" + + "0069006400650072002000760031002E00303082039706092A864886F70D0107" + + "06A0820388308203840201003082037D06092A864886F70D010701301C060A2A" + + "864886F70D010C0103300E0408196DD4C6F976C7AE020207D08082035049FA3E" + + "9C159024F1821379145C29EFEE5AFEADC5F364CD86547A125BF22CDD99010BD6" + + "FD3A5CF0F028DC3E37E1DD509F83F2C13F59AFE2D3908B33EDC93488DBC0D091" + + "6A209039CC4A9B8E37F614FA6E877969796EE55B58699A65A98449F8F0ABA078" + + "50497075821CEA2BAE375092254407B1CAB99E8AC3AB1F582D13217E651E328A" + + "DBE6054A3FA4E0A6911B57A5F2651FC772D5A180FDA6846C089C6F0CFF7D3EFD" + + "22D04551B59F58BB605D9F6B99EF7F027082E200052A19AB9606DCD522386A98" + + "BF17FB599252052A69440DAC7D57187000D58E8902911A51422DE3BE79001A42" + + "0EBEE4D263A265D49D41432D6040D4D28734DD38288DD84ED32EBE281C361400" + + "7DA2D4751F423538EF6608F017C3E2B0A0E143ED066AA65A933D62F5872EC26B" + + "1C5CF29E264146DD6EC4A2A90DA88FCCC9E0E20F27373CAF09E9CBFB0D057094" + + "A9FB914BC194941A873D03139FFCA79405300FB46CBEA0070115271268C2196F" + + "C39DE444E483D6E36A973DC95775AAB3C81F766065A76EDDEA274C38F103B218" + + "5B57FBBB82F1316A6C023A51BF873DFE71E62259AA2FB6A5C4E4152D45D70284" + + "E08927B559F1706505277EC088BF91D3ACCC4E541AF1B7701DE69483B1CB64F5" + + "DFDCF259761E080D5C58ACD1BA8E3E13C52E4346D4743F4D7C5FC9FD1BD64D52" + + "0539B7E627A33ED2F5840A9D878AF88B32C5D5B8A8279662895A6DD129E8E511" + + "C5123885514D3E3FFC61C000DABC1648BC816746B3FCD00F967BF8F12B1FB18A" + + "E87A9972DD2B9D83A69E06FCACC37EF3CB6CEFE37D6EC68C40ABCDCFF9A91716" + + "6BFFFA54A54016089E4C008B0FCB9EDDBF2F426E6232D04FBA7C41F0BD044D52" + + "70B4B82D865D75BF8475970459E1BC28E9207189586944D84D1CDBB74EF25773" + + "9A2F070A9871B1072822A6614732A9D90B36E6B1F8B9DB190E0B65059601AFF2" + + "D19BF35C1C900E6D575DDBC1DA505FFBC19CE98E90741A898A207D254E236A89" + + "1826B66AB6E1D26AFAE6F59A70477F17D490DD1CD5673FEB65BB4C52CAAB02BC" + + "ADFDE6E483DB58C24BC3E596E451BB70FB425CD2010861D60CE726F9067659CA" + + "907134542C069E52AD359E2C300FE19AB08E343614AEBE1B5584D258F1713927" + + "4FB671EBCBA8B11CD4E35564B518A840D0DE69B54E39F762F3821E5C6EF5C2FE" + + "9CD9D62EB1031AD5D191B95F2B303B301F300706052B0E03021A04144BB56BD6" + + "06B405745EC53A2F4AE4598F557ABFF60414C984B699CDE84E8ADC55A7291E5D" + + "FF09EAAD2394020207D0"; + + internal const string Pkcs12WindowsWithCertPrivacyPasswordIsOne = + "30820A06020103308209C206092A864886F70D010701A08209B3048209AF3082" + + "09AB3082060C06092A864886F70D010701A08205FD048205F9308205F5308205" + + "F1060B2A864886F70D010C0A0102A08204FE308204FA301C060A2A864886F70D" + + "010C0103300E0408D10B4BC509135A33020207D0048204D8BC69D1EFA1BFF345" + + "14685D3FD6F4407BA4106DDBAD150E899E2C6BAE0B291797542F07376E797891" + + "16D8124259D24C3E753781187F3CF49FCF1994554A28E12A2AA76046692D3673" + + "00A6FA70D09BD1A0299FF481A2060879A4B34FD35ABA4C1EE87AADD95A42CA75" + + "50433F2BCF46548580AE0FBF839AC5C6BA984C9ED00EE8C164F701985B116C3D" + + "4771CFBC95B41CE2C61EA951A0B2B8297ED1A10E94F80640E3BC49AB004DD110" + + "7DB967921976B49AE1DC70AC7F3F1D85A4AD84D911E63BAC9DA9A620EE4CD74C" + + "512D240DD4937AD6718432C1CC39B00354945F80BC59B3A9C3A2CE80D17E4388" + + "88BD9A0C6665E1C4D31C676DB4135386704366E1650E457803E784C37658BEBD" + + "64C23338E6D5416587FD8460E2B04B2F9C884845481B93B6E3A829DA9C364ED8" + + "FCFE8DDF2053B8F8A6A3978B6F1760758C0124C87F04BF9D411DC3478E0A45CF" + + "A0BF342255F798D34C059B401B29962DCA862577C43D7BDD41A69BA220FD58E9" + + "5CD79B0F6FC43730E59E7C8709732B88C68F5BCD7156A75359D7AE38A71AC69A" + + "605BEC35038DEB4167EB989FA4D1B4ECBD25981C0C4D5D3109CF8C12863DF59E" + + "904DA26B0B03AF0CCB1D83F07A02338F413B6177DFAFBB4ABEC97FCF7804655C" + + "0697FAD4182358064A55AAC998B035D559C4496575676413152A38F079568272" + + "2E80AA090D9D974F8CCB59159F184B448ADCC3FE9E3032D64DFEC9405ED27030" + + "09A5BA3AA1A6A9D190DE7D068BBBE5F5A9220788B8052A81C1AE4343E1E17FE0" + + "0B8EB2D4537A97A9726E901FCC8F5B660AE84FF7EF1D2633FCE243DE56053C64" + + "52B1B0C8E73112B34C4DEDF9ADE21BFF9217B341017945D73B6B2670926AA4C0" + + "FF1EEE23EE56C8650CF0861A338F645B4859DB37281B4D655BE084D5FEAD1B8D" + + "15C77FF3EA96CBBD098C4E05F718FA81BBD8D423D491DA5A42C7919D14BC0C66" + + "D7F2FFF8102F2207D7866B3952A15B3EF96E59B8B0AFE59668AE4BBF8A75C0F4" + + "39F3096C3B9B172074C37CE8C0335BA90CED4C78A35EAE6BEC26FCEC69AA6470" + + "518A9131E0BDCE14604CF7C1DFB7C6CBC90C0147EC64417418F877045F0C947E" + + "16168035DC404E2EBD1C6B9BA0347F011AFAF908FF0A1D8FEB85DE87BA2F8CC5" + + "BBE29F4AD3FA4F2F16BB282DC801B817DBA5D00A71A83ADCD228DC03DDC477C1" + + "1693D7C9F179D1ACB1C13F6CFFBFBF7504A31BDF719B35E7A25B116EFAE68F96" + + "6AF7A9B545DCD3C9FE9FDA171E28E46A5FA749F81FD8D87FD52D4795F4E28554" + + "3B3C2289264EA9F5B1DBF0797F7795638E2BEA075F3AAF04C119329F43D9788A" + + "98E22784CE45D3F0659CFF73C55379156A56F75D3CE6BBA7F11F949CD61F9ED6" + + "9D84ADC7A41D67E64C2FCF532CFE4BA2D31400A8DBE70C4344790FFB9F353245" + + "8967D45FE4C6BAA588534AB8A43BB1417DE16D7413DB778698BDB75906BA8E22" + + "7C9221B2B44D358908BBE0C0F2F004BBCA5EA8986169C1EB59B6C8C9C254037F" + + "D44375DF38AE1AF5BC23485CB6FDCEC1C0CF0B8692B4E0A00EA549D4E4697924" + + "0CF5A90137D4E12ECC7F1966E6817CB1F06673EA7D51F462289E08B080257281" + + "30D738CAABFDA23821DCD9CF25452857E3EF237B661338E44A0C8C474944F265" + + "0FE693A3B677EC99A647CAD574E85605800B1BF305B779DF5ACFE21329E1B4D8" + + "09B9CC96363574E387403DE8B57A636D731108EF9501075547E412D22475C053" + + "AC21B74B24ED7AE7C23E1235E93F58D73181DF301306092A864886F70D010915" + + "3106040401000000305B06092A864886F70D010914314E1E4C007B0037003900" + + "4100300039004200300036002D0044003100440030002D003400430046003600" + + "2D0041003800460044002D003800420046003100360043004400320039003700" + + "340032007D306B06092B0601040182371101315E1E5C004D006900630072006F" + + "0073006F0066007400200045006E00680061006E006300650064002000430072" + + "007900700074006F0067007200610070006800690063002000500072006F0076" + + "0069006400650072002000760031002E00303082039706092A864886F70D0107" + + "06A0820388308203840201003082037D06092A864886F70D010701301C060A2A" + + "864886F70D010C0103300E0408CC0493121813F19A020207D08082035041716C" + + "8BF56E445181DCC9560D5AE27F850E9F87928D642B9C3264C2991F3BC05818FF" + + "30EF2D88C20F7E8F3453BF925BBCBBDE8273F5EDAA719D979B468DB9A02B38FA" + + "FB3A852F1CB828B69AD64B92DB29B0275255E0E9E2A1D82208B9388ED4075E7F" + + "18EFB6FEE20A3F1A440245BBC01C71DEA4AEC041C6BC2B7B108E85C1636F8C98" + + "2D2F860EF6B87C8C2705C14F4EBD351A36112BB26EF542EB4CD89DAEA112817D" + + "667B44AC99FBCEFC2164AC9D15A5CE589A61E0AD01F5C4467BD0835E23B41D48" + + "8122061A2E547CFCF38ACBEAEC0DA94290BB0CD52EFE15F5E0AAA89000E04437" + + "2B63787DC5C88392258C58C12BA1E63EB6A8D69ACF662BABF63714D99410C419" + + "D167820182988F5EE810A4C3F76D95057F0772F80E4E6B5F69CC58226DAC747A" + + "34311F509FC06F8055A83895E08520A88F74AC118C8F5FFA94DD6DDA74FAF779" + + "2B2A9B105079654A209D981E4C9954B3EC64E45681629DFC08E03B3D5FDF9461" + + "2A82365F2B959FADC808244ECC80A31C931E0E74DB4AF6864BD7AA90C33EE7E3" + + "432C41C756479927E1D80E241C59CF7BD5F1C2C3ED3376B2C1595C8C28A30937" + + "4E092FC99863A02D3C88E55AE43C3DDF83D8729D5CCAD761AF84C16E44F575AA" + + "67AE08CE9F8BC09C0A67C4C53B964A747C2505BDCF20690D8094F5AD58667CE4" + + "23BEE3383D9FCCC522F17304EF55B27B2DFF3CC4347537B7FCA30ADC16274EF2" + + "2DB9BFDECD5F44D55F8246D21EB64BBCA141BC5A8B62F999CBF06553490B6265" + + "68C3F61B060B0A04AA7A758D5C33155AA453564BA9CABE511C6D4C351A49F914" + + "3B80877542D9E65DEE2DE4AC2BC7A4997EE657FA4B885E3606D1F84D6977E758" + + "EFA84F7097A18330A3A222E7EAE434AD8D472127C7457CEC10602C4E0A4F0B72" + + "1968D8E0019EB5D77EF5B1EFF02D4A6CEE9BB28EDDD72D623FE9295126082631" + + "BE3A95DB414758B414448CB401EF0763BCCE74C83D93D45C2512977C35DEE3E9" + + "8A9D7AB96CAA0EFE7DDB8BB7AA77427151B88087FC97579A39D8A2AEF93741A6" + + "2C02E951ED1C3A172FC366253000AD457CE3194DCAC4DE13297D138A2EB007D3" + + "667F72FD0CE169799D85B85E474D06A28EBFB4C166911EAD43A70DB60A7FEC30" + + "4A6931591F13F3D029409548002D873551ABB2873BA3E16411E7E55CB693088C" + + "2B5DBB5F6861679BD1C2817A73303B301F300706052B0E03021A04145FA3D2F2" + + "D00A66EA4DFB51D5DE4D316276BCCDC00414FDBF473E8C4EEE8CC4D8DF166E6F" + + "6409A8F0EEDE020207D0"; + + internal const string Pkcs12WindowsWithoutCertPrivacyPasswordIsOne = + "308209CD0201033082098906092A864886F70D010701A082097A048209763082" + + "09723082060C06092A864886F70D010701A08205FD048205F9308205F5308205" + + "F1060B2A864886F70D010C0A0102A08204FE308204FA301C060A2A864886F70D" + + "010C0103300E04083EE6D2E1BADA3F12020207D0048204D8B84EA7E2CF71A281" + + "7828C34AA3005FEE52146EA713B5C3AA7958278B35FDF64AE8B998E3D87EA25B" + + "54B5319CF4390C812F7EE71D10CD3C70851AD81C690DE0326D0FAD71FF3D5038" + + "223988DAE31EC0060B6C2C5C9C74B08BE8EE3B78FED2A04AF83D38AD11AE8DF7" + + "8F7E5E1E447CDDDD0D9DF2AB10C4B8A90AF6E1152B6A7BE2BEDFFB4BCD8FDF3B" + + "D100114E75760396304BBA8C2AA19C430C9913028B422D5A74AE1429940D9B55" + + "DB9225604C5C4FD9B162A921E62BBCBC268470B84BC3BBB383A2C9BE7E178C0B" + + "2593D617D1466B95E57E90E30ADB7E08F6B0753B8B9981C49537B9B80D98BEFF" + + "350017130F360095156BD5F2F8963572F1B78A9B08B67642BB09FAEE48877259" + + "3383A830F3EB080210F39F5C28EA7892B8E6D8D6831A1DB33EE2B7A5BE758C65" + + "8837A6D1CB4383B47FDE181BB1F043C403567EDB66EFD95F585BC8DB248CD0B1" + + "909763DC9E3F46203C6FC61004962FA6799248E5E7F5B7A131D720F24056BD42" + + "30D1F5E6827B3025A66DF97436A02D441678797BAEB5135931B02A182C045B16" + + "9E8F86CB5871FD3DFC3FB573392230B70414A18BC792AC988993AE9AA2DAC5DE" + + "E09C87F60AA13637EC006ACA2525078E353497E1B242A5FA4BE57C764B24C4B0" + + "F5956D6067CD150ACEC57D4CAE982E782449588D5184961952A2871EC6FBCEB7" + + "E38DAED63C897808D7C2D499428E1EE04BDA40A287552493954A45941E684028" + + "2C964AB94D5A81E833EF28B3B7DF3698CE84595415001DE52ED85A6DB49D4329" + + "562C73F2AD51118A9E409FF96677C117B0528E725F55433798DB598F2B5B558D" + + "77F7703D1BFE6C24CBBD1CDC5961FFC45C139FE9855F93BA52A0183FF1C18742" + + "73CEBA04CDFD3270ADF3E20590E65E019DD6DE4FBD7C62DCEFDEC21103DC1C65" + + "078B76E9CC1DE6D33C4C6688A14CE938ACFEB25C8CD134C1BE439BFFCF8B9399" + + "8E8DBD7CFBD86D6CED0E1D1D8712913EABB7DD493209C61C39B757B329130562" + + "0E38EFC575C2FFC43A86300D5665C0B56DEE483762A623DFDEFF4627BCBD00CD" + + "3DC181AB22CBD3D602DFD379A223F6AC2134E47507501EEEAF33B06001C45B67" + + "C6DE14026B88CA0BBD44F941729FD3B9A078D801B98AAEC83A2431C1A7A1EB7B" + + "99051B4447256B2EC42A4E2917D6E7BE65FAB7866EB797F6ED4A988C57D4DCB9" + + "8C9236348A45BA717796E7715E734E2B585176100C5FFF37778EF76EE952CCE1" + + "5540E9DEC3E84E740694BCBE6E4108414319DC8E760852313C86B4EE03B8DF16" + + "8D00615FE20442C4687400E2436135C938E9167027799ED8890CC08788BD2A28" + + "41F0F2C1CF8CC2CB2950D3B2C93394017300C714BA941D356F8FA95FB5F82262" + + "B703F77A48E6EBE95DB2E7325F9248758578735EEE3BC0CC169FDA777A9FB591" + + "9A0007E0C191668F65714C359A872C14527B1A455305CE275135C7EB9F2E6AFA" + + "5F7FBB4994D0C2E8BF42EA9BC3581A7D70D3829B7D8204F2BC5AD9D24D7F3A09" + + "E0A0933D6532ADF03C500E11865C3138834AC110C513239E83606921929853F8" + + "D87FD51EEF9288178891AA5BC8A496E9BE44D4BFB83A3D435625DF3FF752E7FE" + + "FB8509D28E3A5E8BD5115FF0BBC2AB54DFB9DC8250478CC7E7A0624060B446A6" + + "4777501DBE0FF81EAAAC1F108BDD7E122FAE1CE7F326EBC697A016CDD1E364AC" + + "39FE901DF5D9E7A49225017DEA5374091232A47BE1147753CD60199268C70CA5" + + "ACFF5023B35FE76C92738BEBB1533FCB3181DF301306092A864886F70D010915" + + "3106040401000000305B06092A864886F70D010914314E1E4C007B0037003900" + + "4100300039004200300036002D0044003100440030002D003400430046003600" + + "2D0041003800460044002D003800420046003100360043004400320039003700" + + "340032007D306B06092B0601040182371101315E1E5C004D006900630072006F" + + "0073006F0066007400200045006E00680061006E006300650064002000430072" + + "007900700074006F0067007200610070006800690063002000500072006F0076" + + "0069006400650072002000760031002E00303082035E06092A864886F70D0107" + + "01A082034F0482034B3082034730820343060B2A864886F70D010C0A0103A082" + + "031B30820317060A2A864886F70D01091601A082030704820303308202FF3082" + + "01E7A00302010202140A49BFCB1DA91FFFDDECE6FBEA3EE7098A4FE4B6300D06" + + "092A864886F70D01010B0500300F310D300B06035504030C0474657374301E17" + + "0D3233303432303137323434315A170D3234303431393137323434315A300F31" + + "0D300B06035504030C047465737430820122300D06092A864886F70D01010105" + + "000382010F003082010A0282010100C53F2D0A6732510BD381F04F9EBFA1914E" + + "197754762CB256EB13B690D5F9A89E27D32FB92F706CB2615285BAECE16C93E1" + + "B6E2E205818A69EE99C2FF456F6EF117F1B414E43F71C0E78BEA69565683C9B6" + + "1CBB1247055FB88C758288CD70B22A1FC72E0B0EDE8A8A7B7AD50271B915DB06" + + "F2F7F6AC149439FA12049CFED26C916A80FA53E8DFCFFD7F2FD4FBF8A70B2BEC" + + "11342C977636C40EEB88F56B07337B2174EF51AD505B4283B876E98B93E8DEAF" + + "5CF4415BC828CDF39C34340921E16437BC7E19EEA44B73B26B594CBDA5729601" + + "C758F3476A221AE043E74975BD90D154643E319F9C253DCA9263A1C2526F7096" + + "A75C524A24B02F6DB13ECA5C43F9370203010001A3533051301D0603551D0E04" + + "1604143939D5CBE561A3E16AF98C385C4DE21C7745A7DB301F0603551D230418" + + "301680143939D5CBE561A3E16AF98C385C4DE21C7745A7DB300F0603551D1301" + + "01FF040530030101FF300D06092A864886F70D01010B05000382010100B4CA91" + + "1663AA6EB8B55B8BDEDDD4A07B1B0D0C79A819035BCAC086A01C5DFC64D2749C" + + "49FD67B20095288E1C54BC3A74FB7384DA4EF82CF5E66114373093DF1729DFF5" + + "95520975BE15C319B747F2209623245113C39B4A61909A6962A4CDDE832F6EE7" + + "DE15308DACAC4A6CFB1C0B0DA61AA9FCEE70441DC554F14A170BEFAD2BFDE032" + + "99C781BC115305E56E0BFF667B518DB0F16FCFA0B730B61EE01CF65EFE499C6A" + + "F5A67F9E20F7DFCD96A4B86ECA84F3E60AE94931B7A06C238BDE733BFAF131A0" + + "BD7D69D92AC75A4FA2EE300C1119DD05BF44BA05BDF1923DCAC9E372E5F2C155" + + "9EADDD2DB07B9BE2A984D2463E12262F058170C60BFC2646713C347D04311530" + + "1306092A864886F70D0109153106040401000000303B301F300706052B0E0302" + + "1A0414B7DC97F46A80902C720E8D237F10ED6FCC44ADB90414695EB196470870" + + "037CD616FBE42CC7469BA795DC020207D0"; + + internal const string Pkcs12MacosKeychainCreated = + "308209B60201033082097D06092A864886F70D010701A082096E0482096A3082" + + "0966308203BF06092A864886F70D010706A08203B0308203AC020100308203A5" + + "06092A864886F70D010701301C060A2A864886F70D010C0106300E0408365868" + + "CD387F42DB0202080080820378CB4B33E06FC54306174EC0AEB21E7DAB66B368" + + "4BFD1E6A2A01F894F38EAE1899CA23205BCD50A9525B125AD532084E6BD4AB4A" + + "5F80AD6FAFADF47AEDB18C9533E527833B972D8F8719141F9982E47AF3E7560E" + + "C34A3F248393659197480475AFE35DC804DA34C14043C67E0EB969FCEE09A933" + + "AC1DC8407F667744C395AB4FFCAFBE4E5553204228B32340692C68BEB99C4519" + + "DDF88D30E8CEF133AAFA77BE355A333C1BC395DFA9581B7F78A59B2089289CF1" + + "207266F8B237141013CA65EEF7DB2681ADC4FA7E36ABFAB2D424AAF83FED6039" + + "FB74BAA00D7D743E6DE29184656754EF99E927960717B414EA3390D62E3773E5" + + "BC82D8B0477ABB2338685951CB6471665E6EF8A7AF869F7A204DB5DAA1C34153" + + "EE9BEFADDE03082ECC0496EB245FE6DAD783F286AE114BAFC0DE20D435F1833C" + + "1FEE5021161D327127198D3BF568297C302DC2C37769DE8E7A499AE6CEF5186B" + + "168544996F5F4159676A2B9B887A335FDEDB14699C03629E204DF1FB5396B00B" + + "B40E20F8898BFCC46E400E32085C827346FC8E69F463938C9224E16EF2E892AD" + + "C37488389501A79A35EB573E915D62ADB2897543989D5105594A3CF3C38E0472" + + "FE8A66FB507498C09FE2BB191935C46A00C9DAAD4FC842DC3218182548D36B0E" + + "EA4114E5997F7FF6210352FE8FA2B0E5D0871DB8B65AF97F3748BD413FC55DD3" + + "B522BBA38113801D03577200126F18868314C11A0F2FB1BD5A4C60A7DAE49FBB" + + "B14A4B256B367289FAA891A1CABD58951531224B5BCDA6B61A17C7033BAB3D80" + + "E08CC0385C98E7B388E072060030B60796BF56A71B31163AB9827F3E3ED043F4" + + "F3DA619D8AB27E7887983152AF110EE552B5BC722FF0F021CEC1206A5C6D2B12" + + "3C5DF369DCC5A1C3C722B3A6767881F5142EE63D0A67866E8ED447884BD4A349" + + "A6DD2641AAE38624CE400E3D71A6420C0685F22422608FA143921EF661252626" + + "F54D743214531AD1F8D91B547E0EC24B9B01A97FD7FB2FF8DCBA530C221DE1F2" + + "0067196F2C1FAFF892E8E49803B33BAA291FC516E3FD5933E5DD0D2016F724EE" + + "E4E8644D7D93D80C9A6BDA84A10F79F50B52E6F76EA9274BCCE40D09A85F6072" + + "654645F4FA044719BEE24A04C2380A6596E17F1DF7213AD98019561E21DBC14A" + + "64D4AF49676113FBBAB9DF2C51E71048B505D1741B325B7AD2D202DC19D541B6" + + "DEDC7B57279C08EBFF5F588086295CE78840D8504D91577C35E9B49F164DAC31" + + "90704B2A7E3082059F06092A864886F70D010701A08205900482058C30820588" + + "30820584060B2A864886F70D010C0A0102A08204EE308204EA301C060A2A8648" + + "86F70D010C0103300E040814D5FF817FE6B0EE02020800048204C8E933D4E9FE" + + "25B62F989659649395ABCA2E20D6784D7F60A36074EFF5E6BB6C319D7E595E1A" + + "F676D24709D8C0A2DB9BB5AD2A0FC0342C77F098C2BA51CB4A1E1B3E26CBC64D" + + "6655704BAF173EA6C38740A9DEDCCF378D7C95588F3F767A9BFF8B0B6DFE668F" + + "1475A860F86E782469F21486C001BFF476319C6E5F9FEDFF8BCBFB4F7012A68D" + + "C85EE96590FC71DD8ABB0C967724564082533DADE23522D73D56707E22211A71" + + "EDD5F62041A79500840D808C61644B1746865D84A6021C20A0818DC173B16263" + + "01F462E54115E15726C1C897CEC39466117AE2AB5C15EAAD645F04E59E7F5E4D" + + "360AC5B4CE7F06C197C3FE699CDAF1B27A197897F97D0FD62D5F9F8FD3CD0D66" + + "13D01CD2DE930C147A7CFE4787763DC0BD864185F9DD9D50A231079B92ED32A4" + + "D290B85142FACCFBC2FE1A9823FDB1E4D5AAE57826F39DBEA82E2A8D7BC8D6CD" + + "B9FC1407BE84447ED48EB17FD3529091FB78398D56CB8C797CFB2574ECDD9732" + + "023315A77D3BCE8EA9DC29FA97F23A09BD5C546A524BDB3C7F4870AC7CACE935" + + "F13C1466ADEF7E66A405B28F4A59589149524A429E03854E62297CE26A4DB720" + + "9BFA48AB52F3646FB5421494C287C30EA2E2311EAF42C561CA144A5C7C592004" + + "88C8D85E9A89EB36C94CB18A2AC306ADC55197C21106137CBBA023DEB14561C8" + + "B6C2B789BB542816CE48F98CC68D65B1DFC406E2E99A80816D069EA1BF2117DB" + + "50D4ACA51B19AFF8669347DCAFB227D827137E633AD37727C352E1CFE184EC5F" + + "D567B865C63BDDC66D16BDAAB053EDD9210EE167F28D9E885262DD8B142A0143" + + "1356A942FE56D9B49E343F9459597C02E2EEEC4F59BBAA06BD9D6E9906ACC2AF" + + "85129F72F78FF97D2FCD0B6A6CC6DD6E2A5A92903B5A35C04DE62259A128CD8E" + + "A162057FE51667D2AA4D661AE36728A424D359409678956EFF604CB254E0A1C6" + + "822C1CC349AA77541D101FC5A0D487C33FBBC318E14FB1B13B74F6C41E9C53EA" + + "ABCFF7FBEF0D370E85A5918BC170AD62BFEFB8B46273901FB9615A808B912183" + + "25E79F666DCBF60B2FFEA25680E1AF19EDC0768AB6C1BAA67304F2FD25AED2B4" + + "BBFEB8BD4FABE09AC3B1298B4CAED0772C5B8EDE2063E0A65C424AE2BA344B56" + + "9E8DAA789B5799480E293EFBD625F8C3482F81C25ED9A44B41DE951D3B0565C7" + + "4889C29C101B9921952D2D7776212AF33C6F60C55A3BCA457C2045C6F4B0ADE9" + + "F4B63CE3148F16153C4425373A335EC789BF3EACAB052BA091A75ABDF4E01B7C" + + "F33805702A53A11E5FFD0752E2B6E14CE2840B94FFE53405EE0EE5C43C19D001" + + "7147891D4FC5DE5B949A8C602481D8C1F9F8B2CC3BF2271BB12B306452EC55BE" + + "EE81E13710746EEA3534F106F14DBE9FBD4E00C2FA2A331D2C8FC54607F6A772" + + "D8EE0B3E349448B7AB4E5CC783E72C3A3AC82AAD33F7CBB24403CE167A14798C" + + "E23284BC8A3F90BEBECDC4FB142037CBFD0BE595A6DCB2FEB4B80CDD4136374A" + + "6347898251859BEE1DBF18F3972493474E1DA9B60943D49978A8F4A73470BEB6" + + "E534D3E74726CD08BB6E9A04594FC8AD7F586F52AF8313D41D4DF45826A300CE" + + "2E6225CC0FD912F6D56A46A6BE4DB2CFCFB16CBDAEF928F6ABFCC212B12E3A51" + + "33864B1280EDA8E003F9FDB30A06058B35B31B133D67743C934C9CBF3CBDC06B" + + "959340EBACF1D7A781AC1318635697C2D27C00EDCF067A6CCBCADEEFD2CEF3C6" + + "B4E750318182305B06092A864886F70D010914314E1E4C007B00370039004100" + + "300039004200300036002D0044003100440030002D0034004300460036002D00" + + "41003800460044002D0038004200460031003600430044003200390037003400" + + "32007D302306092A864886F70D010915311604143939D5CBE561A3E16AF98C38" + + "5C4DE21C7745A7DB30303021300906052B0E03021A05000414AABF612B1D42C9" + + "7B2A777B2B544302FDEE1129EF0408B1FF31BA6E2D1A2D020101"; + + internal const string Pkcs12BuilderSaltWithMacNullPassword = + "308214060201033082136506092A864886F70D010701A0821356048213523082" + + "134E3082134A06092A864886F70D010706A082133B3082133702010030821330" + + "06092A864886F70D010701305F06092A864886F70D01050D3052303106092A86" + + "4886F70D01050C30240410978E6F227D033AAB5C51682EFFBA56570202271030" + + "0C06082A864886F70D020B0500301D060960864801650304012A0410905BE763" + + "FCE5DCA6ADF7F8E1261A5237808212C059073968AE0766D615903AA16B242ED1" + + "765D4776FCBCAD0EBB59DB954E9D0365C5183E758854B80D5CCBEFD131264AF3" + + "D864832A2C25B8B93DFEB8EF2D4CD204B2ADA80B2B41C4C58E5B48B55EC65DA0" + + "FB083D61288687A896374B6C851B6251C0E661751F7EDF47478B9041EC7F5B54" + + "DB9FB6FB8F4FA58CB9F8AF80D7E33B4D0F36880E2D348B5A84BBEBA738B3A10C" + + "7CF9026327A1D47E695515D2EF2B73ECB46B42DA27917607E3504D7DFA40A000" + + "CB265E4FD9C9DA026104220E3ED100EBCD434AAE29FF89A883B25111DAE8501F" + + "68AE219BA7725B7EA2600841F879E9D57664940D74C36FB25E29ED104DFDDF2A" + + "3F104B6A89A878A85C50133B68C22C00FD9791170287828EE50CDA25EC656C83" + + "7932D5904090337F092B24853D7F4E27108654C5764F04817D8205F661527326" + + "9E7DA0B4982108A91E5344B54A0FC07056326483B0D6D445601888D84B22C8CC" + + "589338DED377ECC841B08B02FA5ED7A1E8841B5BB2E0C5C3CB750EEB49D1BDFE" + + "D10516924049FDB0FDE9B20768ADF2DA0425AC8B4DE6EF89CD6AE5270513D7D6" + + "B78B97FBFFDFC2CAEFC428DEDAB3D44C9917AE8F688F7E3EED875A5203821E22" + + "DBBD45A12E6B3C296F8B37B7782AAE09CE48837E772BAFB0B6063644FF3B3DBD" + + "861115C3B91C14669E5E92CCA38879F6260D387B6884C368F7246DC74387C404" + + "7086ABA92BE2D3783106C3B6BBDAFB7F9788E1315751E411A5DCCFCBB58B67E8" + + "ED207FB88B5E92302B97256C3CCA280D3670A7DEE71639EEFC0546D651F2F400" + + "A45C8B7643DCD814349CA3099A6CF5384CDAB9A9668FED88C40EC7ABD1E0079A" + + "F4CFAC8799506D5330A5A97B2988073893A98611327B9806D5B7E0B2BB46FB0E" + + "A2304A2F6A21357D0A3282A149E6303B8A06D9ABEB0518EE665D05DFD1207CE2" + + "4AAF471334D61524FEB2BCAF02D09C400E6EF7748BC71DC7F2098E82EB18A367" + + "1061F2BDFDB063D1823791C182B22AC24E7128287C036CBFD5998B2BA25B1601" + + "937EF2403AAF3B582662D50558D12F3BFE0C4A4174EE2856171FAAB8DD94A065" + + "8D5016CD4F6224B06E9E7A179BECA8FA90F9419982CB5799AA024F8CD4C33CB4" + + "2BD2BAD207D8EE12F739028B04D7015DA37DEDE30A2855FA99A5D33F68460E36" + + "C7E28CF4C87A13B2E92EA349D394ABE6A9C0BD0A2E9BFBDF8961DAAD2F5BB547" + + "7E088EEDFE2858E816815594DF0D6DF581E41F8E758089344CBF536FCAAE2859" + + "2E170F4A11455DB0D3D7D2D5B8E2D951603B9FAF3AA1F76F9CEB0A4988D0EE6C" + + "F0A6FC537C74F6F1A66C38790BBDEF0DE139DD931F1DA04806474931CE5F5F3B" + + "6B419D2DE5B390F94BB1EBCEBAD49E56A7333C6803C0B30FE9A354B81112A93A" + + "57CA90CE91E9FB92163E87A223D02C917A85F7AED5B4074750B79ECD116D86F0" + + "0C7E053C1D113B3281423F8A3CA78FE67E3DE3E6CD7D6BDAE0E4A69EE3B3EA76" + + "7EB2A9AB24124AE29B00CFA484B8CF26E6C7228CB95261F96E6EB8A0B0EB153D" + + "B6BF8B5D1352CEC2C7FA6C4F5DB10AE2023F85C6A6225127E769205B047AF02C" + + "3F6F18F1B1A590B26F29F1632E47B8231BD40C9BA6AC7140B5493CF3CE58F85B" + + "0ACD857B8EE850B82522757FC12B142C1C8A9E76F68C38C779593207B146D598" + + "64C676CDAA4FE83A3FE6B2974B89D4D04CE9E1ED3A95A1402C1242422A6782E4" + + "EC846091719BAB4A4BA6DF294B3E35764D3E41F2057061354694AB5432B02470" + + "EF92768C838B8E472B5CD48E4BDCACC08157AE2BAFC50C309C30A9B52E12B221" + + "961F251E84C8A69342D14B23AAE57E5295EEDB55A2B3AEE0494CD59CB9B392DD" + + "A1EC7C72282336385561505B1F772BF592C7A3ED6FCE4CCB8249EF83960B841C" + + "9664ECA0409D1DFDB9D926D331011B3FC906968B364CD0C6D0B8523C24204234" + + "CAB129D1A1CF17FAFF85E16B215052E886EFE988813DF5AEF7A525798023021D" + + "D821D867427BB605D7DBB4A522078EC9E3D6E863CB54EFD79B291058EE264945" + + "6D61B5A93ED32B507F0DDFD60BEB3258BBB8577FAA4763E06F77F135C8C62DE4" + + "CCB766EF06DC5A7AAA3E8AC42008DEBE1F70901FAF8B6937FD18FFA9B9DD856D" + + "2136E0814817DE4CC48B129CA09C5A58D7FFCF8C1978C54DFEE521DF01AD683F" + + "682066B142B86CF8BAF94E42369BFC4A5842D9E68C3CB2DF69AD0595D60D998F" + + "DD26984428BEEFB4EF36376D4EA6940CA9A286A7AC285F00FD2AE8740E7BA3E2" + + "1E85CF48F03231CBF7CBA3836A5ACAB14FDDD15F0F90EA21C593FF6E134721E3" + + "FA2704E4473CDBB58A00F88535D5668F9B30A2C11FF44AAA4715BCF6DBC85676" + + "345435564F43A10C1D8BD14434C06A1A75FEC14F77A9102337443EAD5494F2C7" + + "96D8A940F000C78269BC362A08948324057D448966AE0BF05D980DA1C8C8390E" + + "94C56145A62AA07392006B7D36DB3C0541387E826DA682BBAA5436A5DF631653" + + "78D3A1DA28E2B525DAA104457C02A9E2CCCAD37537396478C0441B426197767B" + + "4A37A45D2B31C76DD2DEBB9940D61065F1488DC371B6388BC59054AFEDD80D07" + + "3BF1DC05F10BCD1A519743258CC9354EC43AE806CE9133EE3CD78E2695E0D7EE" + + "017D16A839C66011536EE17C4FF635739828BB6617DC1C74E57702C4BD91B362" + + "2E1DB8D94AD98682B3A07CE713B0C3392081D028E3E28A66DC949513F4CA5028" + + "6A9169A2CE5B16B541440399BA50A98434D62A0C19FD40CF2D6859DC6673EE85" + + "60B7BADADAB9C61B7A7A0CE3CFD261C572B8D6C3C4FAE1B426E8B6CEBECF6D5F" + + "8FB9DF07DA90D0250606B6924363AB365E081C89898C84881965AB4D897FEA21" + + "EFF53408F637A844618288404F251009BEE40D1FBA009AA5F30489FBE4E51467" + + "9346544A82001365FE1F45C5332225F2CDCF9859CF286A0D3C41BF20E421CDAE" + + "96723EBDDD5C7431CA0CADEB4550857DD2828C054F757AC2D62921A7DD6A8FC3" + + "1EFB1E64440FC33DE646AFAE0050CA5BC2799E24CF0C9493396B0EB011393CC3" + + "B8C07AF714B3EAD4FD85959177DF63E84CEC40A449EDE23C3670492E9CE28AFA" + + "4FE4F5AA916E4EA3CCDC2A381EC5675FEB06B541AE428A913CC9EB2C4ED70B04" + + "CB7B0A03776B313326C7698E6EED937C81653421D500D66B70545671C4D0FF62" + + "01B6E6318B177C4FA29B408CAA3776D57B4C0424F7DD0350FBFB60CE27FE8A41" + + "6FB5F61E43DF1538617B993D4229643B7AF9F2F8DB8F5197FBDACBFC8B228019" + + "2A12AC4053B05CF307DCDEC654A0C795A11BFF7E8386F057FEE687C97A2476D8" + + "BF1A7850D8A97FCCF8DB5BCA0818813A05F68B84D5EE3583F8D57E5C919F2F86" + + "800AA4A6A4DDA2A4C6F7028CD9205B7B3A0105CA5394D9B02D74EAE6EC792534" + + "247201A00C32C1C732F863E6538C810D046025CE81B6E7DE5F721F609A3EDBE0" + + "FF0EB459309BEAEF029907C7F16CDB809937057BE54D1FB1DB18B289765F6863" + + "FD398ECECA0524C20709306BE27CC94B3D2C705F7D676BA7CF00DFCFC170F0C0" + + "2EC263AFE2EFC0E6B1B1E7ADA062B2D6DA2D067833B31BE50120351B3EDF8CBF" + + "7BAAA08AFE2A2C3914A1A1AC537AAF4061507066426270E98E6CFBB877BC2AA4" + + "BD3C60EBB630F9788A960BBECE743AC1AE7FCFF28FDE43F7AB14C8216217353A" + + "E25FCB031C2DF336FB09C22D118FF9751323AC9C82A352447F1E6C7AB1E39547" + + "868A5CF5CB44C8108298620E8524A04310EB5C4463D3A50E25AF1ACA506FC1AC" + + "C642C5D5DE0536EC82C8DB9CB17FC612275AD03BF8FF030DD34C3B0B9BC24929" + + "CABC0249DA09CA034A9280CBC3EF09D4C4EB09924F569728499587A1DDA9B185" + + "7FD8B5CB61BE96047A4A5A28C8B7EE4F9F976E0A3CF25620EE783F6BA53719E3" + + "69C3EBF94BC8B229251C34388B01657F0EA45B5FDF1B0EDC25C3F08463ED559A" + + "392820F79CA86CBC0CA7034BF996E98E4FC0255DEE55EC693BD7E20FA123EEB1" + + "BD5FF110E8D85348036342A3330573C03E9F3949ACEB03AB5010173871BF1DAB" + + "AF12D10596AC8E22C48B45CE0E69C6881A4CD268401993631F47A1BEA6C90DF0" + + "CD26D86D32CAC9307FD864CF44841095F636D38233CA73812E9AB12DFCADF391" + + "D9D8733A6D039399871B479B734DCE9A358F5FAFCB39AB43215F8A0635EBC0A0" + + "943EEBA6E7726E57E2F041467FED30D543785B47476DFC0A1BB36C61C726C4B7" + + "1720428889B9F8CA2A82168469EF7E1EEC52E61B8676FCEBFE49E1DBF13761DA" + + "A66DD693BA7E311B042E3BB978DFC50F7177244F8AA32CC09234B7F83367967D" + + "17856EDF91D1D1357B1B4BAC1191BD692AD06BF215CE76B9530B4993E5613D7A" + + "D7FD354D89FAFF2D397E0AEDC3A21D1DA8965CD2C39CA833D218F1B7BFD02643" + + "885881BF15C24916ED1979DFFAAD9B9B6F4A6F4D03C84588CAE47AC7EE9CB9C8" + + "6DCA2DF1D2F92AF46CD5F20E3F7D262C8996FE0CF224FD8D7F848FC2D03E1BFF" + + "01E23DAC01A2A27575CEACD93DB8B330EC4047B82F303177233BFA8094E8861E" + + "0637C9ED617CEFCF60938B78354E80F7E405474BDC35548553D8AF005DE611BD" + + "B52425A99CA1475C63ED881AC909F9B35C83B8572F4A0B51E4E6A66D0381F1D0" + + "09D71577B22D58314023FC3DAD9E10D95D3E340B77A962B93B13E4F595B4BA82" + + "FEF8CB6A7E3F92FBF811CC41D75AD49FBAC4EEA9066F2DACF868CDA63851E1E8" + + "8C939CA85A70D0375D4C9788AFAF31150DEC9AA7401577239C094A8A6F242103" + + "06FF01F613E50249E7CB850109A8CC7FF8A07B8DDA5EE2FB964779F7EB7FD093" + + "47CB0065F2A6B473B974BAFC40A3733D13FECF8C1F4DCCE5FD1FE8791A3B0979" + + "3B84F5A05A80A8B8A7F37197CF4CE48152D052431636863AF42F3240D5B8D4F8" + + "4BB2027B756B54CE93C0902A2DABE8758D118D5E6DD5F60AA44BEE1150ED7551" + + "4610402F58FFAB5C2E6FA177E7C250D8409F6917A5C37A7C051FF62A74EB03CC" + + "74017451A96CF9356E08C75DE4C86AFBF6D2A170BB09251EA914D65FBE1686E3" + + "82F96A7A21840E7AB172D611704D7E32B0C2F4829C8E7576E9BE3332112868A0" + + "1479B6C114ED7983FB9F30B44F299F58AE2925587BCD66F5B9F3E221CE1DF9DA" + + "749D6397854FE5D972805C693FB18943BAA8FBC55B8CF24747217F803F74B2C5" + + "E7637AC7D576E23F644E3E6CF24113E64E1CCFABC56C4BA104BA69A14A9A69F8" + + "B6B1DA8AFD9C8F6730F5BADD3F63F557E63B7BF98DC3DA725AF8485047F61559" + + "03BAD87ED8CDA9EC21BE96B60326F9465119E3F069FA147A25FC11343D531954" + + "CE81C15B31838B8EE1CD25B11AE4A8A7FFC68DA57A828318BBED76596A550C68" + + "72982E099C070812E20C099EBF882B86AB722F02F0EFEAE73CD885E6C36F02F8" + + "1C8DF15AE3C01F0370B02706B0BF4AB292E1488450CE70EDA02292323979415C" + + "91DD1391FEFD5EF4EA539BBFAF1E361826454A2E6CC32324D6C3A5F5D7D88372" + + "3258E59706A650F19B5A6A1C2EDACD23EE3CCCB1F09B9910DC3256DA7A851B8E" + + "A110319F11CCFE7EAD2DAD4D73312A64D6A15D9EBC5DDC912562FB494194B5C7" + + "72290595529184953D1DB67035CE1DBC6C05E15131E2F4114A6D6A0B54866DD4" + + "DCFC00475FCC5C44B3494D23A703388314E20EAFF4C4A034EEA686D589A7E128" + + "CF12599CE46BF7F6E1415CCEB27E3DCCD6715949DED6C4CAC4479F442D4554D0" + + "D0181F637098C9F72B0751F508394C06682A22BE7D587788D010D24786C5E156" + + "A07785A78F737D924580CEA11B845548711310D9D29B04364965252CBCC68A99" + + "B0E8FF248B8F706CC61EB5F0B1142F17FA96E3DC4F43449419ED9C348EBE07AE" + + "66ED2CF037AB4C7B814C73C9F7E7A0B82BB4CA5D301AEE6D1B82858568EA263D" + + "3E5536614A7C77F3AECDF941424B09792246A9738AAFED3939EC319569ED4875" + + "A1B09FDD2167950BF95DAD59F8DCE0FE450E765D0B703FFEB330D032884071B2" + + "F3DE1FF0F5E43C7F180E3F0B45744802E8113311E58C2776A4484A8643CF2567" + + "2638C63B40DCCF80F767D26A5E4A830E15397787FA550FFB0D07872EDD38BBCB" + + "7555C9D7637A503C26E4DA6BB41052C0E1DA2A7B7F33C74EFCC529EFEE43977B" + + "8373A2210EBDB9A7126AD0A6742D7AAA7A73E9BE546344FB35043209E3C8BFB0" + + "527AB4456E6D9F873B4C238DA0491D930EA654F71910ACD69973F01713817B0C" + + "1165F22BDFDA789DBE3D01A3375DEC8C40A0A6EB977B10929CEF89B61274D332" + + "ABFBDA987CFCF14EA59C3FA5D7138AA8C32E1CCAEC3D229E1B4A46A2A9F02EBE" + + "5EEAA9D88122BF053F142E42E8A0E1268A19B77CD4B2A45F68B74EE644D3CCBE" + + "FA586076CA0F8FEDAAC1CA11058E4B9896ED529F613E246F2A4CE29ACE49F0D8" + + "FF6C04150DD03F526DFB7AE7DD751FA746C378AB0D658BB4A808955C9C8C3B36" + + "79426C1941F15835D5FD179BAB3D658D4A0462F617DDF5FCD23EF2C899A52D46" + + "60144C01A542DCBB5C15A8086B6E97262090127E5DB9FB999E45B869833E9641" + + "A7795DC55B0D7971A0EA423F306475E80561384169333D7D26299100FCD24B3B" + + "5AD6A215B8323CAD902A6C1B97A19863F4DDF460780D188391FEFDF013EB4693" + + "D3CFA097C480A10502F21CF5C1C2C45E9CDA63604008EAE8C11112167F539F16" + + "236A4B50D76E8C143AF38ECB60CE07572E9F31C5517D1CCC20AD644B3361EF25" + + "84ED7840AB11F901556CEA40435FD9B491EAD820DBC283D4BFBA3B00A8CF2F0B" + + "99627225326C9C7DF70C89E112CF06C9B9B968E28A148B61BE10B7C8670925EE" + + "77EBEC504F822614D0B0F3F0CDCA3EA9308197304F300B060960864801650304" + + "02030440699B89444D5AB2D939E849803579B6C1651E206FB208C67F879AFFD6" + + "32E080D8D15BDD48651241FF03180ADE528193DB946145CFAA069790AF3405E7" + + "81BA7445044055FC4F56A8FA8F63539E4AD754A11A1CE1BCF972388D24023EB4" + + "0E8B8907D86A9F4715D3591307E9DFC832B7756EB214BDADAB09F9E1E61AB184" + + "3EC3297C0D4302022710"; + + internal const string Pkcs12Builder3DESCBCWithNullPassword = + "3082088E0201033082084A06092A864886F70D010701A082083B048208373082" + + "08333082082F06092A864886F70D010706A08208203082081C02010030820815" + + "06092A864886F70D0107013024060A2A864886F70D010C010330160410F19120" + + "18896CFBB4653C4B7C06E67C7F02022710808207E02D736F0AE772F48FF976AE" + + "91E8614648678AB5A318CF7D577713881F80B0D6FBF645446359584803814B99" + + "1A8BFF573CBD1D52AC5237EC7A42ED303474221F91529FDE33DDC2126EB4AAD7" + + "65CCAC633209A0AD43DCDB5C1D4ECFEA856EFFF607F03D66B29D433F268C7E74" + + "993F5F2384F9E0D08C6657CC7AD32549CB8D893A1EE37A24E398A44987D23E79" + + "B3E4F3F48B106FD6193812634F999CDEB1E5E3485D642B4DA850BE1C210F9321" + + "3BB1E01AB38465C5B23FB80AAA6E1421A2F20BE775F658BB52F57B4CAB79197D" + + "E65860D656CE8135E235A3C7E06B511F1BE398C03416BC137E063DC8CF8B7100" + + "628DC62B87A70A282C11BA08A08AB0E03814A9B1940145AC0EC3327396AD6984" + + "4BE0B4883DAFC5A611804FB628B598DD006ACC039A86B23100B102E1F4B3CCFF" + + "06FA1E9841DBA8913B9D1D15D6A16330A94F55B04D9779A90EDC91230A664C41" + + "9AC825594D9F3F39A08074E06E5B671469E3AC9D20D906FA9B99CDAB6696A952" + + "49F7B3CCBB8EC1BB2714C248AE0C3D0934F949D68995A785F782910BB8457B66" + + "1B4EADA3724023BE1DE63144C3661055986A2E4D2F59A2DC018EB8E6178E9DAE" + + "14027352738A4D3579C55F48D0C373C9280689DC509EF602C69EF10566043EF9" + + "F1A0852A618103B6C2039574696D64C8492963B54C5BCBD4B124FF5F93B04DF2" + + "F5C1FB577A2BF8D24D29D7C6630071EAB5A3CCBF7DA9B4F7CC39673CDD25ABB8" + + "9A805838B32A002CEEC02404A78BEC048DE5D8AD470FAAF89F31EA7E42ED1DD1" + + "20B66246AAB7BA1FEA3DCAF7A78BCF679A3FAD5029318D69EDA8F081FC7216A3" + + "EB610BA3F6EEFE78660CDB365055110446F73D0FB468D4F4FFF01C394C9FDD20" + + "47792192AD9A46458E3BB63BA4703A7D8D4E56776D48312C5033497795A396B8" + + "60115AA3FCEB1E3CAED4FE9211787A8B4B0BC1671A3104DA4A7925A1E3D661B4" + + "35760FD3DDF71A5902269288512C637C94DD1DB6B8551EE951019294342A50BC" + + "4310BACBEF7313D82CE7D351FC2E9114BA421FF1EC206BFE1DCA5E772E90BB92" + + "E7DEB1CE899CD9328C09BF299F7ADFC9D43AE4721FD36BAA93E50EA6B8B6DA5C" + + "7A188AEC11EAC6EE755D60BA5FE98ED8B8D2360972C114DB4A17CEB5BF8EC1DE" + + "8EA0D6A4B26F40376B2C5D66657DCE4A2A2F3E519C65035E51981A6A74415AFA" + + "9BEDB27B2A6B175DAA953919580EB1ABF52D15E2CCC725AB0BE5F09864FBD0E3" + + "6EB76E8ECCA70C1A850197BA84698A00EE1AE2EB95DD79F002EC2401DF3AE3F8" + + "1C68FAD724C59E51AB60AB22C60A2E6E0CCE2E9BA5F9E2E503946CFA77CF6713" + + "E9B98253C42F3A68A6487D2CA4ADF6D0CC8A13962F5569AAE34C3500414CB363" + + "DDED7F3D3BD5BF6A0E1B229136F23362FD016595AD0F825E30BEEB9E2F95124A" + + "6033D3BF9CE8758AFD964B10437DEFD03FB28BD46D3153FACF19D6405D260B1B" + + "257B138D0BDF3AC006CE3C22D1626BE10E8613F6912536D07EBC6142D3EE8A3B" + + "9D7321D35DB2A78A1C3376894D5C2A1C3E41BD7BD8190007327505E76247C6D7" + + "3B7E78E098F4504B205D35EC50987B601F76FE6363AC0E2FDC89853CEEF2BFC1" + + "08E4CD798C20AA7B326A81736B5FDB9365B5272DDF0CB692230A5C69A37DA5A4" + + "7241213B95C44B9733700A7D4216043860C649E979E9B8C304C1C02E7981A502" + + "60233E8539A01A361FDE3B83A8B42259FCDAD89FA279CEFBA6F769C562E75E9F" + + "58FCE65C6D11A7F701161092E78DDBAD9D3FD407DDF675A46348DF53E9EF7CD5" + + "FB7CE0A3C1B7EA0138529D061CD3CE3A76FB40138ECCD2A29BED34E27E2494D2" + + "D3787326C11AAE5933BAE7FFA6F5F21D33FED6CDDCDF5CEE3C1D7A8FADCD8EB2" + + "E77A75D01A50B38E445D91A986F8D1C1100E37A9AA5E83823280236482425DEC" + + "F49EE6D898E9D8FA3E0F502B50EF968AA14220E926D1ABDD225624E81AB0DACA" + + "A781857C260B9E712F644A87D5AFE0EB3D73C9999073F3C3835473C3C4716990" + + "DD57540B5A0A2D433F3A7F6CA74D046658FF85A9AFCE68DF76ADFC9CB682F80F" + + "29F1A15257A9ABA43641C68A405A88F499ED3B29D097BBA995F1D29616CC47CD" + + "D8FAAC992A8E88D7A4E033E1D37B5DB2F38DB1E37B2A6B1A094A621BBDB70B67" + + "EB35E63425BEE4C0549D2B30FC9207FFE0BA8C3B39EC8562AB61D0A77F78CAD9" + + "D5C6227C7EDD91316D5202D6AC8CB5503F4FA01BB76A47C59FBEAEF8064709A6" + + "CC2DD5BFAF4C96535A1F699AAC58C213BC1DA0043252C5C2E2852F3B0326D428" + + "A3EB3CEB1372D65271F23935DA069CDB2E2446B26BB98EE04516548482EF7D9E" + + "2A855266521BED66156D491E7FA20D723054F55930D0E02A356659B7513CED09" + + "8666D05B6C3EC9281048F57031992620BB3F582F5963AA167BC7F8C8DB07644B" + + "8AE5984CBA7122A67275E024B3790178C8DE7F260D0D2FCB643B990FDC514F5F" + + "88B9EE89D16B20E26FBB2FE315347E972A25B6DE4DED8D69526C506004C46918" + + "13567486B8CD40E4D710069F137ED0E5EC4A493ACA9545F395935E145CB63354" + + "4D436F9FB5BDF0B154E72867FCD9A2F8675D38FAD9CBD2B1A4EC01B78C229445" + + "FD2B4232DA613A5BD9847CC2F19E624F6B1223E82F6F12CD97740E938C34FEE2" + + "54F775437183BD93D52F96C4C1ACE5ECE2D70F1C42DAA699BB76AEEA5693C7C4" + + "0B5DCB4E6D61E648E5335B06B2E0BFB55F2F338033DF38D8A2C8AD9760F0B21E" + + "8DB0DF9AF8E682E6F62F0C70A9E921FA86A7C9EFFFF2A4302F94604D1F991AA4" + + "F6B1D3B7E46BBE4126C874583281746CDEA73337A904110E94B333CB6BFFF28E" + + "1D0A0516EA5F72876614328AD34B4C1148B0930A2E303B301F300706052B0E03" + + "021A0414C1F4E43998F3594C85C97FC9C5777848189A67420414104FBC73DE62" + + "EFB93E15B5A39DE7E0C1B46E20E102022710"; + + internal const string Pkcs12Builder3DESCBCWithEmptyPassword = + "3082088E0201033082084A06092A864886F70D010701A082083B048208373082" + + "08333082082F06092A864886F70D010706A08208203082081C02010030820815" + + "06092A864886F70D0107013024060A2A864886F70D010C01033016041039A75E" + + "DA3FFCB2391E25BF504AC4BBAA02022710808207E0A9EFBDBE9CCF94EBD69A0A" + + "22DAD13EE5036E45C5A28F2C15888DE9A6E357D3A35E9C466E3101DD33B08AE3" + + "B17103506D371A69D230C1F00DE33487E0B9DE8318DB88397D13A6B8B172CB2D" + + "C57CE7D3D273878ACDEEA06F6D49D06757B7CED3F6958D98620AD7FB303D9CE7" + + "5F0B0880C9F3D2762157B946963FCA3E4C7DD3CF1BD359CA27CEDEF45613D8C4" + + "2ADD13B133997B508A53C56C1581A87C03F0A946C33226D6F40F523B7F920985" + + "470B0B5E5EDD5401C4BE78072D3333CEDF47FEBF83EEFBC7E6F9D9D02AE95384" + + "B68DF04EF7BA859B6D5AFC6FD9C918BEF427C49D5097E7645FC3BBFD9CA29EDB" + + "09F89908937E2B51FFA2F806CA0EE6E09A1CDC9F73D3E8393F1B9DE437709FF9" + + "59E4AEB2524C15269A871A4F6201D15846CA40F7F052AF72909878945894016F" + + "6BFF0B966338D371BAEE16EF7E3151FEE91F3EB6AA48E91B7580FC1ADB3456B5" + + "2382EBAB36548CA3521A583647CAEB75C50EBF485AECD50EDF6DF6B630031A5C" + + "FBDB9340C05F5F94B2622B8A0DB23B2D658D6F5733DD65328B1EDB4779D318E7" + + "CC704C7B7B78B950DEFAE77872CAE2BB1E25BA7BCAB8C04ED12F6EAF48808C79" + + "7E9C04FE4F7444A7B58D7E8A6E5445729C44E9118158C62E2760BA6D014EF026" + + "8EFD70AE83E45FC1EF05B9043C55E5AC4393508CAF2A36932ECDF77495C35036" + + "4F4C92AE4DEF9475A7F274F946EAF3347D05BF49725C86CFF72579006636F096" + + "FA49D5183100271F94C19D292DE0A7C78A8D2AA347396ACAFF36A123135FDB45" + + "604E3B829C00DF082B7010B41DBD62416315C2AC384E7D700779C592487F69F3" + + "917B391246A24F8E76258F8D3219A3A6D1313443CF78BEF667FBFDC507191625" + + "1913B729E11E895B1840635882997E5C428DB006A875E561AC0758F80F702E33" + + "DD985319B2D6BDB1EA0D403A761968494BC77CAAF4CE42B6E9124083134989A2" + + "877077CAB2F8EDFC8EC13C255022C3AF77A40A3BB5CE1B76A57DC5648234346C" + + "A072852934F310D3446CBD129858D00A64462E89E3C61D128F1C9590CE9A6284" + + "CF29EC375DB56B79F13CB404AC4320BF491472FB0FB1D530D68C82E2029C7CE1" + + "2AF38F419C163454EFFC7FE6EE590BCC3543E2B48AE9A43358E76C4B2D90AEC8" + + "CFC82BFFCCE4DEAAA23E4944C3034B4C1341FCA68246F328B65341442571FEC6" + + "F3671DA0284FF6789452C081DA021CDD3FDBAA34E82FE0C68B75321488018EBB" + + "FE787787A89058696E4F92E23211085EADF706462391F1F631CD87CAD48D72FF" + + "1EDE98CAE24DA0C776F342FECE74B1EEBCA4B8FCDEF4BC9AB952C04F79D5B235" + + "680782399746091BFC93577B863CCF499D93736CAB5500A4C45DE78FAD5E57D2" + + "E22D1A5F7C85FDEBE52F0431F980E90B44C0250079BCB09D4C2E3CCFB6E9930E" + + "B9EA497E7035FDF826600F795E3CC9EB0CE66DC84131B8EE3D55829DF48F6739" + + "0BD11F92B92D20C86B93FC9F9DDEE2C0D7DFF25275BFD25D7C2FF5BED8B4789E" + + "BC5AE940D802C0A86BC0CBE2958BC93B7D80C3272945032AC9B0FAD174A636CD" + + "68500BAB5A53A399A9630F8B523A1639A7B313F3F0517708EFD57E4E57319955" + + "48887831D86087F6D4B5180559CBC461C29327D5161518DD88E0761BF0CE05A2" + + "7FE504C84F6ACBA1C87A1284ACF18D5EE2B17B63549C35951CCC582BB8975EA7" + + "B49E7C061933B53724D25EE9F8F04F2A36B8B1F293A1A76B822C3BB0546C029B" + + "91F3FE656778236EA95B978DAF9987AD80757696DE2393149A260B5EF0C6437D" + + "DA8A63B8A486E14F42B8D1A69725CDE49E68C867B5F87D9E3CBDB4D64045C0CC" + + "50ED426A5F78CA1216AD394F3A4CD33FF6AC219AF8ED4555079511E49C288E96" + + "1165A20134EC21A5100FA597133B2B81646E245E5C94C26247112982667CE49A" + + "5633663629BC8280A4115100F2A3B4384469D3A0A7DE8D35D2FB984EE0190A0F" + + "C70CE790CF27CD3F4D261F941BEA6478CE155C5A409204F1298FCA20B1D3F095" + + "ADE129236F101BBE9D766DAFFD9D12296AAA618FE1FA8E0EB0B4D873AF67B1DC" + + "A3AC63D935952FF833621D1E7E06AE0C5749E60941D9B29D3E68968DF21E31AF" + + "DAC972B604CE613E98BBFB40BBEADA6AE85F716BD655066B1CCBEB11CB48C5A7" + + "56B4B7C96BE9DCD3DC8B74CAADC4CA7038DA00B867B35185355EB0D2C2FC76D4" + + "2842B307D92B707CB61F9BC8BF6AB1FC9EE8D0F5A8C3A1EECED5D6FB1D13A38F" + + "B2D17E0513AA4F126B5D5FC9029E574179C447D04D5A22063B60E88C48A4F52C" + + "949F49841DBF73A2F884239F18BBE35453BF67611036781876920157358303B2" + + "BF9D17473EBAD888D5A612BDE9AC41778B33F660C7C2922B654CAB899F16F017" + + "ABDE8660ABF43652ED8AB2B9177CB407E79B3B94FDD61407618B77FE980A727B" + + "BBC8B3034B0FF138C6B32B0AC9B0A851FEA1A8383EE1C571A55E0ABBD63B55BC" + + "3A5F87A3ABC9D69BFAC4FE5AFF937F536A66D9EECC8CEB491BFD3505564AA8DB" + + "0EB624817F7D6E848E505C320349697F13026A024F8D5C74E0DE9065974CD0C1" + + "D8D6D7C55C0721EFF5A960C6A44F7FCFC432998859C397C33171A3E539BB2FB3" + + "C0939BFC3D63BA3D03EF18F11CCFD4F95AB2C99AC69CCFAB692659193FF81FB6" + + "5A2A4ED12C75E2B3E12C5B76420FCB34C94CB5140AAE2F96F5CE0C6C2784CF30" + + "88F10B7DE2B2FE8F486E7A5A8858891A98DC460C51730909688BC9E1DB92DD3E" + + "B6BED869FC7D708FEA4BA6FC5DEADAF86DEBECC75A4FB0FB61FD19C05F371EBC" + + "EA880808ABAA83CE2B447F7DE021900D6777A7377FB990B85DDCFE64A36C8FD5" + + "09463C6E50BCA36EB3F8BCB00D8A415D2D0DB5AE08303B301F300706052B0E03" + + "021A0414A57105D833610A6D07EBFBE51E5486CD3F8BCE0D0414DB32290CC077" + + "37E9D9446E37F104FA876C861C0102022710"; } } diff --git a/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs index 6ebaa978de95e2..f53e582af6e295 100644 --- a/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs +++ b/src/libraries/System.Security.Cryptography/src/Microsoft/Win32/SafeHandles/SafePasswordHandle.cs @@ -14,7 +14,13 @@ internal sealed partial class SafePasswordHandle : SafeHandleZeroOrMinusOneIsInv { internal int Length { get; private set; } - public SafePasswordHandle(string? password) + /// + /// This is used to track if a password was explicitly provided. + /// A null/empty password is a valid password. + /// + internal bool PasswordProvided { get; } + + public SafePasswordHandle(string? password, bool passwordProvided) : base(ownsHandle: true) { if (password != null) @@ -22,9 +28,11 @@ public SafePasswordHandle(string? password) handle = Marshal.StringToHGlobalUni(password); Length = password.Length; } + + PasswordProvided = passwordProvided; } - public SafePasswordHandle(ReadOnlySpan password) + public SafePasswordHandle(ReadOnlySpan password, bool passwordProvided) : base(ownsHandle: true) { // "".AsSpan() is not default, so this is compat for "null tries NULL first". @@ -47,9 +55,11 @@ public SafePasswordHandle(ReadOnlySpan password) Length = password.Length; } + + PasswordProvided = passwordProvided; } - public SafePasswordHandle(SecureString? password) + public SafePasswordHandle(SecureString? password, bool passwordProvided) : base(ownsHandle: true) { if (password != null) @@ -57,6 +67,8 @@ public SafePasswordHandle(SecureString? password) handle = Marshal.SecureStringToGlobalAllocUnicode(password); Length = password.Length; } + + PasswordProvided = passwordProvided; } protected override bool ReleaseHandle() @@ -94,7 +106,7 @@ internal ReadOnlySpan DangerousGetSpan() SafeHandleCache.GetInvalidHandle( () => { - var handle = new SafePasswordHandle((string?)null); + var handle = new SafePasswordHandle((string?)null, false); handle.handle = (IntPtr)(-1); return handle; }); diff --git a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx index 4dc40bba0b1b7a..fa55fa3a86431c 100644 --- a/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +++ b/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx @@ -822,4 +822,7 @@ Unknown error. + + PKCS12 (PFX) without a supplied password has exceeded maximum allowed iterations. See https://go.microsoft.com/fwlink/?linkid=2233907 for more information. + diff --git a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj index cf25738f6e7bab..fefe1086c00aab 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -1,4 +1,4 @@ - + true $(DefineConstants);INTERNAL_ASYMMETRIC_IMPLEMENTATIONS @@ -73,6 +73,13 @@ Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml.cs Common\System\Security\Cryptography\Asn1\DirectoryStringAsn.xml + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml + Common\System\Security\Cryptography\Asn1\DssParms.xml @@ -225,6 +232,59 @@ Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.manual.cs Common\System\Security\Cryptography\Asn1\X509ExtensionAsn.xml + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs + Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml + + + @@ -718,66 +781,6 @@ Link="Common\System\Security\Cryptography\ECOpenSsl.ImportExport.cs" /> - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - @@ -1099,66 +1042,6 @@ Link="Common\Interop\OSX\System.Security.Cryptography.Native.Apple\Interop.X509Chain.cs" /> - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\DigestInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\CertBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\MacData.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.manual.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\PfxAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs12\SafeBagAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\ContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedContentInfoAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - - - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml.cs - Common\System\Security\Cryptography\Asn1\Pkcs7\EncryptedDataAsn.xml - rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + private static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -67,6 +67,8 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH throw new PlatformNotSupportedException(SR.Cryptography_X509_PKCS12_PersistKeySetNotSupported); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); + return ReadPkcs12(rawData, password, ephemeralSpecified); case X509ContentType.Cert: default: @@ -85,10 +87,15 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH throw new CryptographicException(); } + public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { byte[] fileBytes = System.IO.File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } // Handles both DER and PEM diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs index d042ade14b0be1..daab1181c0e620 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.iOS.cs @@ -91,6 +91,7 @@ internal static ICertificatePal FromDerBlob( ReadOnlySpan rawData, X509ContentType contentType, SafePasswordHandle password, + bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -116,6 +117,7 @@ internal static ICertificatePal FromDerBlob( throw new PlatformNotSupportedException(SR.Cryptography_X509_PKCS12_PersistKeySetNotSupported); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); return ImportPkcs12(rawData, password, ephemeralSpecified); } @@ -143,6 +145,15 @@ public static ICertificatePal FromBlob( ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + + private static ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + bool readingFromFile, + X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -151,11 +162,11 @@ public static ICertificatePal FromBlob( rawData, (derData, contentType) => { - result = FromDerBlob(derData, contentType, password, keyStorageFlags); + result = FromDerBlob(derData, contentType, password, readingFromFile, keyStorageFlags); return false; }); - return result ?? FromDerBlob(rawData, GetDerCertContentType(rawData), password, keyStorageFlags); + return result ?? FromDerBlob(rawData, GetDerCertContentType(rawData), password, readingFromFile, keyStorageFlags); } // No temporary keychain on iOS diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs index 4e9d87d798c3f1..ed045143f94d70 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.ImportExport.macOS.cs @@ -18,6 +18,15 @@ public static ICertificatePal FromBlob( ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + + private static ICertificatePal FromBlob( + ReadOnlySpan rawData, + SafePasswordHandle password, + bool readingFromFile, + X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -42,6 +51,7 @@ public static ICertificatePal FromBlob( throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs index 01a60958416186..26a1f569abe17b 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.Pkcs12.iOS.cs @@ -7,7 +7,7 @@ namespace System.Security.Cryptography.X509Certificates { internal sealed partial class AppleCertificatePal : ICertificatePal { - private static SafePasswordHandle s_passwordExportHandle = new SafePasswordHandle("DotnetExportPassphrase"); + private static SafePasswordHandle s_passwordExportHandle = new SafePasswordHandle("DotnetExportPassphrase", passwordProvided: true); private static AppleCertificatePal ImportPkcs12( ReadOnlySpan rawData, diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs index fb8c18acdcb39e..594bc8f5e8c1a7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/AppleCertificatePal.cs @@ -70,12 +70,12 @@ public static ICertificatePal FromOtherCert(X509Certificate cert) return pal; } - public static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + internal static ICertificatePal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); byte[] fileBytes = System.IO.File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } internal AppleCertificatePal(SafeSecCertificateHandle certHandle) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs index 904d84b8c6c63b..793725130ca4f8 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/CertificatePal.Windows.Import.cs @@ -85,6 +85,7 @@ out pCertContext } pCertContext?.Dispose(); + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile: loadFromFile, password.PasswordProvided); pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); // If PersistKeySet is set we don't delete the key, so that it persists. diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs new file mode 100644 index 00000000000000..0b7eb187e76b0a --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/LocalAppContextSwitches.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System +{ + internal static partial class LocalAppContextSwitches + { + internal const long DefaultPkcs12UnspecifiedPasswordIterationLimit = 600_000; + + internal static long Pkcs12UnspecifiedPasswordIterationLimit { get; } = InitializePkcs12UnspecifiedPasswordIterationLimit(); + + private static long InitializePkcs12UnspecifiedPasswordIterationLimit() + { + object? data = AppContext.GetData("System.Security.Cryptography.Pkcs12UnspecifiedPasswordIterationLimit"); + + if (data is null) + { + return DefaultPkcs12UnspecifiedPasswordIterationLimit; + } + + try + { + return Convert.ToInt64(data); + } + catch + { + return DefaultPkcs12UnspecifiedPasswordIterationLimit; + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs index 2abdf8a791c864..309df74ed074a2 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslCertificateAssetDownloader.cs @@ -24,6 +24,16 @@ internal static class OpenSslCertificateAssetDownloader try { + X509ContentType contentType = X509Certificate2.GetCertContentType(data); + switch (contentType) + { + case X509ContentType.Cert: + case X509ContentType.Pkcs7: + break; + default: + return null; + } + X509Certificate2 certificate = new X509Certificate2(data); certificate.ThrowIfInvalid(); return certificate; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs index 4e07816023dae5..441aadebda8428 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslPkcsFormatReader.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; using Microsoft.Win32.SafeHandles; namespace System.Security.Cryptography.X509Certificates @@ -241,6 +242,7 @@ internal static bool TryReadPkcs12( ReadOnlySpan rawData, SafePasswordHandle password, bool ephemeralSpecified, + bool readingFromFile, [NotNullWhen(true)] out ICertificatePal? certPal, out Exception? openSslException) { @@ -249,6 +251,7 @@ internal static bool TryReadPkcs12( password, single: true, ephemeralSpecified, + readingFromFile, out certPal!, out _, out openSslException); @@ -258,6 +261,7 @@ internal static bool TryReadPkcs12( ReadOnlySpan rawData, SafePasswordHandle password, bool ephemeralSpecified, + bool readingFromFile, [NotNullWhen(true)] out List? certPals, out Exception? openSslException) { @@ -266,6 +270,7 @@ internal static bool TryReadPkcs12( password, single: false, ephemeralSpecified, + readingFromFile, out _, out certPals!, out openSslException); @@ -276,6 +281,7 @@ private static bool TryReadPkcs12( SafePasswordHandle password, bool single, bool ephemeralSpecified, + bool readingFromFile, out ICertificatePal? readPal, out List? readCerts, out Exception? openSslException) @@ -292,18 +298,21 @@ private static bool TryReadPkcs12( using (pfx) { - return TryReadPkcs12(pfx, password, single, ephemeralSpecified, out readPal, out readCerts); + return TryReadPkcs12(rawData, pfx, password, single, ephemeralSpecified, readingFromFile, out readPal, out readCerts); } } private static bool TryReadPkcs12( + ReadOnlySpan rawData, OpenSslPkcs12Reader pfx, SafePasswordHandle password, bool single, bool ephemeralSpecified, + bool readingFromFile, out ICertificatePal? readPal, out List? readCerts) { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); pfx.Decrypt(password, ephemeralSpecified); if (single) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs index fe1fa8f95dd1e6..64ae8fb9a365a4 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/OpenSslX509CertificateReader.cs @@ -52,7 +52,7 @@ public static ICertificatePal FromBlob(ReadOnlySpan rawData, SafePasswordH TryReadX509Pem(rawData, out cert) || OpenSslPkcsFormatReader.TryReadPkcs7Der(rawData, out cert) || OpenSslPkcsFormatReader.TryReadPkcs7Pem(rawData, out cert) || - OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out cert, out openSslException)) + OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, readingFromFile: false, out cert, out openSslException)) { if (cert == null) { @@ -87,6 +87,7 @@ public static ICertificatePal FromFile(string fileName, SafePasswordHandle passw File.ReadAllBytes(fileName), password, ephemeralSpecified, + readingFromFile: true, out pal, out Exception? exception); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs index 7c31e1f3734354..1c6d27c1f94fda 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Android.cs @@ -15,7 +15,7 @@ internal static partial IStorePal FromHandle(IntPtr storeHandle) throw new NotImplementedException($"{nameof(StorePal)}.{nameof(FromHandle)}"); } - internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + private static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -24,6 +24,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass if (contentType == X509ContentType.Pkcs12) { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); ICertificatePal[] certPals = ReadPkcs12Collection(rawData, password, ephemeralSpecified); return new AndroidCertLoader(certPals); } @@ -34,10 +35,15 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass } } + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags: keyStorageFlags); + } + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { byte[] fileBytes = File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags: keyStorageFlags); } internal static partial IExportPal FromCertificate(ICertificatePalCore cert) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs index e1c4a49284961c..4d31433360c0b1 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.OpenSsl.cs @@ -37,7 +37,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass if (OpenSslPkcsFormatReader.TryReadPkcs7Der(rawData, out certPals) || OpenSslPkcsFormatReader.TryReadPkcs7Pem(rawData, out certPals) || - OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, out certPals, out openSslException)) + OpenSslPkcsFormatReader.TryReadPkcs12(rawData, password, ephemeralSpecified, readingFromFile: false, out certPals, out openSslException)) { Debug.Assert(certPals != null); @@ -108,7 +108,7 @@ private static ILoaderPal FromBio( // Capture the exception so in case of failure, the call to BioSeek does not override it. Exception? openSslException; byte[] data = File.ReadAllBytes(fileName); - if (OpenSslPkcsFormatReader.TryReadPkcs12(data, password, ephemeralSpecified, out certPals, out openSslException)) + if (OpenSslPkcsFormatReader.TryReadPkcs12(data, password, ephemeralSpecified, readingFromFile: true, out certPals, out openSslException)) { return ListToLoaderPal(certPals); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs index b4d796eb4357fb..b76d6ce25f87ca 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.Windows.Import.cs @@ -68,6 +68,11 @@ private static StorePal FromBlobOrFile(ReadOnlySpan rawData, string? fileN { rawData = File.ReadAllBytes(fileName!); } + else + { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile: false, password.PasswordProvided); + } + fixed (byte* pRawData2 = rawData) { Interop.Crypt32.DATA_BLOB blob2 = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData2), (uint)rawData!.Length); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs index 02c3af95fa66f3..41ce25dcb00d11 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.iOS.cs @@ -15,7 +15,7 @@ internal static partial IStorePal FromHandle(IntPtr storeHandle) throw new PlatformNotSupportedException($"{nameof(StorePal)}.{nameof(FromHandle)}"); } - internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + private static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { List? certificateList = null; @@ -23,8 +23,8 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass rawData, (derData, contentType) => { - certificateList ??= new List(); - certificateList.Add(AppleCertificatePal.FromDerBlob(derData, contentType, password, keyStorageFlags)); + certificateList = certificateList ?? new List(); + certificateList.Add(AppleCertificatePal.FromDerBlob(derData, contentType, password, readingFromFile, keyStorageFlags)); return true; }); @@ -45,6 +45,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass if (contentType == X509ContentType.Pkcs12) { + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); ApplePkcs12Reader reader = new ApplePkcs12Reader(rawData); try @@ -94,12 +95,17 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass return new CertCollectionLoader(certificateList); } + internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); byte[] fileBytes = File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } internal static partial IExportPal FromCertificate(ICertificatePalCore cert) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs index 5587d6330e5cdc..69e48fb4868780 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/StorePal.macOS.cs @@ -25,6 +25,11 @@ internal static partial IStorePal FromHandle(IntPtr storeHandle) } internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) + { + return FromBlob(rawData, password, readingFromFile: false, keyStorageFlags); + } + + private static ILoaderPal FromBlob(ReadOnlySpan rawData, SafePasswordHandle password, bool readingFromFile, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(password != null); @@ -37,6 +42,7 @@ internal static partial ILoaderPal FromBlob(ReadOnlySpan rawData, SafePass throw new PlatformNotSupportedException(SR.Cryptography_X509_NoEphemeralPfx); } + X509Certificate.EnforceIterationCountLimit(rawData, readingFromFile, password.PasswordProvided); bool exportable = (keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable; bool persist = @@ -86,7 +92,7 @@ internal static partial ILoaderPal FromFile(string fileName, SafePasswordHandle Debug.Assert(password != null); byte[] fileBytes = File.ReadAllBytes(fileName); - return FromBlob(fileBytes, password, keyStorageFlags); + return FromBlob(fileBytes, password, readingFromFile: true, keyStorageFlags); } internal static partial IExportPal FromCertificate(ICertificatePalCore cert) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs index 59a82d473dc575..4abf6efbbe0f37 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate.cs @@ -3,11 +3,14 @@ using Internal.Cryptography; using Microsoft.Win32.SafeHandles; +using System.Buffers; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Formats.Asn1; using System.Globalization; using System.Runtime.Serialization; using System.Runtime.Versioning; +using System.Security.Cryptography.Asn1.Pkcs12; using System.Text; namespace System.Security.Cryptography.X509Certificates @@ -62,7 +65,7 @@ private protected X509Certificate(ReadOnlySpan data) if (!data.IsEmpty) { // For compat reasons, this constructor treats passing a null or empty data set as the same as calling the nullary constructor. - using (var safePasswordHandle = new SafePasswordHandle((string?)null)) + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) { Pal = CertificatePal.FromBlob(data, safePasswordHandle, X509KeyStorageFlags.DefaultKeySet); } @@ -90,7 +93,7 @@ public X509Certificate(byte[] rawData, string? password, X509KeyStorageFlags key ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags); } @@ -105,7 +108,7 @@ public X509Certificate(byte[] rawData, SecureString? password, X509KeyStorageFla ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags); } @@ -118,7 +121,7 @@ private protected X509Certificate(ReadOnlySpan rawData, ReadOnlySpan ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags); } @@ -162,7 +165,7 @@ public X509Certificate(string fileName, string? password, X509KeyStorageFlags ke ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromFile(fileName, safePasswordHandle, keyStorageFlags); } @@ -174,7 +177,7 @@ private protected X509Certificate(string fileName, ReadOnlySpan password, ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromFile(fileName, safePasswordHandle, keyStorageFlags); } @@ -190,7 +193,7 @@ public X509Certificate(string fileName, SecureString? password, X509KeyStorageFl ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { Pal = CertificatePal.FromFile(fileName, safePasswordHandle, keyStorageFlags); } @@ -302,7 +305,7 @@ public virtual byte[] Export(X509ContentType contentType, string? password) if (Pal == null) throw new CryptographicException(ErrorCode.E_POINTER); // Not the greatest error, but needed for backward compat. - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { return Pal.Export(contentType, safePasswordHandle); } @@ -316,7 +319,7 @@ public virtual byte[] Export(X509ContentType contentType, SecureString? password if (Pal == null) throw new CryptographicException(ErrorCode.E_POINTER); // Not the greatest error, but needed for backward compat. - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) { return Pal.Export(contentType, safePasswordHandle); } @@ -680,6 +683,88 @@ private static void VerifyContentType(X509ContentType contentType) throw new CryptographicException(SR.Cryptography_X509_InvalidContentType); } + internal static void EnforceIterationCountLimit(ReadOnlySpan pkcs12, bool readingFromFile, bool passwordProvided) + { + if (readingFromFile || passwordProvided) + { + return; + } + + long pkcs12UnspecifiedPasswordIterationLimit = LocalAppContextSwitches.Pkcs12UnspecifiedPasswordIterationLimit; + + // -1 = no limit + if (LocalAppContextSwitches.Pkcs12UnspecifiedPasswordIterationLimit == -1) + { + return; + } + + // any other negative number means use default limits + if (pkcs12UnspecifiedPasswordIterationLimit < 0) + { + pkcs12UnspecifiedPasswordIterationLimit = LocalAppContextSwitches.DefaultPkcs12UnspecifiedPasswordIterationLimit; + } + + try + { + try + { + checked + { + KdfWorkLimiter.SetIterationLimit((ulong)pkcs12UnspecifiedPasswordIterationLimit); + ulong observedIterationCount = GetIterationCount(pkcs12); + + // Check both conditions: we want a KDF-exceeded failure anywhere in the system to produce a failure here. + // There are some places within the GetIterationCount method where we optimistically try processing the + // PFX in one manner, and if we see failures we'll swallow any exceptions and try a different manner + // instead. The problem with this is that when we swallow failures, we don't have the ability to add the + // so-far-observed iteration count back to the running total returned by GetIterationCount. This + // potentially allows a clever adversary a window through which to squeeze in work beyond our configured + // limits. To mitigate this risk, we'll fail now if we observed *any* KDF-exceeded failure while processing + // this PFX. + if (observedIterationCount > (ulong)pkcs12UnspecifiedPasswordIterationLimit || KdfWorkLimiter.WasWorkLimitExceeded()) + { + throw new CryptographicException(); // iteration count exceeded + } + } + } + finally + { + KdfWorkLimiter.ResetIterationLimit(); + } + } + catch (Exception ex) + { + // It's important for this catch-all block to be *outside* the inner try/finally + // so that we can prevent exception filters from running before we've had a chance + // to clean up the threadstatic. + throw new CryptographicException(SR.Cryptography_X509_PfxWithoutPassword, ex); + } + } + + internal static ulong GetIterationCount(ReadOnlySpan pkcs12) + { + ulong iterations; + + unsafe + { + fixed (byte* pin = pkcs12) + { + using (var manager = new PointerMemoryManager(pin, pkcs12.Length)) + { + AsnValueReader reader = new AsnValueReader(pkcs12, AsnEncodingRules.BER); + PfxAsn.Decode(ref reader, manager.Memory, out PfxAsn pfx); + + // Don't throw when trailing data is present. + // Windows doesn't have such enforcement as well. + + iterations = pfx.CountTotalIterations(); + } + } + } + + return iterations; + } + internal const X509KeyStorageFlags KeyStorageFlagsAll = X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.MachineKeySet | diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs index bf62d21ac5ae98..4908ce8b94ddbb 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509Certificate2Collection.cs @@ -106,12 +106,16 @@ public bool Contains(X509Certificate2 certificate) public byte[]? Export(X509ContentType contentType) { - return Export(contentType, password: null); + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) + using (IExportPal storePal = StorePal.LinkFromCertificateCollection(this)) + { + return storePal.Export(contentType, safePasswordHandle); + } } public byte[]? Export(X509ContentType contentType, string? password) { - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (IExportPal storePal = StorePal.LinkFromCertificateCollection(this)) { return storePal.Export(contentType, safePasswordHandle); @@ -147,7 +151,11 @@ public void Import(byte[] rawData) /// public void Import(ReadOnlySpan rawData) { - Import(rawData, password: null, keyStorageFlags: X509KeyStorageFlags.DefaultKeySet); + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) + using (ILoaderPal storePal = StorePal.FromBlob(rawData, safePasswordHandle, X509KeyStorageFlags.DefaultKeySet)) + { + storePal.MoveTo(this); + } } public void Import(byte[] rawData, string? password, X509KeyStorageFlags keyStorageFlags = 0) @@ -190,7 +198,7 @@ public void Import(ReadOnlySpan rawData, ReadOnlySpan password, X509 { X509Certificate.ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (ILoaderPal storePal = StorePal.FromBlob(rawData, safePasswordHandle, keyStorageFlags)) { storePal.MoveTo(this); @@ -199,7 +207,14 @@ public void Import(ReadOnlySpan rawData, ReadOnlySpan password, X509 public void Import(string fileName) { - Import(fileName, password: null, keyStorageFlags: X509KeyStorageFlags.DefaultKeySet); + if (fileName == null) + throw new ArgumentNullException(nameof(fileName)); + + using (var safePasswordHandle = new SafePasswordHandle((string?)null, passwordProvided: false)) + using (ILoaderPal storePal = StorePal.FromFile(fileName, safePasswordHandle, X509KeyStorageFlags.DefaultKeySet)) + { + storePal.MoveTo(this); + } } public void Import(string fileName, string? password, X509KeyStorageFlags keyStorageFlags = 0) @@ -208,7 +223,7 @@ public void Import(string fileName, string? password, X509KeyStorageFlags keySto X509Certificate.ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (ILoaderPal storePal = StorePal.FromFile(fileName, safePasswordHandle, keyStorageFlags)) { storePal.MoveTo(this); @@ -233,7 +248,7 @@ public void Import(string fileName, ReadOnlySpan password, X509KeyStorageF X509Certificate.ValidateKeyStorageFlags(keyStorageFlags); - using (var safePasswordHandle = new SafePasswordHandle(password)) + using (var safePasswordHandle = new SafePasswordHandle(password, passwordProvided: true)) using (ILoaderPal storePal = StorePal.FromFile(fileName, safePasswordHandle, keyStorageFlags)) { storePal.MoveTo(this); diff --git a/src/native/corehost/apphost/static/CMakeLists.txt b/src/native/corehost/apphost/static/CMakeLists.txt index a632d993c0f2a1..57681e9c54bd30 100644 --- a/src/native/corehost/apphost/static/CMakeLists.txt +++ b/src/native/corehost/apphost/static/CMakeLists.txt @@ -55,7 +55,9 @@ endif() if(CLR_CMAKE_TARGET_WIN32) list(APPEND SOURCES - ../apphost.windows.cpp) + ../apphost.windows.cpp + ${CLR_SRC_NATIVE_DIR}/libs/Common/delayloadhook_windows.cpp + ) list(APPEND HEADERS ../apphost.windows.h) @@ -105,6 +107,9 @@ if(CLR_CMAKE_TARGET_WIN32) # Delay load libraries required for WinRT as that is not supported on all platforms add_linker_flag("/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll") + + # Delay load version.dll so that we can specify how to search when loading it as it is not part of Windows' known DLLs + add_linker_flag("/DELAYLOAD:version.dll") endif() if(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/dlls/mscoree/delayloadhook.cpp b/src/native/libs/Common/delayloadhook_windows.cpp similarity index 97% rename from src/coreclr/dlls/mscoree/delayloadhook.cpp rename to src/native/libs/Common/delayloadhook_windows.cpp index b09cd75215a200..901ac5661749c8 100644 --- a/src/coreclr/dlls/mscoree/delayloadhook.cpp +++ b/src/native/libs/Common/delayloadhook_windows.cpp @@ -4,8 +4,7 @@ // File: delayloadhook.cpp // -#include "stdafx.h" - +#include #include FARPROC WINAPI secureDelayHook(unsigned dliNotify, PDelayLoadInfo pdli)