Imported Upstream version 5.10.0.69

Former-commit-id: fc39669a0b707dd3c063977486506b6793da2890
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-29 19:03:06 +00:00
parent d8f8abd549
commit e2950ec768
6283 changed files with 453847 additions and 91879 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -3,7 +3,8 @@
<PropertyGroup>
<BuildConfigurations>
netstandard;
netcoreapp;
netfx;
</BuildConfigurations>
</PropertyGroup>
</Project>
</Project>

View File

@@ -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 { } }
}

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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;
}
}
}

View File

@@ -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";
}
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
}
}
}
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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)

View File

@@ -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;
}
}
}

View File

@@ -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