You've already forked linux-packaging-mono
Imported Upstream version 5.10.0.69
Former-commit-id: fc39669a0b707dd3c063977486506b6793da2890
This commit is contained in:
parent
d8f8abd549
commit
e2950ec768
@@ -30,14 +30,14 @@ Global
|
||||
{2DD8DFFA-09FF-46C6-8313-4A9CC1849A44}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU
|
||||
{2DD8DFFA-09FF-46C6-8313-4A9CC1849A44}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU
|
||||
{2DD8DFFA-09FF-46C6-8313-4A9CC1849A44}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Debug|Any CPU.ActiveCfg = netstandard-Windows_NT-Debug|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Debug|Any CPU.Build.0 = netstandard-Windows_NT-Debug|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Release|Any CPU.ActiveCfg = netstandard-Windows_NT-Release|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Release|Any CPU.Build.0 = netstandard-Windows_NT-Release|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Release|Any CPU.Build.0 = netstandard-Release|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU
|
||||
{03D84CBD-896D-4B2F-9A22-07034F51E73D}.Release|Any CPU.Build.0 = netcoreapp-Windows_NT-Release|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
|
||||
{881269F5-9F22-4427-8DC5-63E2C05875BA}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ref\System.Security.Cryptography.Pkcs.csproj">
|
||||
<SupportedFramework>net461;netcoreapp2.0;$(AllXamarinFrameworks)</SupportedFramework>
|
||||
<SupportedFramework>net461;netcoreapp2.1;$(AllXamarinFrameworks)</SupportedFramework>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\src\System.Security.Cryptography.Pkcs.csproj" />
|
||||
<HarvestIncludePaths Include="ref/net46;lib/net46;runtimes/win/lib/net46" />
|
||||
<HarvestIncludePaths Include="runtimes/win/lib/netcore50" />
|
||||
<HarvestIncludePaths Include="ref/netstandard1.3;runtimes/win/lib/netstandard1.3;lib/netstandard1.3" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<PropertyGroup>
|
||||
<BuildConfigurations>
|
||||
netstandard;
|
||||
netcoreapp;
|
||||
netfx;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -80,6 +80,22 @@ namespace System.Security.Cryptography.Pkcs
|
||||
public bool MoveNext() { throw null; }
|
||||
public void Reset() { }
|
||||
}
|
||||
public sealed partial class CmsSigner
|
||||
{
|
||||
public CmsSigner() => throw null;
|
||||
public CmsSigner(SubjectIdentifierType signerIdentifierType) => throw null;
|
||||
public CmsSigner(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null;
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public CmsSigner(CspParameters parameters) => throw null;
|
||||
public CmsSigner(SubjectIdentifierType signerIdentifierType, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null;
|
||||
public SubjectIdentifierType SignerIdentifierType { get => throw null; set => throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get => throw null; set => throw null; }
|
||||
public Oid DigestAlgorithm { get => throw null; set => throw null; }
|
||||
public CryptographicAttributeObjectCollection SignedAttributes { get => throw null; set => throw null; }
|
||||
public CryptographicAttributeObjectCollection UnsignedAttributes { get => throw null; set => throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get => throw null; set => throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509IncludeOption IncludeOption { get => throw null; set => throw null; }
|
||||
}
|
||||
public sealed partial class ContentInfo
|
||||
{
|
||||
public ContentInfo(byte[] content) { }
|
||||
@@ -213,6 +229,70 @@ namespace System.Security.Cryptography.Pkcs
|
||||
KeyTransport = 1,
|
||||
Unknown = 0,
|
||||
}
|
||||
public sealed partial class SignedCms
|
||||
{
|
||||
public SignedCms() => throw null;
|
||||
public SignedCms(SubjectIdentifierType signerIdentifierType) => throw null;
|
||||
public SignedCms(ContentInfo contentInfo) => throw null;
|
||||
public SignedCms(SubjectIdentifierType signerIdentifierType, ContentInfo contentInfo) => throw null;
|
||||
public SignedCms(ContentInfo contentInfo, bool detached) => throw null;
|
||||
public SignedCms(SubjectIdentifierType signerIdentifierType, ContentInfo contentInfo, bool detached) => throw null;
|
||||
public int Version => throw null;
|
||||
public ContentInfo ContentInfo => throw null;
|
||||
public bool Detached => throw null;
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates => throw null;
|
||||
public SignerInfoCollection SignerInfos => throw null;
|
||||
public byte[] Encode() => throw null;
|
||||
public void Decode(byte[] encodedMessage) => throw null;
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void ComputeSignature() => throw null;
|
||||
public void ComputeSignature(CmsSigner signer) => throw null;
|
||||
public void ComputeSignature(CmsSigner signer, bool silent) => throw null;
|
||||
public void RemoveSignature(int index) => throw null;
|
||||
public void RemoveSignature(SignerInfo signerInfo) => throw null;
|
||||
public void CheckSignature(bool verifySignatureOnly) => throw null;
|
||||
public void CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2Collection extraStore, bool verifySignatureOnly) => throw null;
|
||||
public void CheckHash() => throw null;
|
||||
}
|
||||
public sealed partial class SignerInfo
|
||||
{
|
||||
private SignerInfo() => throw null;
|
||||
public int Version => throw null;
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate => throw null;
|
||||
public SubjectIdentifier SignerIdentifier => throw null;
|
||||
public Oid DigestAlgorithm => throw null;
|
||||
public CryptographicAttributeObjectCollection SignedAttributes => throw null;
|
||||
public CryptographicAttributeObjectCollection UnsignedAttributes => throw null;
|
||||
public SignerInfoCollection CounterSignerInfos => throw null;
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public void ComputeCounterSignature() => throw null;
|
||||
public void ComputeCounterSignature(CmsSigner signer) => throw null;
|
||||
public void RemoveCounterSignature(int index) => throw null;
|
||||
public void RemoveCounterSignature(SignerInfo counterSignerInfo) => throw null;
|
||||
public void CheckSignature(bool verifySignatureOnly) => throw null;
|
||||
public void CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2Collection extraStore, bool verifySignatureOnly) => throw null;
|
||||
public void CheckHash() => throw null;
|
||||
}
|
||||
public sealed partial class SignerInfoCollection : System.Collections.ICollection, System.Collections.IEnumerable
|
||||
{
|
||||
internal SignerInfoCollection() => throw null;
|
||||
public SignerInfo this[int index] => throw null;
|
||||
public int Count => throw null;
|
||||
public SignerInfoEnumerator GetEnumerator() => throw null;
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;
|
||||
public void CopyTo(Array array, int index) => throw null;
|
||||
public void CopyTo(SignerInfo[] array, int index) => throw null;
|
||||
public bool IsSynchronized => throw null;
|
||||
public object SyncRoot => throw null;
|
||||
}
|
||||
public sealed partial class SignerInfoEnumerator : System.Collections.IEnumerator
|
||||
{
|
||||
private SignerInfoEnumerator() { }
|
||||
public SignerInfo Current => throw null;
|
||||
object System.Collections.IEnumerator.Current => throw null;
|
||||
public bool MoveNext() => throw null;
|
||||
public void Reset() => throw null;
|
||||
}
|
||||
public sealed partial class SubjectIdentifier
|
||||
{
|
||||
internal SubjectIdentifier() { }
|
||||
@@ -242,9 +322,9 @@ namespace System.Security.Cryptography.Pkcs
|
||||
}
|
||||
namespace System.Security.Cryptography.Xml
|
||||
{
|
||||
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
|
||||
public partial struct X509IssuerSerial
|
||||
{
|
||||
private object _dummy;
|
||||
public string IssuerName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public string SerialNumber { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
|
||||
@@ -5,17 +5,26 @@
|
||||
<ProjectGuid>{881269F5-9F22-4427-8DC5-63E2C05875BA}</ProjectGuid>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
|
||||
<ItemGroup>
|
||||
<Compile Include="System.Security.Cryptography.Pkcs.cs" />
|
||||
<Compile Include="System.Security.Cryptography.Pkcs.netcoreapp.cs" Condition="'$(TargetGroup)' == 'netcoreapp'" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Security" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
|
||||
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
|
||||
<ProjectReference Include="..\..\System.Security.Cryptography.Csp\ref\System.Security.Cryptography.Csp.csproj" />
|
||||
<ProjectReference Include="..\..\System.Security.Cryptography.Encoding\ref\System.Security.Cryptography.Encoding.csproj" />
|
||||
<ProjectReference Include="..\..\System.Security.Cryptography.X509Certificates\ref\System.Security.Cryptography.X509Certificates.csproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
// ------------------------------------------------------------------------------
|
||||
// Changes to this file must follow the http://aka.ms/api-review process.
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Security.Cryptography.Pkcs
|
||||
{
|
||||
public sealed partial class SignerInfo
|
||||
{
|
||||
public Oid SignatureAlgorithm => throw null;
|
||||
public byte[] GetSignature() => throw null;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<BuildConfigurations>
|
||||
netstandard-Windows_NT;
|
||||
netstandard;
|
||||
netstandard-Windows_NT;
|
||||
netcoreapp-Windows_NT;
|
||||
netcoreapp;
|
||||
netfx-Windows_NT;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.Asn1;
|
||||
using System.Security.Cryptography.Pkcs;
|
||||
using System.Security.Cryptography.Pkcs.Asn1;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using X509IssuerSerial = System.Security.Cryptography.Xml.X509IssuerSerial;
|
||||
|
||||
@@ -19,6 +23,39 @@ namespace Internal.Cryptography
|
||||
return (byte[])(a.Clone());
|
||||
}
|
||||
|
||||
#if !netcoreapp
|
||||
// Compatibility API.
|
||||
internal static void AppendData(this IncrementalHash hasher, ReadOnlySpan<byte> data)
|
||||
{
|
||||
hasher.AppendData(data.ToArray());
|
||||
}
|
||||
#endif
|
||||
|
||||
internal static HashAlgorithmName GetDigestAlgorithm(Oid oid)
|
||||
{
|
||||
Debug.Assert(oid != null);
|
||||
return GetDigestAlgorithm(oid.Value);
|
||||
}
|
||||
|
||||
internal static HashAlgorithmName GetDigestAlgorithm(string oidValue)
|
||||
{
|
||||
switch (oidValue)
|
||||
{
|
||||
case Oids.Md5:
|
||||
return HashAlgorithmName.MD5;
|
||||
case Oids.Sha1:
|
||||
return HashAlgorithmName.SHA1;
|
||||
case Oids.Sha256:
|
||||
return HashAlgorithmName.SHA256;
|
||||
case Oids.Sha384:
|
||||
return HashAlgorithmName.SHA384;
|
||||
case Oids.Sha512:
|
||||
return HashAlgorithmName.SHA512;
|
||||
default:
|
||||
throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, oidValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is not just a convenience wrapper for Array.Resize(). In DEBUG builds, it forces the array to move in memory even if no resize is needed. This should be used by
|
||||
/// helper methods that do anything of the form "call a native api once to get the estimated size, call it again to get the data and return the data in a byte[] array."
|
||||
@@ -34,6 +71,54 @@ namespace Internal.Cryptography
|
||||
return a;
|
||||
}
|
||||
|
||||
public static void RemoveAt<T>(ref T[] arr, int idx)
|
||||
{
|
||||
Debug.Assert(arr != null);
|
||||
Debug.Assert(idx >= 0);
|
||||
Debug.Assert(idx < arr.Length);
|
||||
|
||||
if (arr.Length == 1)
|
||||
{
|
||||
arr = Array.Empty<T>();
|
||||
return;
|
||||
}
|
||||
|
||||
T[] tmp = new T[arr.Length - 1];
|
||||
|
||||
if (idx != 0)
|
||||
{
|
||||
Array.Copy(arr, 0, tmp, 0, idx);
|
||||
}
|
||||
|
||||
if (idx < tmp.Length)
|
||||
{
|
||||
Array.Copy(arr, idx + 1, tmp, idx, tmp.Length - idx);
|
||||
}
|
||||
|
||||
arr = tmp;
|
||||
}
|
||||
|
||||
public static T[] NormalizeSet<T>(
|
||||
T[] setItems,
|
||||
Action<byte[]> encodedValueProcessor=null)
|
||||
{
|
||||
AsnSet<T> set = new AsnSet<T>
|
||||
{
|
||||
SetData = setItems,
|
||||
};
|
||||
|
||||
AsnWriter writer = AsnSerializer.Serialize(set, AsnEncodingRules.DER);
|
||||
byte[] normalizedValue = writer.Encode();
|
||||
set = AsnSerializer.Deserialize<AsnSet<T>>(normalizedValue, AsnEncodingRules.DER);
|
||||
|
||||
if (encodedValueProcessor != null)
|
||||
{
|
||||
encodedValueProcessor(normalizedValue);
|
||||
}
|
||||
|
||||
return set.SetData;
|
||||
}
|
||||
|
||||
public static CmsRecipientCollection DeepCopy(this CmsRecipientCollection recipients)
|
||||
{
|
||||
CmsRecipientCollection recipientsCopy = new CmsRecipientCollection();
|
||||
@@ -149,9 +234,14 @@ namespace Internal.Cryptography
|
||||
return skiString.UpperHexStringToByteArray();
|
||||
}
|
||||
|
||||
public static string ToSkiString(this ReadOnlySpan<byte> skiBytes)
|
||||
{
|
||||
return ToUpperHexString(skiBytes);
|
||||
}
|
||||
|
||||
public static string ToSkiString(this byte[] skiBytes)
|
||||
{
|
||||
return skiBytes.ToUpperHexString();
|
||||
return ToUpperHexString(skiBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -170,16 +260,18 @@ namespace Internal.Cryptography
|
||||
{
|
||||
serialBytes = serialBytes.CloneByteArray();
|
||||
Array.Reverse(serialBytes);
|
||||
return serialBytes.ToUpperHexString();
|
||||
return ToUpperHexString(serialBytes);
|
||||
}
|
||||
|
||||
private static string ToUpperHexString(this byte[] ba)
|
||||
private static string ToUpperHexString(ReadOnlySpan<byte> ba)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(ba.Length * 2);
|
||||
foreach (byte b in ba)
|
||||
|
||||
for (int i = 0; i < ba.Length; i++)
|
||||
{
|
||||
sb.Append(b.ToString("X2"));
|
||||
sb.Append(ba[i].ToString("X2"));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
@@ -256,5 +348,122 @@ namespace Internal.Cryptography
|
||||
enhancedAttribute.CopyFrom(basicAttribute);
|
||||
return enhancedAttribute;
|
||||
}
|
||||
|
||||
public static byte[] GetSubjectKeyIdentifier(this X509Certificate2 certificate)
|
||||
{
|
||||
Debug.Assert(certificate != null);
|
||||
|
||||
X509Extension extension = certificate.Extensions[Oids.SubjectKeyIdentifier];
|
||||
|
||||
if (extension != null)
|
||||
{
|
||||
// Certificates are DER encoded.
|
||||
AsnReader reader = new AsnReader(extension.RawData, AsnEncodingRules.DER);
|
||||
|
||||
if (reader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> contents))
|
||||
{
|
||||
return contents.ToArray();
|
||||
}
|
||||
|
||||
// TryGetPrimitiveOctetStringBytes will have thrown if the next tag wasn't
|
||||
// Universal (primitive) OCTET STRING, since we're in DER mode.
|
||||
// So there's really no way we can get here.
|
||||
Debug.Fail($"TryGetPrimitiveOctetStringBytes returned false in DER mode");
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
// The Desktop/Windows version of this method use CertGetCertificateContextProperty
|
||||
// with a property ID of CERT_KEY_IDENTIFIER_PROP_ID.
|
||||
//
|
||||
// MSDN says that when there's no extension, this method takes the SHA-1 of the
|
||||
// SubjectPublicKeyInfo block, and returns that.
|
||||
//
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa376079%28v=vs.85%29.aspx
|
||||
|
||||
#pragma warning disable CA5350 // SHA-1 is required for compat.
|
||||
using (HashAlgorithm hash = SHA1.Create())
|
||||
#pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1.
|
||||
{
|
||||
ReadOnlyMemory<byte> publicKeyInfoBytes = GetSubjectPublicKeyInfo(certificate);
|
||||
return hash.ComputeHash(publicKeyInfoBytes.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DigestWriter(IncrementalHash hasher, AsnWriter writer)
|
||||
{
|
||||
#if netcoreapp
|
||||
hasher.AppendData(writer.EncodeAsSpan());
|
||||
#else
|
||||
hasher.AppendData(writer.Encode());
|
||||
#endif
|
||||
}
|
||||
|
||||
private static ReadOnlyMemory<byte> GetSubjectPublicKeyInfo(X509Certificate2 certificate)
|
||||
{
|
||||
var parsedCertificate = AsnSerializer.Deserialize<Certificate>(certificate.RawData, AsnEncodingRules.DER);
|
||||
return parsedCertificate.TbsCertificate.SubjectPublicKeyInfo;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct Certificate
|
||||
{
|
||||
internal TbsCertificateLite TbsCertificate;
|
||||
internal AlgorithmIdentifierAsn AlgorithmIdentifier;
|
||||
[BitString]
|
||||
internal ReadOnlyMemory<byte> SignatureValue;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct TbsCertificateLite
|
||||
{
|
||||
[ExpectedTag(0, ExplicitTag = true)]
|
||||
#pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant
|
||||
[DefaultValue(0xA0, 0x03, 0x02, 0x01, 0x00)]
|
||||
#pragma warning restore CS3016 // Arrays as attribute arguments is not CLS-compliant
|
||||
internal int Version;
|
||||
|
||||
[Integer]
|
||||
internal ReadOnlyMemory<byte> SerialNumber;
|
||||
|
||||
internal AlgorithmIdentifierAsn AlgorithmIdentifier;
|
||||
|
||||
[AnyValue]
|
||||
[ExpectedTag(TagClass.Universal, (int)UniversalTagNumber.SequenceOf)]
|
||||
internal ReadOnlyMemory<byte> Issuer;
|
||||
|
||||
[AnyValue]
|
||||
[ExpectedTag(TagClass.Universal, (int)UniversalTagNumber.Sequence)]
|
||||
internal ReadOnlyMemory<byte> Validity;
|
||||
|
||||
[AnyValue]
|
||||
[ExpectedTag(TagClass.Universal, (int)UniversalTagNumber.SequenceOf)]
|
||||
internal ReadOnlyMemory<byte> Subject;
|
||||
|
||||
[AnyValue]
|
||||
[ExpectedTag(TagClass.Universal, (int)UniversalTagNumber.Sequence)]
|
||||
internal ReadOnlyMemory<byte> SubjectPublicKeyInfo;
|
||||
|
||||
[ExpectedTag(1)]
|
||||
[OptionalValue]
|
||||
[BitString]
|
||||
internal ReadOnlyMemory<byte>? IssuerUniqueId;
|
||||
|
||||
[ExpectedTag(2)]
|
||||
[OptionalValue]
|
||||
[BitString]
|
||||
internal ReadOnlyMemory<byte>? SubjectUniqueId;
|
||||
|
||||
[OptionalValue]
|
||||
[AnyValue]
|
||||
[ExpectedTag(3)]
|
||||
internal ReadOnlyMemory<byte>? Extensions;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AsnSet<T>
|
||||
{
|
||||
[SetOf]
|
||||
public T[] SetData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Internal.Cryptography
|
||||
|
||||
// Asymmetric encryption algorithms
|
||||
public const string Rsa = "1.2.840.113549.1.1.1";
|
||||
public const string RsaPss = "1.2.840.113549.1.1.10";
|
||||
public const string Esdh = "1.2.840.113549.1.9.16.3.5";
|
||||
|
||||
// Cryptographic Attribute Types
|
||||
@@ -22,6 +23,7 @@ namespace Internal.Cryptography
|
||||
public const string ContentType = "1.2.840.113549.1.9.3";
|
||||
public const string DocumentDescription = "1.3.6.1.4.1.311.88.2.2";
|
||||
public const string MessageDigest = "1.2.840.113549.1.9.4";
|
||||
public const string CounterSigner = "1.2.840.113549.1.9.6";
|
||||
public const string DocumentName = "1.3.6.1.4.1.311.88.2.1";
|
||||
|
||||
// Key wrap algorithms
|
||||
@@ -35,5 +37,32 @@ namespace Internal.Cryptography
|
||||
public const string Pkcs7SignedEnveloped = "1.2.840.113549.1.7.4";
|
||||
public const string Pkcs7Hashed = "1.2.840.113549.1.7.5";
|
||||
public const string Pkcs7Encrypted = "1.2.840.113549.1.7.6";
|
||||
|
||||
public const string Md5 = "1.2.840.113549.2.5";
|
||||
public const string Sha1 = "1.3.14.3.2.26";
|
||||
public const string Sha256 = "2.16.840.1.101.3.4.2.1";
|
||||
public const string Sha384 = "2.16.840.1.101.3.4.2.2";
|
||||
public const string Sha512 = "2.16.840.1.101.3.4.2.3";
|
||||
|
||||
// DSA CMS uses the combined signature+digest OID
|
||||
public const string DsaPublicKey = "1.2.840.10040.4.1";
|
||||
public const string DsaWithSha1 = "1.2.840.10040.4.3";
|
||||
public const string DsaWithSha256 = "2.16.840.1.101.3.4.3.2";
|
||||
public const string DsaWithSha384 = "2.16.840.1.101.3.4.3.3";
|
||||
public const string DsaWithSha512 = "2.16.840.1.101.3.4.3.4";
|
||||
|
||||
// ECDSA CMS uses the combined signature+digest OID
|
||||
// https://tools.ietf.org/html/rfc5753#section-2.1.1
|
||||
public const string EcPublicKey = "1.2.840.10045.2.1";
|
||||
public const string ECDsaWithSha1 = "1.2.840.10045.4.1";
|
||||
public const string ECDsaWithSha256 = "1.2.840.10045.4.3.2";
|
||||
public const string ECDsaWithSha384 = "1.2.840.10045.4.3.3";
|
||||
public const string ECDsaWithSha512 = "1.2.840.10045.4.3.4";
|
||||
|
||||
public const string Mgf1 = "1.2.840.113549.1.1.8";
|
||||
|
||||
// Cert Extensions
|
||||
public const string SubjectKeyIdentifier = "2.5.29.14";
|
||||
public const string KeyUsage = "2.5.29.15";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.Asn1;
|
||||
using System.Security.Cryptography.Pkcs;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal abstract partial class PkcsPal
|
||||
{
|
||||
private static PkcsPal s_instance = new ManagedPkcsPal();
|
||||
|
||||
private class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
public override byte[] Encrypt(
|
||||
CmsRecipientCollection recipients,
|
||||
ContentInfo contentInfo,
|
||||
AlgorithmIdentifier contentEncryptionAlgorithm,
|
||||
X509Certificate2Collection originatorCerts,
|
||||
CryptographicAttributeObjectCollection unprotectedAttributes)
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override DecryptorPal Decode(
|
||||
byte[] encodedMessage,
|
||||
out int version,
|
||||
out ContentInfo contentInfo,
|
||||
out AlgorithmIdentifier contentEncryptionAlgorithm,
|
||||
out X509Certificate2Collection originatorCerts,
|
||||
out CryptographicAttributeObjectCollection unprotectedAttributes)
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override byte[] EncodeOctetString(byte[] octets)
|
||||
{
|
||||
// Write using DER to support the most readers.
|
||||
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
|
||||
{
|
||||
writer.WriteOctetString(octets);
|
||||
return writer.Encode();
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] DecodeOctetString(byte[] encodedOctets)
|
||||
{
|
||||
// Read using BER because the CMS specification says the encoding is BER.
|
||||
AsnReader reader = new AsnReader(encodedOctets, AsnEncodingRules.BER);
|
||||
|
||||
const int ArbitraryStackLimit = 256;
|
||||
Span<byte> tmp = stackalloc byte[ArbitraryStackLimit];
|
||||
// Use stackalloc 0 so data can later hold a slice of tmp.
|
||||
ReadOnlySpan<byte> data = stackalloc byte[0];
|
||||
byte[] poolBytes = null;
|
||||
|
||||
try
|
||||
{
|
||||
if (!reader.TryGetPrimitiveOctetStringBytes(out var contents))
|
||||
{
|
||||
if (reader.TryCopyOctetStringBytes(tmp, out int bytesWritten))
|
||||
{
|
||||
data = tmp.Slice(0, bytesWritten);
|
||||
}
|
||||
else
|
||||
{
|
||||
poolBytes = ArrayPool<byte>.Shared.Rent(reader.PeekContentBytes().Length);
|
||||
|
||||
if (!reader.TryCopyOctetStringBytes(poolBytes, out bytesWritten))
|
||||
{
|
||||
Debug.Fail("TryCopyOctetStringBytes failed with a provably-large-enough buffer");
|
||||
throw new CryptographicException();
|
||||
}
|
||||
|
||||
data = new ReadOnlySpan<byte>(poolBytes, 0, bytesWritten);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
data = contents.Span;
|
||||
}
|
||||
|
||||
if (reader.HasData)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
return data.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (poolBytes != null)
|
||||
{
|
||||
Array.Clear(poolBytes, 0, data.Length);
|
||||
ArrayPool<byte>.Shared.Return(poolBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] EncodeUtcTime(DateTime utcTime)
|
||||
{
|
||||
// Write using DER to support the most readers.
|
||||
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
|
||||
{
|
||||
// Sending the DateTime through ToLocalTime here will cause the right normalization
|
||||
// of DateTimeKind.Unknown.
|
||||
//
|
||||
// Local => Local (noop) => UTC (in WriteUtcTime) (adjust, correct)
|
||||
// UTC => Local (adjust) => UTC (adjust back, correct)
|
||||
// Unknown => Local (adjust) => UTC (adjust "back", add Z marker; matches Windows)
|
||||
writer.WriteUtcTime(utcTime.ToLocalTime());
|
||||
return writer.Encode();
|
||||
}
|
||||
}
|
||||
|
||||
public override DateTime DecodeUtcTime(byte[] encodedUtcTime)
|
||||
{
|
||||
// Read using BER because the CMS specification says the encoding is BER.
|
||||
AsnReader reader = new AsnReader(encodedUtcTime, AsnEncodingRules.BER);
|
||||
DateTimeOffset value = reader.GetUtcTime();
|
||||
|
||||
if (reader.HasData)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
return value.UtcDateTime;
|
||||
}
|
||||
|
||||
public override string DecodeOid(byte[] encodedOid)
|
||||
{
|
||||
Span<byte> emptyInvalidOid = stackalloc byte[2];
|
||||
emptyInvalidOid[0] = 0x06;
|
||||
emptyInvalidOid[1] = 0x00;
|
||||
|
||||
// Windows compat.
|
||||
if (emptyInvalidOid.SequenceEqual(encodedOid))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
// Read using BER because the CMS specification says the encoding is BER.
|
||||
AsnReader reader = new AsnReader(encodedOid, AsnEncodingRules.BER);
|
||||
string value = reader.ReadObjectIdentifierAsString();
|
||||
|
||||
if (reader.HasData)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public override Oid GetEncodedMessageType(byte[] encodedMessage)
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override void AddCertsFromStoreForDecryption(X509Certificate2Collection certs)
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override Exception CreateRecipientsNotFoundException()
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override Exception CreateRecipientInfosAfterEncryptException()
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override Exception CreateDecryptAfterEncryptException()
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override Exception CreateDecryptTwiceException()
|
||||
{
|
||||
throw new PlatformNotSupportedException(SR.PlatformNotSupported_CryptographyPkcs);
|
||||
}
|
||||
|
||||
public override byte[] GetSubjectKeyIdentifier(X509Certificate2 certificate)
|
||||
{
|
||||
return certificate.GetSubjectKeyIdentifier();
|
||||
}
|
||||
|
||||
public override T GetPrivateKeyForSigning<T>(X509Certificate2 certificate, bool silent)
|
||||
{
|
||||
return GetPrivateKey<T>(certificate);
|
||||
}
|
||||
|
||||
public override T GetPrivateKeyForDecryption<T>(X509Certificate2 certificate, bool silent)
|
||||
{
|
||||
return GetPrivateKey<T>(certificate);
|
||||
}
|
||||
|
||||
private T GetPrivateKey<T>(X509Certificate2 certificate) where T : AsymmetricAlgorithm
|
||||
{
|
||||
if (typeof(T) == typeof(RSA))
|
||||
return (T)(object)certificate.GetRSAPrivateKey();
|
||||
if (typeof(T) == typeof(ECDsa))
|
||||
return (T)(object)certificate.GetECDsaPrivateKey();
|
||||
#if netcoreapp
|
||||
if (typeof(T) == typeof(DSA))
|
||||
return (T)(object)certificate.GetDSAPrivateKey();
|
||||
#endif
|
||||
|
||||
Debug.Fail($"Unknown key type requested: {typeof(T).FullName}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal abstract partial class PkcsPal
|
||||
{
|
||||
private static PkcsPal s_instance;
|
||||
|
||||
static PkcsPal()
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,12 @@ namespace Internal.Cryptography.Pal.Windows
|
||||
return null;
|
||||
|
||||
// Desktop compat: We pass false for "silent" here (thus allowing crypto providers to display UI.)
|
||||
using (SafeProvOrNCryptKeyHandle hKey = TryGetCertificatePrivateKey(cert, false, out exception))
|
||||
const bool Silent = false;
|
||||
// Note: Using CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG rather than CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG
|
||||
// because wrapping an NCrypt wrapper over CAPI keys unconditionally causes some legacy features
|
||||
// (such as RC4 support) to break.
|
||||
const bool PreferNCrypt = false;
|
||||
using (SafeProvOrNCryptKeyHandle hKey = PkcsPalWindows.GetCertificatePrivateKey(cert, Silent, PreferNCrypt, out _, out exception))
|
||||
{
|
||||
if (hKey == null)
|
||||
return null;
|
||||
@@ -104,69 +109,6 @@ namespace Internal.Cryptography.Pal.Windows
|
||||
}
|
||||
}
|
||||
|
||||
private static SafeProvOrNCryptKeyHandle TryGetCertificatePrivateKey(X509Certificate2 cert, bool silent, out Exception exception)
|
||||
{
|
||||
CryptAcquireCertificatePrivateKeyFlags flags =
|
||||
CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_USE_PROV_INFO_FLAG
|
||||
| CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_COMPARE_KEY_FLAG
|
||||
// Note: Using CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG rather than CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG because wrapping an NCrypt wrapper over CAPI keys unconditionally
|
||||
// causes some legacy features (such as RC4 support) to break.
|
||||
| CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG;
|
||||
if (silent)
|
||||
{
|
||||
flags |= CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_SILENT_FLAG;
|
||||
}
|
||||
|
||||
bool mustFree;
|
||||
using (SafeCertContextHandle hCertContext = cert.CreateCertContextHandle())
|
||||
{
|
||||
IntPtr hKey;
|
||||
int cbSize = IntPtr.Size;
|
||||
|
||||
if (Interop.Crypt32.CertGetCertificateContextProperty(
|
||||
hCertContext,
|
||||
CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
|
||||
out hKey,
|
||||
ref cbSize))
|
||||
{
|
||||
exception = null;
|
||||
return new SafeProvOrNCryptKeyHandleUwp(hKey, hCertContext);
|
||||
}
|
||||
|
||||
CryptKeySpec keySpec;
|
||||
|
||||
if (!Interop.Crypt32.CryptAcquireCertificatePrivateKey(hCertContext, flags, IntPtr.Zero, out hKey, out keySpec, out mustFree))
|
||||
{
|
||||
exception = Marshal.GetHRForLastWin32Error().ToCryptographicException();
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need to know whether we got back a CRYPTPROV or NCrypt handle. Unfortunately, NCryptIsKeyHandle() is a prohibited api on UWP.
|
||||
// Fortunately, CryptAcquireCertificatePrivateKey() is documented to tell us which one we got through the keySpec value.
|
||||
bool isNCrypt;
|
||||
switch (keySpec)
|
||||
{
|
||||
case CryptKeySpec.AT_KEYEXCHANGE:
|
||||
case CryptKeySpec.AT_SIGNATURE:
|
||||
isNCrypt = false;
|
||||
break;
|
||||
|
||||
case CryptKeySpec.CERT_NCRYPT_KEY_SPEC:
|
||||
isNCrypt = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// As of this writing, we've exhausted all the known values of keySpec. We have no idea what kind of key handle we got so
|
||||
// play it safe and fail fast.
|
||||
throw new NotSupportedException(SR.Format(SR.Cryptography_Cms_UnknownKeySpec, keySpec));
|
||||
}
|
||||
|
||||
SafeProvOrNCryptKeyHandleUwp hProvOrNCryptKey = new SafeProvOrNCryptKeyHandleUwp(hKey, ownsHandle: mustFree, isNcrypt: isNCrypt);
|
||||
exception = null;
|
||||
return hProvOrNCryptKey;
|
||||
}
|
||||
}
|
||||
|
||||
private Exception TryDecryptTrans(KeyTransRecipientInfo recipientInfo, SafeProvOrNCryptKeyHandle hKey, CryptKeySpec keySpec)
|
||||
{
|
||||
KeyTransRecipientInfoPalWindows pal = (KeyTransRecipientInfoPalWindows)(recipientInfo.Pal);
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -13,6 +15,7 @@ using X509IssuerSerial = System.Security.Cryptography.Xml.X509IssuerSerial;
|
||||
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
using CryptProvParam=Interop.Advapi32.CryptProvParam;
|
||||
using static Interop.Crypt32;
|
||||
|
||||
namespace Internal.Cryptography.Pal.Windows
|
||||
@@ -326,6 +329,124 @@ namespace Internal.Cryptography.Pal.Windows
|
||||
}
|
||||
}
|
||||
|
||||
public static CspParameters GetProvParameters(this SafeProvOrNCryptKeyHandle handle)
|
||||
{
|
||||
// A normal key container name is a GUID (~34 bytes ASCII)
|
||||
// The longest standard provider name is 64 bytes (including the \0),
|
||||
// but we shouldn't have a CAPI call with a software CSP.
|
||||
//
|
||||
// In debug builds use a buffer which will need to be resized, but is big
|
||||
// enough to hold the DWORD "can't fail" values.
|
||||
Span<byte> stackSpan = stackalloc byte[
|
||||
#if DEBUG
|
||||
sizeof(int)
|
||||
#else
|
||||
64
|
||||
#endif
|
||||
];
|
||||
|
||||
stackSpan.Clear();
|
||||
int size = stackSpan.Length;
|
||||
|
||||
if (!Interop.Advapi32.CryptGetProvParam(handle, CryptProvParam.PP_PROVTYPE, stackSpan, ref size))
|
||||
{
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
|
||||
if (size != sizeof(int))
|
||||
{
|
||||
Debug.Fail("PP_PROVTYPE writes a DWORD - enum misalignment?");
|
||||
throw new CryptographicException();
|
||||
}
|
||||
|
||||
int provType = BinaryPrimitives.ReadMachineEndian<int>(stackSpan.Slice(0, size));
|
||||
|
||||
size = stackSpan.Length;
|
||||
if (!Interop.Advapi32.CryptGetProvParam(handle, CryptProvParam.PP_KEYSET_TYPE, stackSpan, ref size))
|
||||
{
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
|
||||
if (size != sizeof(int))
|
||||
{
|
||||
Debug.Fail("PP_KEYSET_TYPE writes a DWORD - enum misalignment?");
|
||||
throw new CryptographicException();
|
||||
}
|
||||
|
||||
int keysetType = BinaryPrimitives.ReadMachineEndian<int>(stackSpan.Slice(0, size));
|
||||
|
||||
// Only CRYPT_MACHINE_KEYSET is described as coming back, but be defensive.
|
||||
CspProviderFlags provFlags =
|
||||
((CspProviderFlags)keysetType & CspProviderFlags.UseMachineKeyStore) |
|
||||
CspProviderFlags.UseExistingKey;
|
||||
|
||||
byte[] rented = null;
|
||||
Span<byte> asciiStringBuf = stackSpan;
|
||||
|
||||
string provName = GetStringProvParam(handle, CryptProvParam.PP_NAME, ref asciiStringBuf, ref rented, 0);
|
||||
int maxClear = provName.Length;
|
||||
string keyName = GetStringProvParam(handle, CryptProvParam.PP_CONTAINER, ref asciiStringBuf, ref rented, maxClear);
|
||||
maxClear = Math.Max(maxClear, keyName.Length);
|
||||
|
||||
if (rented != null)
|
||||
{
|
||||
Array.Clear(rented, 0, maxClear);
|
||||
ArrayPool<byte>.Shared.Return(rented);
|
||||
}
|
||||
|
||||
return new CspParameters(provType)
|
||||
{
|
||||
Flags = provFlags,
|
||||
KeyContainerName = keyName,
|
||||
ProviderName = provName,
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetStringProvParam(
|
||||
SafeProvOrNCryptKeyHandle handle,
|
||||
CryptProvParam dwParam,
|
||||
ref Span<byte> buf,
|
||||
ref byte[] rented,
|
||||
int clearLen)
|
||||
{
|
||||
int len = buf.Length;
|
||||
|
||||
if (!Interop.Advapi32.CryptGetProvParam(handle, dwParam, buf, ref len))
|
||||
{
|
||||
if (len > buf.Length)
|
||||
{
|
||||
ArrayPool<byte> pool = ArrayPool<byte>.Shared;
|
||||
|
||||
if (rented != null)
|
||||
{
|
||||
Array.Clear(rented, 0, clearLen);
|
||||
pool.Return(rented);
|
||||
}
|
||||
|
||||
rented = pool.Rent(len);
|
||||
buf = rented;
|
||||
len = rented.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
|
||||
if (!Interop.Advapi32.CryptGetProvParam(handle, dwParam, buf, ref len))
|
||||
{
|
||||
throw Marshal.GetLastWin32Error().ToCryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* asciiPtr = &MemoryMarshal.GetReference(buf))
|
||||
{
|
||||
return Marshal.PtrToStringAnsi((IntPtr)asciiPtr, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe CryptographicAttributeObjectCollection ToCryptographicAttributeObjectCollection(CRYPT_ATTRIBUTES* pCryptAttributes)
|
||||
{
|
||||
CryptographicAttributeObjectCollection collection = new CryptographicAttributeObjectCollection();
|
||||
|
||||
@@ -6,6 +6,7 @@ using System;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.Pkcs;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
@@ -165,5 +166,169 @@ namespace Internal.Cryptography.Pal.Windows
|
||||
return ski;
|
||||
}
|
||||
}
|
||||
|
||||
public override T GetPrivateKeyForSigning<T>(X509Certificate2 certificate, bool silent)
|
||||
{
|
||||
return GetPrivateKey<T>(certificate, silent, preferNCrypt: true);
|
||||
}
|
||||
|
||||
public override T GetPrivateKeyForDecryption<T>(X509Certificate2 certificate, bool silent)
|
||||
{
|
||||
return GetPrivateKey<T>(certificate, silent, preferNCrypt: false);
|
||||
}
|
||||
|
||||
private T GetPrivateKey<T>(X509Certificate2 certificate, bool silent, bool preferNCrypt) where T : AsymmetricAlgorithm
|
||||
{
|
||||
if (!certificate.HasPrivateKey)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
SafeProvOrNCryptKeyHandle handle = GetCertificatePrivateKey(
|
||||
certificate,
|
||||
silent,
|
||||
preferNCrypt,
|
||||
out CryptKeySpec keySpec,
|
||||
out Exception exception);
|
||||
|
||||
using (handle)
|
||||
{
|
||||
if (handle == null || handle.IsInvalid)
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (keySpec == CryptKeySpec.CERT_NCRYPT_KEY_SPEC)
|
||||
{
|
||||
using (SafeNCryptKeyHandle keyHandle = new SafeNCryptKeyHandle(handle.DangerousGetHandle(), handle))
|
||||
using (CngKey cngKey = CngKey.Open(keyHandle, CngKeyHandleOpenOptions.None))
|
||||
{
|
||||
if (typeof(T) == typeof(RSA))
|
||||
return (T)(object)new RSACng(cngKey);
|
||||
if (typeof(T) == typeof(ECDsa))
|
||||
return (T)(object)new ECDsaCng(cngKey);
|
||||
if (typeof(T) == typeof(DSA))
|
||||
return (T)(object)new DSACng(cngKey);
|
||||
|
||||
Debug.Fail($"Unknown CNG key type request: {typeof(T).FullName}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// The key handle is for CAPI.
|
||||
// Our CAPI types don't allow usage from a handle, so we have a few choices:
|
||||
// 1) Extract the information we need to re-open the key handle.
|
||||
// 2) Re-implement {R|D}SACryptoServiceProvider
|
||||
// 3) PNSE.
|
||||
// 4) Defer to cert.Get{R|D}SAPrivateKey if not silent, throw otherwise.
|
||||
CspParameters cspParams = handle.GetProvParameters();
|
||||
Debug.Assert((cspParams.Flags & CspProviderFlags.UseExistingKey) != 0);
|
||||
cspParams.KeyNumber = (int)keySpec;
|
||||
|
||||
if (silent)
|
||||
{
|
||||
cspParams.Flags |= CspProviderFlags.NoPrompt;
|
||||
}
|
||||
|
||||
if (typeof(T) == typeof(RSA))
|
||||
return (T)(object)new RSACryptoServiceProvider(cspParams);
|
||||
if (typeof(T) == typeof(DSA))
|
||||
return (T)(object)new DSACryptoServiceProvider(cspParams);
|
||||
|
||||
Debug.Fail($"Unknown CAPI key type request: {typeof(T).FullName}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static SafeProvOrNCryptKeyHandle GetCertificatePrivateKey(
|
||||
X509Certificate2 cert,
|
||||
bool silent,
|
||||
bool preferNCrypt,
|
||||
out CryptKeySpec keySpec,
|
||||
out Exception exception)
|
||||
{
|
||||
CryptAcquireCertificatePrivateKeyFlags flags =
|
||||
CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_USE_PROV_INFO_FLAG
|
||||
| CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_COMPARE_KEY_FLAG;
|
||||
|
||||
if (preferNCrypt)
|
||||
{
|
||||
flags |= CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags |= CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG;
|
||||
}
|
||||
|
||||
if (silent)
|
||||
{
|
||||
flags |= CryptAcquireCertificatePrivateKeyFlags.CRYPT_ACQUIRE_SILENT_FLAG;
|
||||
}
|
||||
|
||||
bool isNCrypt;
|
||||
bool mustFree;
|
||||
using (SafeCertContextHandle hCertContext = cert.CreateCertContextHandle())
|
||||
{
|
||||
IntPtr hKey;
|
||||
int cbSize = IntPtr.Size;
|
||||
|
||||
if (Interop.Crypt32.CertGetCertificateContextProperty(
|
||||
hCertContext,
|
||||
CertContextPropId.CERT_NCRYPT_KEY_HANDLE_PROP_ID,
|
||||
out hKey,
|
||||
ref cbSize))
|
||||
{
|
||||
exception = null;
|
||||
keySpec = CryptKeySpec.CERT_NCRYPT_KEY_SPEC;
|
||||
return new SafeProvOrNCryptKeyHandleUwp(hKey, hCertContext);
|
||||
}
|
||||
|
||||
if (!Interop.Crypt32.CryptAcquireCertificatePrivateKey(
|
||||
hCertContext,
|
||||
flags,
|
||||
IntPtr.Zero,
|
||||
out hKey,
|
||||
out keySpec,
|
||||
out mustFree))
|
||||
{
|
||||
exception = Marshal.GetHRForLastWin32Error().ToCryptographicException();
|
||||
return null;
|
||||
}
|
||||
|
||||
// We need to know whether we got back a CRYPTPROV or NCrypt handle.
|
||||
// Unfortunately, NCryptIsKeyHandle() is a prohibited api on UWP.
|
||||
// Fortunately, CryptAcquireCertificatePrivateKey() is documented to tell us which
|
||||
// one we got through the keySpec value.
|
||||
switch (keySpec)
|
||||
{
|
||||
case CryptKeySpec.AT_KEYEXCHANGE:
|
||||
case CryptKeySpec.AT_SIGNATURE:
|
||||
isNCrypt = false;
|
||||
break;
|
||||
|
||||
case CryptKeySpec.CERT_NCRYPT_KEY_SPEC:
|
||||
isNCrypt = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// As of this writing, we've exhausted all the known values of keySpec.
|
||||
// We have no idea what kind of key handle we got so play it safe and fail fast.
|
||||
throw new NotSupportedException(SR.Format(SR.Cryptography_Cms_UnknownKeySpec, keySpec));
|
||||
}
|
||||
|
||||
SafeProvOrNCryptKeyHandleUwp hProvOrNCryptKey = new SafeProvOrNCryptKeyHandleUwp(
|
||||
hKey,
|
||||
ownsHandle: mustFree,
|
||||
isNcrypt: isNCrypt);
|
||||
|
||||
exception = null;
|
||||
return hProvOrNCryptKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,16 @@ namespace Internal.Cryptography
|
||||
/// </summary>
|
||||
public abstract byte[] GetSubjectKeyIdentifier(X509Certificate2 certificate);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a private key object for the certificate to use with signing.
|
||||
/// </summary>
|
||||
public abstract T GetPrivateKeyForSigning<T>(X509Certificate2 certificate, bool silent) where T : AsymmetricAlgorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a private key object for the certificate to use with decryption.
|
||||
/// </summary>
|
||||
public abstract T GetPrivateKeyForDecryption<T>(X509Certificate2 certificate, bool silent) where T : AsymmetricAlgorithm;
|
||||
|
||||
/// <summary>
|
||||
/// Get the one (and only) instance of PkcsPal.
|
||||
/// </summary>
|
||||
|
||||
@@ -67,33 +67,183 @@
|
||||
<data name="Argument_InvalidOffLen" xml:space="preserve">
|
||||
<value>Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.</value>
|
||||
</data>
|
||||
<data name="Argument_InvalidOidValue" xml:space="preserve">
|
||||
<value>The OID value was invalid.</value>
|
||||
</data>
|
||||
<data name="ArgumentOutOfRange_Index" xml:space="preserve">
|
||||
<value>Index was out of range. Must be non-negative and less than the size of the collection.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Asn_EnumeratedValueRequiresNonFlagsEnum" xml:space="preserve">
|
||||
<value>ASN.1 Enumerated values only apply to enum types without the [Flags] attribute.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Asn_NamedBitListRequiresFlagsEnum" xml:space="preserve">
|
||||
<value>Named bit list operations require an enum with the [Flags] attribute.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Asn_NamedBitListValueTooBig" xml:space="preserve">
|
||||
<value>The encoded named bit list value is larger than the value size of the '{0}' enum.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Asn_UniversalValueIsFixed" xml:space="preserve">
|
||||
<value>Tags with TagClass Universal must have the appropriate TagValue value for the data type being read or written.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Asn_UnusedBitCountRange" xml:space="preserve">
|
||||
<value>Unused bit count must be between 0 and 7, inclusive.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_AmbiguousFieldType" xml:space="preserve">
|
||||
<value>Field '{0}' of type '{1}' has ambiguous type '{2}', an attribute derived from AsnTypeAttribute is required.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_AllowNullNonNullable" xml:space="preserve">
|
||||
<value>[Choice].AllowNull=true is not valid because type '{0}' cannot have a null value.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_ConflictingTagMapping" xml:space="preserve">
|
||||
<value>The tag ({0} {1}) for field '{2}' on type '{3}' already is associated in this context with field '{4}' on type '{5}'.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_DefaultValueDisallowed" xml:space="preserve">
|
||||
<value>Field '{0}' on [Choice] type '{1}' has a default value, which is not permitted.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_NoChoiceWasMade" xml:space="preserve">
|
||||
<value>An instance of [Choice] type '{0}' has no non-null fields.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_NonNullableField" xml:space="preserve">
|
||||
<value>Field '{0}' on [Choice] type '{1}' can not be assigned a null value.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_TooManyValues" xml:space="preserve">
|
||||
<value>Fields '{0}' and '{1}' on type '{2}' are both non-null when only one value is permitted.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Choice_TypeCycle" xml:space="preserve">
|
||||
<value>Field '{0}' on [Choice] type '{1}' has introduced a type chain cycle.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_MultipleAsnTypeAttributes" xml:space="preserve">
|
||||
<value>Field '{0}' on type '{1}' has multiple attributes deriving from '{2}' when at most one is permitted.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_NoJaggedArrays" xml:space="preserve">
|
||||
<value>Type '{0}' cannot be serialized or deserialized because it is an array of arrays.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_NoMultiDimensionalArrays" xml:space="preserve">
|
||||
<value>Type '{0}' cannot be serialized or deserialized because it is a multi-dimensional array.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_NoOpenTypes" xml:space="preserve">
|
||||
<value>Type '{0}' cannot be serialized or deserialized because it is not sealed or has unbound generic parameters.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_Optional_NonNullableField" xml:space="preserve">
|
||||
<value>Field '{0}' on type '{1}' is declared [OptionalValue], but it can not be assigned a null value.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_PopulateFriendlyNameOnString" xml:space="preserve">
|
||||
<value>Field '{0}' on type '{1}' has [ObjectIdentifier].PopulateFriendlyName set to true, which is not applicable to a string. Change the field to '{2}' or set PopulateFriendlyName to false.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_SetValueException" xml:space="preserve">
|
||||
<value>Unable to set field {0} on type {1}.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_SpecificTagChoice" xml:space="preserve">
|
||||
<value>Field '{0}' on type '{1}' has specified an implicit tag value via [ExpectedTag] for [Choice] type '{2}'. ExplicitTag must be true, or the [ExpectedTag] attribute removed.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_UnexpectedTypeForAttribute" xml:space="preserve">
|
||||
<value>Field '{0}' of type '{1}' has an effective type of '{2}' when one of ({3}) was expected.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_UtcTimeTwoDigitYearMaxTooSmall" xml:space="preserve">
|
||||
<value>Field '{0}' on type '{1}' has a [UtcTime] TwoDigitYearMax value ({2}) smaller than the minimum (99).</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnSerializer_UnhandledType" xml:space="preserve">
|
||||
<value>Could not determine how to serialize or deserialize type '{0}'.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnWriter_EncodeUnbalancedStack" xml:space="preserve">
|
||||
<value>Encode cannot be called while a Sequence or SetOf is still open.</value>
|
||||
</data>
|
||||
<data name="Cryptography_AsnWriter_PopWrongTag" xml:space="preserve">
|
||||
<value>Cannot pop the requested tag as it is not currently in progress.</value>
|
||||
</data>
|
||||
<data name="Cryptography_BadHashValue" xml:space="preserve">
|
||||
<value>The hash value is not correct.</value>
|
||||
</data>
|
||||
<data name="Cryptography_BadSignature" xml:space="preserve">
|
||||
<value>Invalid signature.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_CannotDetermineSignatureAlgorithm" xml:space="preserve">
|
||||
<value>Could not determine signature algorithm for the signer certificate.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_IncompleteCertChain" xml:space="preserve">
|
||||
<value>The certificate chain is incomplete, the self-signed root authority could not be determined.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_Invalid_Originator_Identifier_Choice" xml:space="preserve">
|
||||
<value>Invalid originator identifier choice {0} found in decoded CMS.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_Invalid_Subject_Identifier_Type" xml:space="preserve">
|
||||
<value>The subject identifier type {0} is not valid.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_InvalidMessageType" xml:space="preserve">
|
||||
<value>Invalid cryptographic message type.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_InvalidSignerHashForSignatureAlg" xml:space="preserve">
|
||||
<value>SignerInfo digest algorithm '{0}' is not valid for signature algorithm '{1}'.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_Key_Agree_Date_Not_Available" xml:space="preserve">
|
||||
<value>The Date property is not available for none KID key agree recipient.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_MessageNotEncrypted" xml:space="preserve">
|
||||
<value>The CMS message is not encrypted.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_MessageNotSigned" xml:space="preserve">
|
||||
<value>The CMS message is not signed.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_MissingAuthenticatedAttribute" xml:space="preserve">
|
||||
<value>The cryptographic message does not contain an expected authenticated attribute.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_NoCounterCounterSigner" xml:space="preserve">
|
||||
<value>Only one level of counter-signatures are supported on this platform.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_NoRecipients" xml:space="preserve">
|
||||
<value>The recipients collection is empty. You must specify at least one recipient. This platform does not implement the certificate picker UI.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_NoSignerCert" xml:space="preserve">
|
||||
<value>No signer certificate was provided. This platform does not implement the certificate picker UI.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_NoSignerAtIndex" xml:space="preserve">
|
||||
<value>The signed cryptographic message does not have a signer for the specified signer index.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_Sign_Empty_Content" xml:space="preserve">
|
||||
<value>Cannot create CMS signature for empty content.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_SignerNotFound" xml:space="preserve">
|
||||
<value>Cannot find the original signer.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_Signing_RequiresPrivateKey" xml:space="preserve">
|
||||
<value>A certificate with a private key is required.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_TrustFailure" xml:space="preserve">
|
||||
<value>Certificate trust could not be established. The first reported error is: {0}</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_UnknownAlgorithm" xml:space="preserve">
|
||||
<value>Unknown algorithm '{0}'.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_UnknownKeySpec" xml:space="preserve">
|
||||
<value>Unable to determine the type of key handle from this keyspec {0}.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_WrongKeyUsage" xml:space="preserve">
|
||||
<value>The certificate is not valid for the requested usage.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs_InvalidSignatureParameters" xml:space="preserve">
|
||||
<value>Invalid signature paramters.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs9_AttributeMismatch" xml:space="preserve">
|
||||
<value>The parameter should be a PKCS 9 attribute.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs9_MultipleSigningTimeNotAllowed" xml:space="preserve">
|
||||
<value>Cannot add multiple PKCS 9 signing time attributes.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs_PssParametersMissing" xml:space="preserve">
|
||||
<value>PSS parameters were not present.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs_PssParametersHashMismatch" xml:space="preserve">
|
||||
<value>This platform requires that the PSS hash algorithm ({0}) match the data digest algorithm ({1}).</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs_PssParametersMgfHashMismatch" xml:space="preserve">
|
||||
<value>This platform does not support the MGF hash algorithm ({0}) being different from the signature hash algorithm ({1}).</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs_PssParametersMgfNotSupported" xml:space="preserve">
|
||||
<value>Mask generation function '{0}' is not supported by this platform.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Pkcs_PssParametersSaltMismatch" xml:space="preserve">
|
||||
<value>PSS salt size {0} is not supported by this platform with hash algorithm {1}.</value>
|
||||
</data>
|
||||
<data name="InvalidOperation_DuplicateItemNotAllowed" xml:space="preserve">
|
||||
<value>Duplicate items are not allowed in the collection.</value>
|
||||
</data>
|
||||
@@ -103,4 +253,16 @@
|
||||
<data name="PlatformNotSupported_CryptographyPkcs" xml:space="preserve">
|
||||
<value>System.Security.Cryptography.Pkcs is only supported on Windows platforms.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Der_Invalid_Encoding" xml:space="preserve">
|
||||
<value>ASN1 corrupted data.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Invalid_IA5String" xml:space="preserve">
|
||||
<value>The string contains a character not in the 7 bit ASCII character set.</value>
|
||||
</data>
|
||||
<data name="Cryptography_UnknownHashAlgorithm" xml:space="preserve">
|
||||
<value>'{0}' is not a known hash algorithm.</value>
|
||||
</data>
|
||||
<data name="Cryptography_WriteEncodedValue_OneValueAtATime" xml:space="preserve">
|
||||
<value>The input to WriteEncodedValue must represent a single encoded value with no trailing data.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -7,20 +7,26 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netfx'">true</IsPartialFacadeAssembly>
|
||||
<ResourcesSourceOutputDirectory Condition="'$(IsPartialFacadeAssembly)' == 'true'">None</ResourcesSourceOutputDirectory>
|
||||
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetGroup)' == 'netstandard' AND '$(TargetsWindows)' != 'true'">SR.PlatformNotSupported_CryptographyPkcs</GeneratePlatformNotSupportedAssemblyMessage>
|
||||
<UsePackageTargetRuntimeDefaults Condition="'$(IsPartialFacadeAssembly)' != 'true'">true</UsePackageTargetRuntimeDefaults>
|
||||
<IncludeDllSafeSearchPathAttribute>true</IncludeDllSafeSearchPathAttribute>
|
||||
</PropertyGroup>
|
||||
<!-- Don't delete these clauses even if they look useless. They tell the VS IDE that "Windows_Debug", etc., are
|
||||
valid configuration for this project and stop it from trying to "fix up" the .sln file -->
|
||||
<!-- API types (platform independent) -->
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netstandard-Windows_NT-Release|AnyCPU'" />
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true' AND ('$(TargetGroup)' != 'netstandard' OR '$(TargetsWindows)' == 'true')">
|
||||
<PropertyGroup Condition="'$(TargetGroup)'=='netcoreapp'">
|
||||
<DefineConstants>$(DefineConstants);netcoreapp</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="System\Security\Cryptography\CryptographicAttributeObject.cs" />
|
||||
<Compile Include="System\Security\Cryptography\CryptographicAttributeObjectCollection.cs" />
|
||||
<Compile Include="System\Security\Cryptography\CryptographicAttributeObjectEnumerator.cs" />
|
||||
@@ -50,7 +56,7 @@
|
||||
<Compile Include="System\Security\Cryptography\Xml\X509IssuerSerial.cs" />
|
||||
</ItemGroup>
|
||||
<!-- Internal types (platform independent) -->
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true' AND ('$(TargetGroup)' != 'netstandard' OR '$(TargetsWindows)' == 'true')">
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="Internal\Cryptography\DecryptorPal.cs" />
|
||||
<Compile Include="Internal\Cryptography\KeyAgreeRecipientInfoPal.cs" />
|
||||
<Compile Include="Internal\Cryptography\KeyLengths.cs" />
|
||||
@@ -82,6 +88,9 @@
|
||||
</ItemGroup>
|
||||
<!-- Interop types (platform: Windows) -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' == 'true' AND '$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="$(CommonPath)\Interop\Windows\advapi32\Interop.CryptGetProvParam.cs">
|
||||
<Link>Common\Interop\Windows\advapi32\Interop.CryptGetProvParam.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Interop\Windows\Crypt32\Interop.CERT_CONTEXT.cs" />
|
||||
<Compile Include="Interop\Windows\Crypt32\Interop.CERT_ID.cs" />
|
||||
<Compile Include="Interop\Windows\Crypt32\Interop.CERT_INFO.cs" />
|
||||
@@ -164,13 +173,75 @@
|
||||
<Link>Common\Interop\Windows\NCrypt\Interop.NCryptFreeObject.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<!-- Internal types (platform: Unix) -->
|
||||
<ItemGroup Condition="'$(TargetsUnix)' == 'true' AND '$(IsPartialFacadeAssembly)' != 'true' AND '$(TargetGroup)' != 'netstandard'">
|
||||
<Compile Include="Internal\Cryptography\Pal\Unix\PkcsPal.Unix.cs" />
|
||||
<!-- Internal types (platform: AnyOS) -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' != 'true' AND '$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\PkcsPal.AnyOS.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' == 'true'">
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="System.Security" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
|
||||
<Reference Include="System.Runtime" />
|
||||
<Reference Include="System.Runtime.Numerics" />
|
||||
<Reference Include="System.Collections" />
|
||||
<Reference Include="System.Collections.NonGeneric" />
|
||||
<Reference Include="System.Collections.Concurrent" />
|
||||
<Reference Include="System.Security.Cryptography.Csp" />
|
||||
<Reference Include="System.Security.Cryptography.Encoding" />
|
||||
<Reference Include="System.Security.Cryptography.X509Certificates" />
|
||||
<Reference Include="System.Resources.ResourceManager" />
|
||||
<Reference Include="System.Runtime.InteropServices" />
|
||||
<Reference Include="System.Diagnostics.Debug" />
|
||||
<Reference Include="System.Diagnostics.Tools" />
|
||||
<Reference Include="System.Runtime.Extensions" />
|
||||
<Reference Include="System.Runtime.InteropServices.RuntimeInformation" />
|
||||
<Reference Include="System.Security.Cryptography.Primitives" />
|
||||
<Reference Include="System.Security.Cryptography.Algorithms" />
|
||||
<Reference Include="System.Threading" />
|
||||
<Reference Include="System.Linq" />
|
||||
<Reference Include="System.Text.Encoding.Extensions" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Reference Include="System.Buffers" />
|
||||
<Reference Include="System.Memory" />
|
||||
<Reference Include="System.Security.Cryptography.Cng" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1V2.cs">
|
||||
<Link>Common\System\Security\Cryptography\Asn1V2.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Security\Cryptography\Asn1V2.Serializer.cs">
|
||||
<Link>Common\System\Security\Cryptography\Asn1V2.Serializer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Security\Cryptography\AsnReader.cs">
|
||||
<Link>Common\System\Security\Cryptography\AsnReader.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\System\Security\Cryptography\AsnWriter.cs">
|
||||
<Link>Common\System\Security\Cryptography\AsnWriter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\AlgorithmIdentifierAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\AttributeAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\CertificateChoiceAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\ContentInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\EncapsulatedContentInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\IssuerAndSerialNumberAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\PssParamsAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\SignedDataAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\SignerIdentifierAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\SignerInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\CmsSignature.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\CmsSignature.ECDsa.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\CmsSignature.RSA.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\CmsSigner.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\SignedCms.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\SignedCms.CtorOverloads.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\SignerInfo.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\SignerInfoCollection.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\SignerInfoEnumerator.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\CmsSignature.DSA.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -72,6 +72,12 @@ namespace System.Security.Cryptography
|
||||
return indexOfNewItem;
|
||||
}
|
||||
|
||||
internal void AddWithoutMerge(CryptographicAttributeObject attribute)
|
||||
{
|
||||
Debug.Assert(attribute != null);
|
||||
_list.Add(attribute);
|
||||
}
|
||||
|
||||
public void Remove(CryptographicAttributeObject attribute)
|
||||
{
|
||||
if (attribute == null)
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.Asn1;
|
||||
|
||||
namespace System.Security.Cryptography.Pkcs.Asn1
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// https://tools.ietf.org/html/rfc3280#section-4.1.1.2
|
||||
//
|
||||
// AlgorithmIdentifier ::= SEQUENCE {
|
||||
// algorithm OBJECT IDENTIFIER,
|
||||
// parameters ANY DEFINED BY algorithm OPTIONAL }
|
||||
internal struct AlgorithmIdentifierAsn
|
||||
{
|
||||
[ObjectIdentifier(PopulateFriendlyName = true)]
|
||||
public Oid Algorithm;
|
||||
|
||||
[AnyValue, OptionalValue]
|
||||
public ReadOnlyMemory<byte>? Parameters;
|
||||
|
||||
internal bool Equals(ref AlgorithmIdentifierAsn other)
|
||||
{
|
||||
if (Algorithm.Value != other.Algorithm.Value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isNull = RepresentsNull(Parameters);
|
||||
bool isOtherNull = RepresentsNull(other.Parameters);
|
||||
|
||||
if (isNull != isOtherNull)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNull)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parameters.Value.Span.SequenceEqual(other.Parameters.Value.Span);
|
||||
}
|
||||
|
||||
private static bool RepresentsNull(ReadOnlyMemory<byte>? parameters)
|
||||
{
|
||||
if (parameters == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> span = parameters.Value.Span;
|
||||
|
||||
if (span.Length != 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (span[0] != 0x05)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return span[1] == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.Asn1;
|
||||
|
||||
namespace System.Security.Cryptography.Pkcs.Asn1
|
||||
{
|
||||
// https://tools.ietf.org/html/rfc5652#section-5.3
|
||||
//
|
||||
// Attribute ::= SEQUENCE {
|
||||
// attrType OBJECT IDENTIFIER,
|
||||
// attrValues SET OF AttributeValue }
|
||||
//
|
||||
// AttributeValue ::= ANY
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct AttributeAsn
|
||||
{
|
||||
public Oid AttrType;
|
||||
|
||||
[AnyValue]
|
||||
public ReadOnlyMemory<byte> AttrValues;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user