You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@@ -8,6 +8,12 @@
|
||||
<ProjectReference Include="..\src\System.Security.Cryptography.Pkcs.csproj" />
|
||||
<HarvestIncludePaths Include="ref/net46;lib/net46;runtimes/win/lib/net46" />
|
||||
<HarvestIncludePaths Include="ref/netstandard1.3;runtimes/win/lib/netstandard1.3;lib/netstandard1.3" />
|
||||
|
||||
<!--
|
||||
Suppress NETStandard.Library collpasing as it add more dependencies then needed in some
|
||||
scenarios like .NET Framework which adds an unecessary amount of package dependencies to download
|
||||
-->
|
||||
<SuppressMetaPackage Include="NETStandard.Library" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace System.Security.Cryptography
|
||||
public CryptographicAttributeObjectCollection(System.Security.Cryptography.CryptographicAttributeObject attribute) { }
|
||||
public int Count { get { throw null; } }
|
||||
public System.Security.Cryptography.CryptographicAttributeObject this[int index] { get { throw null; } }
|
||||
bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
|
||||
object System.Collections.ICollection.SyncRoot { get { throw null; } }
|
||||
public bool IsSynchronized { get { throw null; } }
|
||||
public object SyncRoot { get { throw null; } }
|
||||
public int Add(System.Security.Cryptography.AsnEncodedData asnEncodedData) { throw null; }
|
||||
public int Add(System.Security.Cryptography.CryptographicAttributeObject attribute) { throw null; }
|
||||
public void CopyTo(System.Security.Cryptography.CryptographicAttributeObject[] array, int index) { }
|
||||
@@ -48,6 +48,7 @@ namespace System.Security.Cryptography.Pkcs
|
||||
public AlgorithmIdentifier(System.Security.Cryptography.Oid oid, int keyLength) { }
|
||||
public int KeyLength { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public System.Security.Cryptography.Oid Oid { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
public byte[] Parameters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
|
||||
}
|
||||
public sealed partial class CmsRecipient
|
||||
{
|
||||
@@ -63,8 +64,8 @@ namespace System.Security.Cryptography.Pkcs
|
||||
public CmsRecipientCollection(System.Security.Cryptography.Pkcs.SubjectIdentifierType recipientIdentifierType, System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) { }
|
||||
public int Count { get { throw null; } }
|
||||
public System.Security.Cryptography.Pkcs.CmsRecipient this[int index] { get { throw null; } }
|
||||
bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
|
||||
object System.Collections.ICollection.SyncRoot { get { throw null; } }
|
||||
public bool IsSynchronized { get { throw null; } }
|
||||
public object SyncRoot { get { throw null; } }
|
||||
public int Add(System.Security.Cryptography.Pkcs.CmsRecipient recipient) { throw null; }
|
||||
public void CopyTo(System.Array array, int index) { }
|
||||
public void CopyTo(System.Security.Cryptography.Pkcs.CmsRecipient[] array, int index) { }
|
||||
@@ -91,9 +92,9 @@ namespace System.Security.Cryptography.Pkcs
|
||||
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 CryptographicAttributeObjectCollection SignedAttributes { get => throw null; }
|
||||
public CryptographicAttributeObjectCollection UnsignedAttributes { get => throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get => throw null; }
|
||||
public System.Security.Cryptography.X509Certificates.X509IncludeOption IncludeOption { get => throw null; set => throw null; }
|
||||
}
|
||||
public sealed partial class ContentInfo
|
||||
@@ -208,8 +209,8 @@ namespace System.Security.Cryptography.Pkcs
|
||||
internal RecipientInfoCollection() { }
|
||||
public int Count { get { throw null; } }
|
||||
public System.Security.Cryptography.Pkcs.RecipientInfo this[int index] { get { throw null; } }
|
||||
bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
|
||||
object System.Collections.ICollection.SyncRoot { get { throw null; } }
|
||||
public bool IsSynchronized { get { throw null; } }
|
||||
public object SyncRoot { get { throw null; } }
|
||||
public void CopyTo(System.Array array, int index) { }
|
||||
public void CopyTo(System.Security.Cryptography.Pkcs.RecipientInfo[] array, int index) { }
|
||||
public System.Security.Cryptography.Pkcs.RecipientInfoEnumerator GetEnumerator() { throw null; }
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<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.Primitives\ref\System.Security.Cryptography.Primitives.csproj" />
|
||||
<ProjectReference Include="..\..\System.Security.Cryptography.X509Certificates\ref\System.Security.Cryptography.X509Certificates.csproj" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
|
||||
@@ -5,8 +5,60 @@
|
||||
// Changes to this file must follow the http://aka.ms/api-review process.
|
||||
// ------------------------------------------------------------------------------
|
||||
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace System.Security.Cryptography.Pkcs
|
||||
{
|
||||
public sealed partial class Rfc3161TimestampRequest
|
||||
{
|
||||
private Rfc3161TimestampRequest() { }
|
||||
public int Version => throw null;
|
||||
public ReadOnlyMemory<byte> GetMessageHash() => throw null;
|
||||
public Oid HashAlgorithmId => throw null;
|
||||
public Oid RequestedPolicyId => throw null;
|
||||
public bool RequestSignerCertificate => throw null;
|
||||
public ReadOnlyMemory<byte>? GetNonce() => throw null;
|
||||
public bool HasExtensions => throw null;
|
||||
public X509ExtensionCollection GetExtensions() => throw null;
|
||||
public byte[] Encode() => throw null;
|
||||
public bool TryEncode(Span<byte> destination, out int bytesWritten) => throw null;
|
||||
public Rfc3161TimestampToken ProcessResponse(ReadOnlyMemory<byte> responseBytes, out int bytesConsumed) => throw null;
|
||||
public static Rfc3161TimestampRequest CreateFromData(ReadOnlySpan<byte> data, HashAlgorithmName hashAlgorithm, Oid requestedPolicyId = null, ReadOnlyMemory<byte>? nonce = null, bool requestSignerCertificates = false, X509ExtensionCollection extensions = null) => throw null;
|
||||
public static Rfc3161TimestampRequest CreateFromHash(ReadOnlyMemory<byte> hash, HashAlgorithmName hashAlgorithm, Oid requestedPolicyId = null, ReadOnlyMemory<byte>? nonce = null, bool requestSignerCertificates = false, X509ExtensionCollection extensions = null) => throw null;
|
||||
public static Rfc3161TimestampRequest CreateFromHash(ReadOnlyMemory<byte> hash, Oid hashAlgorithmId, Oid requestedPolicyId = null, ReadOnlyMemory<byte>? nonce = null, bool requestSignerCertificates = false, X509ExtensionCollection extensions = null) => throw null;
|
||||
public static Rfc3161TimestampRequest CreateFromSignerInfo(SignerInfo signerInfo, HashAlgorithmName hashAlgorithm, Oid requestedPolicyId = null, ReadOnlyMemory<byte>? nonce = null, bool requestSignerCertificates = false, X509ExtensionCollection extensions = null) => throw null;
|
||||
public static bool TryDecode(ReadOnlyMemory<byte> encodedBytes, out Rfc3161TimestampRequest request, out int bytesConsumed) => throw null;
|
||||
}
|
||||
public sealed partial class Rfc3161TimestampToken
|
||||
{
|
||||
private Rfc3161TimestampToken() { }
|
||||
public Rfc3161TimestampTokenInfo TokenInfo => throw null;
|
||||
public SignedCms AsSignedCms() => throw null;
|
||||
public bool VerifySignatureForHash(ReadOnlySpan<byte> hash, HashAlgorithmName hashAlgorithm, out X509Certificate2 signerCertificate, X509Certificate2Collection extraCandidates = null) => throw null;
|
||||
public bool VerifySignatureForHash(ReadOnlySpan<byte> hash, Oid hashAlgorithmId, out X509Certificate2 signerCertificate, X509Certificate2Collection extraCandidates = null) => throw null;
|
||||
public bool VerifySignatureForData(ReadOnlySpan<byte> data, out X509Certificate2 signerCertificate, X509Certificate2Collection extraCandidates = null) => throw null;
|
||||
public bool VerifySignatureForSignerInfo(SignerInfo signerInfo, out X509Certificate2 signerCertificate, X509Certificate2Collection extraCandidates = null) => throw null;
|
||||
public static bool TryDecode(ReadOnlyMemory<byte> encodedBytes, out Rfc3161TimestampToken token, out int bytesConsumed) => throw null;
|
||||
}
|
||||
public sealed partial class Rfc3161TimestampTokenInfo
|
||||
{
|
||||
public Rfc3161TimestampTokenInfo(Oid policyId, Oid hashAlgorithmId, ReadOnlyMemory<byte> messageHash, ReadOnlyMemory<byte> serialNumber, DateTimeOffset timestamp, long? accuracyInMicroseconds=null, bool isOrdering=false, ReadOnlyMemory<byte>? nonce=null, ReadOnlyMemory<byte>? timestampAuthorityName=null, X509ExtensionCollection extensions =null) { throw null; }
|
||||
public int Version => throw null;
|
||||
public Oid PolicyId=> throw null;
|
||||
public Oid HashAlgorithmId => throw null;
|
||||
public ReadOnlyMemory<byte> GetMessageHash() { throw null; }
|
||||
public ReadOnlyMemory<byte> GetSerialNumber() { throw null; }
|
||||
public DateTimeOffset Timestamp => throw null;
|
||||
public long? AccuracyInMicroseconds => throw null;
|
||||
public bool IsOrdering => throw null;
|
||||
public ReadOnlyMemory<byte>? GetNonce() { throw null; }
|
||||
public ReadOnlyMemory<byte>? GetTimestampAuthorityName() { throw null; }
|
||||
public bool HasExtensions => throw null;
|
||||
public X509ExtensionCollection GetExtensions() { throw null; }
|
||||
public byte[] Encode() => throw null;
|
||||
public bool TryEncode(Span<byte> destination, out int bytesWritten) => throw null;
|
||||
public static bool TryDecode(ReadOnlyMemory<byte> encodedBytes, out Rfc3161TimestampTokenInfo timestampTokenInfo, out int bytesConsumed) { throw null; }
|
||||
}
|
||||
public sealed partial class SignerInfo
|
||||
{
|
||||
public Oid SignatureAlgorithm => throw null;
|
||||
|
||||
@@ -6,6 +6,7 @@ using System;
|
||||
using System.Buffers;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.Asn1;
|
||||
@@ -56,6 +57,22 @@ namespace Internal.Cryptography
|
||||
}
|
||||
}
|
||||
|
||||
internal static string GetOidFromHashAlgorithm(HashAlgorithmName algName)
|
||||
{
|
||||
if (algName == HashAlgorithmName.MD5)
|
||||
return Oids.Md5;
|
||||
if (algName == HashAlgorithmName.SHA1)
|
||||
return Oids.Sha1;
|
||||
if (algName == HashAlgorithmName.SHA256)
|
||||
return Oids.Sha256;
|
||||
if (algName == HashAlgorithmName.SHA384)
|
||||
return Oids.Sha384;
|
||||
if (algName == HashAlgorithmName.SHA512)
|
||||
return Oids.Sha512;
|
||||
|
||||
throw new CryptographicException(SR.Cryptography_Cms_UnknownAlgorithm, algName.Name);
|
||||
}
|
||||
|
||||
/// <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."
|
||||
@@ -119,6 +136,26 @@ namespace Internal.Cryptography
|
||||
return set.SetData;
|
||||
}
|
||||
|
||||
internal static byte[] EncodeContentInfo<T>(
|
||||
T value,
|
||||
string contentType,
|
||||
AsnEncodingRules ruleSet = AsnEncodingRules.DER)
|
||||
{
|
||||
using (AsnWriter innerWriter = AsnSerializer.Serialize(value, ruleSet))
|
||||
{
|
||||
ContentInfoAsn content = new ContentInfoAsn
|
||||
{
|
||||
ContentType = contentType,
|
||||
Content = innerWriter.Encode(),
|
||||
};
|
||||
|
||||
using (AsnWriter outerWriter = AsnSerializer.Serialize(content, ruleSet))
|
||||
{
|
||||
return outerWriter.Encode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static CmsRecipientCollection DeepCopy(this CmsRecipientCollection recipients)
|
||||
{
|
||||
CmsRecipientCollection recipientsCopy = new CmsRecipientCollection();
|
||||
@@ -151,7 +188,7 @@ namespace Internal.Cryptography
|
||||
|
||||
public static X509Certificate2Collection GetStoreCertificates(StoreName storeName, StoreLocation storeLocation, bool openExistingOnly)
|
||||
{
|
||||
using (X509Store store = new X509Store())
|
||||
using (X509Store store = new X509Store(storeName, storeLocation))
|
||||
{
|
||||
OpenFlags flags = OpenFlags.ReadOnly | OpenFlags.IncludeArchived;
|
||||
if (openExistingOnly)
|
||||
@@ -234,14 +271,14 @@ namespace Internal.Cryptography
|
||||
return skiString.UpperHexStringToByteArray();
|
||||
}
|
||||
|
||||
public static string ToSkiString(this ReadOnlySpan<byte> skiBytes)
|
||||
public static string ToSkiString(this byte[] skiBytes)
|
||||
{
|
||||
return ToUpperHexString(skiBytes);
|
||||
}
|
||||
|
||||
public static string ToSkiString(this byte[] skiBytes)
|
||||
public static string ToBigEndianHex(this ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
return ToUpperHexString(skiBytes);
|
||||
return ToUpperHexString(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -398,6 +435,29 @@ namespace Internal.Cryptography
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static byte[] OneShot(this ICryptoTransform transform, byte[] data)
|
||||
{
|
||||
return OneShot(transform, data, 0, data.Length);
|
||||
}
|
||||
|
||||
internal static byte[] OneShot(this ICryptoTransform transform, byte[] data, int offset, int length)
|
||||
{
|
||||
if (transform.CanTransformMultipleBlocks)
|
||||
{
|
||||
return transform.TransformFinalBlock(data, offset, length);
|
||||
}
|
||||
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Write))
|
||||
{
|
||||
cryptoStream.Write(data, offset, length);
|
||||
}
|
||||
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static ReadOnlyMemory<byte> GetSubjectPublicKeyInfo(X509Certificate2 certificate)
|
||||
{
|
||||
var parsedCertificate = AsnSerializer.Deserialize<Certificate>(certificate.RawData, AsnEncodingRules.DER);
|
||||
|
||||
@@ -2,19 +2,22 @@
|
||||
// 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.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Internal.Cryptography
|
||||
{
|
||||
internal static class Oids
|
||||
{
|
||||
// Symmetric encryption algorithms
|
||||
public const string Rc2Cbc = "1.2.840.113549.3.2";
|
||||
public const string Rc4 = "1.2.840.113549.3.4";
|
||||
public const string TripleDesCbc = "1.2.840.113549.3.7";
|
||||
public const string DesCbc = "1.3.14.3.2.7";
|
||||
public const string Aes128Cbc = "2.16.840.1.101.3.4.1.2";
|
||||
public const string Aes192Cbc = "2.16.840.1.101.3.4.1.22";
|
||||
public const string Aes256Cbc = "2.16.840.1.101.3.4.1.42";
|
||||
|
||||
// Asymmetric encryption algorithms
|
||||
public const string Rsa = "1.2.840.113549.1.1.1";
|
||||
public const string RsaOaep = "1.2.840.113549.1.1.7";
|
||||
public const string RsaPss = "1.2.840.113549.1.1.10";
|
||||
public const string Esdh = "1.2.840.113549.1.9.16.3.5";
|
||||
|
||||
@@ -24,6 +27,8 @@ namespace Internal.Cryptography
|
||||
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 SigningCertificate = "1.2.840.113549.1.9.16.2.12";
|
||||
public const string SigningCertificateV2 = "1.2.840.113549.1.9.16.2.47";
|
||||
public const string DocumentName = "1.3.6.1.4.1.311.88.2.1";
|
||||
|
||||
// Key wrap algorithms
|
||||
@@ -64,5 +69,9 @@ namespace Internal.Cryptography
|
||||
// Cert Extensions
|
||||
public const string SubjectKeyIdentifier = "2.5.29.14";
|
||||
public const string KeyUsage = "2.5.29.15";
|
||||
|
||||
// RFC3161 Timestamping
|
||||
public const string TstInfo = "1.2.840.113549.1.9.16.1.4";
|
||||
public const string TimeStampingPurpose = "1.3.6.1.5.5.7.3.8";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
// 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;
|
||||
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 System.Security.Cryptography.Xml;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal static class AsnHelpers
|
||||
{
|
||||
internal static SubjectIdentifierOrKey ToSubjectIdentifierOrKey(
|
||||
this OriginatorIdentifierOrKeyAsn originator)
|
||||
{
|
||||
if (originator.IssuerAndSerialNumber != null)
|
||||
{
|
||||
var name = new X500DistinguishedName(originator.IssuerAndSerialNumber.Value.Issuer.ToArray());
|
||||
|
||||
return new SubjectIdentifierOrKey(
|
||||
SubjectIdentifierOrKeyType.IssuerAndSerialNumber,
|
||||
new X509IssuerSerial(
|
||||
name.Name,
|
||||
originator.IssuerAndSerialNumber.Value.SerialNumber.Span.ToBigEndianHex()));
|
||||
}
|
||||
|
||||
if (originator.SubjectKeyIdentifier != null)
|
||||
{
|
||||
return new SubjectIdentifierOrKey(
|
||||
SubjectIdentifierOrKeyType.SubjectKeyIdentifier,
|
||||
originator.SubjectKeyIdentifier.Value.Span.ToBigEndianHex());
|
||||
}
|
||||
|
||||
if (originator.OriginatorKey != null)
|
||||
{
|
||||
OriginatorPublicKeyAsn originatorKey = originator.OriginatorKey;
|
||||
|
||||
return new SubjectIdentifierOrKey(
|
||||
SubjectIdentifierOrKeyType.PublicKeyInfo,
|
||||
new PublicKeyInfo(
|
||||
originatorKey.Algorithm.ToPresentationObject(),
|
||||
originatorKey.PublicKey.ToArray()));
|
||||
}
|
||||
|
||||
Debug.Fail("Unknown SubjectIdentifierOrKey state");
|
||||
return new SubjectIdentifierOrKey(SubjectIdentifierOrKeyType.Unknown, String.Empty);
|
||||
}
|
||||
|
||||
internal static AlgorithmIdentifier ToPresentationObject(this AlgorithmIdentifierAsn asn)
|
||||
{
|
||||
int keyLength;
|
||||
|
||||
switch (asn.Algorithm.Value)
|
||||
{
|
||||
case Oids.Rc2Cbc:
|
||||
{
|
||||
if (asn.Parameters == null)
|
||||
{
|
||||
keyLength = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
Rc2CbcParameters rc2Params = AsnSerializer.Deserialize<Rc2CbcParameters>(
|
||||
asn.Parameters.Value,
|
||||
AsnEncodingRules.BER);
|
||||
|
||||
int keySize = rc2Params.GetEffectiveKeyBits();
|
||||
|
||||
// These are the only values .NET Framework would set.
|
||||
switch (keySize)
|
||||
{
|
||||
case 40:
|
||||
case 56:
|
||||
case 64:
|
||||
case 128:
|
||||
keyLength = keySize;
|
||||
break;
|
||||
default:
|
||||
keyLength = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Oids.Rc4:
|
||||
{
|
||||
if (asn.Parameters == null)
|
||||
{
|
||||
keyLength = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
int saltLen = 0;
|
||||
AsnReader reader = new AsnReader(asn.Parameters.Value, AsnEncodingRules.BER);
|
||||
|
||||
// DER NULL is considered the same as not present.
|
||||
// No call to ReadNull() is necessary because the serializer already verified that
|
||||
// there's no data after the [AnyValue] value.
|
||||
if (reader.PeekTag() != Asn1Tag.Null)
|
||||
{
|
||||
if (reader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> contents))
|
||||
{
|
||||
saltLen = contents.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<byte> salt = stackalloc byte[KeyLengths.Rc4Max_128Bit / 8];
|
||||
|
||||
if (!reader.TryCopyOctetStringBytes(salt, out saltLen))
|
||||
{
|
||||
throw new CryptographicException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keyLength = KeyLengths.Rc4Max_128Bit - 8 * saltLen;
|
||||
break;
|
||||
}
|
||||
case Oids.DesCbc:
|
||||
keyLength = KeyLengths.Des_64Bit;
|
||||
break;
|
||||
case Oids.TripleDesCbc:
|
||||
keyLength = KeyLengths.TripleDes_192Bit;
|
||||
break;
|
||||
default:
|
||||
// .NET Framework doesn't set a keylength for AES, or any other algorithm than the ones
|
||||
// listed here.
|
||||
keyLength = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return new AlgorithmIdentifier(new Oid(asn.Algorithm), keyLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
// 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.Asn1;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
private static readonly byte[] s_invalidEmptyOid = { 0x06, 0x00 };
|
||||
|
||||
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.
|
||||
#if __MonoCS__
|
||||
ReadOnlySpan<byte> data = new byte[0];
|
||||
#else
|
||||
ReadOnlySpan<byte> data = stackalloc byte[0];
|
||||
#endif
|
||||
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)
|
||||
{
|
||||
const int minLegalYear = 1950;
|
||||
// Write using DER to support the most readers.
|
||||
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Sending the DateTime through ToLocalTime here will cause the right normalization
|
||||
// of DateTimeKind.Unknown.
|
||||
//
|
||||
// Unknown => Local (adjust) => UTC (adjust "back", add Z marker; matches Windows)
|
||||
if (utcTime.Kind == DateTimeKind.Unspecified)
|
||||
{
|
||||
writer.WriteUtcTime(utcTime.ToLocalTime(), minLegalYear);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteUtcTime(utcTime, minLegalYear);
|
||||
}
|
||||
|
||||
return writer.Encode();
|
||||
}
|
||||
catch (ArgumentException ex)
|
||||
{
|
||||
throw new CryptographicException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// Windows compat.
|
||||
if (s_invalidEmptyOid.AsSpan().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)
|
||||
{
|
||||
AsnReader reader = new AsnReader(encodedMessage, AsnEncodingRules.BER);
|
||||
|
||||
ContentInfoAsn contentInfo = AsnSerializer.Deserialize<ContentInfoAsn>(
|
||||
reader.GetEncodedValue(),
|
||||
AsnEncodingRules.BER);
|
||||
|
||||
switch (contentInfo.ContentType)
|
||||
{
|
||||
case Oids.Pkcs7Data:
|
||||
case Oids.Pkcs7Signed:
|
||||
case Oids.Pkcs7Enveloped:
|
||||
case Oids.Pkcs7SignedEnveloped:
|
||||
case Oids.Pkcs7Hashed:
|
||||
case Oids.Pkcs7Encrypted:
|
||||
return new Oid(contentInfo.ContentType);
|
||||
}
|
||||
|
||||
throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
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;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
public override DecryptorPal Decode(
|
||||
byte[] encodedMessage,
|
||||
out int version,
|
||||
out ContentInfo contentInfo,
|
||||
out AlgorithmIdentifier contentEncryptionAlgorithm,
|
||||
out X509Certificate2Collection originatorCerts,
|
||||
out CryptographicAttributeObjectCollection unprotectedAttributes)
|
||||
{
|
||||
// Read using BER because the CMS specification says the encoding is BER.
|
||||
AsnReader reader = new AsnReader(encodedMessage, AsnEncodingRules.BER);
|
||||
|
||||
ContentInfoAsn parsedContentInfo = AsnSerializer.Deserialize<ContentInfoAsn>(
|
||||
reader.GetEncodedValue(),
|
||||
AsnEncodingRules.BER);
|
||||
|
||||
if (parsedContentInfo.ContentType != Oids.Pkcs7Enveloped)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
|
||||
}
|
||||
|
||||
byte[] copy = parsedContentInfo.Content.ToArray();
|
||||
|
||||
EnvelopedDataAsn data = AsnSerializer.Deserialize<EnvelopedDataAsn>(
|
||||
copy,
|
||||
AsnEncodingRules.BER);
|
||||
|
||||
version = data.Version;
|
||||
|
||||
contentInfo = new ContentInfo(
|
||||
new Oid(data.EncryptedContentInfo.ContentType),
|
||||
data.EncryptedContentInfo.EncryptedContent?.ToArray() ?? Array.Empty<byte>());
|
||||
|
||||
contentEncryptionAlgorithm =
|
||||
data.EncryptedContentInfo.ContentEncryptionAlgorithm.ToPresentationObject();
|
||||
|
||||
originatorCerts = new X509Certificate2Collection();
|
||||
|
||||
if (data.OriginatorInfo != null && data.OriginatorInfo.CertificateSet != null)
|
||||
{
|
||||
foreach (CertificateChoiceAsn certChoice in data.OriginatorInfo.CertificateSet)
|
||||
{
|
||||
if (certChoice.Certificate != null)
|
||||
{
|
||||
originatorCerts.Add(new X509Certificate2(certChoice.Certificate.Value.ToArray()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unprotectedAttributes = SignerInfo.MakeAttributeCollection(data.UnprotectedAttributes);
|
||||
|
||||
var recipientInfos = new List<RecipientInfo>();
|
||||
|
||||
foreach (RecipientInfoAsn recipientInfo in data.RecipientInfos)
|
||||
{
|
||||
if (recipientInfo.Ktri != null)
|
||||
{
|
||||
recipientInfos.Add(new KeyTransRecipientInfo(new ManagedKeyTransPal(recipientInfo.Ktri)));
|
||||
}
|
||||
else if (recipientInfo.Kari != null)
|
||||
{
|
||||
for (int i = 0; i < recipientInfo.Kari.RecipientEncryptedKeys.Length; i++)
|
||||
{
|
||||
recipientInfos.Add(
|
||||
new KeyAgreeRecipientInfo(new ManagedKeyAgreePal(recipientInfo.Kari, i)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Fail($"{nameof(RecipientInfoAsn)} deserialized with an unknown recipient type");
|
||||
throw new CryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
return new ManagedDecryptorPal(copy, data, new RecipientInfoCollection(recipientInfos));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
// 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.Pkcs.Asn1;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
private sealed class ManagedDecryptorPal : DecryptorPal
|
||||
{
|
||||
private byte[] _dataCopy;
|
||||
private EnvelopedDataAsn _envelopedData;
|
||||
|
||||
public ManagedDecryptorPal(
|
||||
byte[] dataCopy,
|
||||
EnvelopedDataAsn envelopedDataAsn,
|
||||
RecipientInfoCollection recipientInfos)
|
||||
: base(recipientInfos)
|
||||
{
|
||||
_dataCopy = dataCopy;
|
||||
_envelopedData = envelopedDataAsn;
|
||||
}
|
||||
|
||||
public override unsafe ContentInfo TryDecrypt(
|
||||
RecipientInfo recipientInfo,
|
||||
X509Certificate2 cert,
|
||||
X509Certificate2Collection originatorCerts,
|
||||
X509Certificate2Collection extraStore,
|
||||
out Exception exception)
|
||||
{
|
||||
// When encryptedContent is null Windows seems to decrypt the CEK first,
|
||||
// then return a 0 byte answer.
|
||||
|
||||
byte[] cek;
|
||||
|
||||
if (recipientInfo.Pal is ManagedKeyTransPal ktri)
|
||||
{
|
||||
cek = ktri.DecryptCek(cert, out exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
exception = new CryptographicException(
|
||||
SR.Cryptography_Cms_RecipientType_NotSupported,
|
||||
recipientInfo.Type.ToString());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] decrypted;
|
||||
|
||||
// Pin CEK to prevent it from getting copied during heap compaction.
|
||||
fixed (byte* pinnedCek = cek)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ReadOnlyMemory<byte>? encryptedContent = _envelopedData.EncryptedContentInfo.EncryptedContent;
|
||||
|
||||
if (encryptedContent == null)
|
||||
{
|
||||
exception = null;
|
||||
|
||||
return new ContentInfo(
|
||||
new Oid(_envelopedData.EncryptedContentInfo.ContentType),
|
||||
Array.Empty<byte>());
|
||||
}
|
||||
|
||||
decrypted = DecryptContent(encryptedContent.Value, cek, out exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cek != null)
|
||||
{
|
||||
Array.Clear(cek, 0, cek.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_envelopedData.EncryptedContentInfo.ContentType == Oids.Pkcs7Data)
|
||||
{
|
||||
byte[] tmp = null;
|
||||
|
||||
try
|
||||
{
|
||||
AsnReader reader = new AsnReader(decrypted, AsnEncodingRules.BER);
|
||||
|
||||
if (reader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> contents))
|
||||
{
|
||||
decrypted = contents.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = ArrayPool<byte>.Shared.Rent(decrypted.Length);
|
||||
|
||||
if (reader.TryCopyOctetStringBytes(tmp, out int written))
|
||||
{
|
||||
Span<byte> innerContents = new Span<byte>(tmp, 0, written);
|
||||
decrypted = innerContents.ToArray();
|
||||
innerContents.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Fail("Octet string grew during copy");
|
||||
// If this happens (which requires decrypted was overwritten, which
|
||||
// shouldn't be possible), just leave decrypted alone.
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (tmp != null)
|
||||
{
|
||||
// Already cleared
|
||||
ArrayPool<byte>.Shared.Return(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exception = null;
|
||||
return new ContentInfo(
|
||||
new Oid(_envelopedData.EncryptedContentInfo.ContentType),
|
||||
decrypted);
|
||||
}
|
||||
|
||||
private byte[] DecryptContent(ReadOnlyMemory<byte> encryptedContent, byte[] cek, out Exception exception)
|
||||
{
|
||||
exception = null;
|
||||
int encryptedContentLength = encryptedContent.Length;
|
||||
byte[] encryptedContentArray = ArrayPool<byte>.Shared.Rent(encryptedContentLength);
|
||||
|
||||
try
|
||||
{
|
||||
encryptedContent.CopyTo(encryptedContentArray);
|
||||
|
||||
AlgorithmIdentifierAsn contentEncryptionAlgorithm =
|
||||
_envelopedData.EncryptedContentInfo.ContentEncryptionAlgorithm;
|
||||
|
||||
using (SymmetricAlgorithm alg = OpenAlgorithm(contentEncryptionAlgorithm))
|
||||
using (ICryptoTransform decryptor = alg.CreateDecryptor(cek, alg.IV))
|
||||
{
|
||||
return decryptor.OneShot(
|
||||
encryptedContentArray,
|
||||
0,
|
||||
encryptedContentLength);
|
||||
}
|
||||
}
|
||||
catch (CryptographicException e)
|
||||
{
|
||||
exception = e;
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(encryptedContentArray, 0, encryptedContentLength);
|
||||
ArrayPool<byte>.Shared.Return(encryptedContentArray);
|
||||
encryptedContentArray = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
// 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.Collections.Generic;
|
||||
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;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
public override unsafe byte[] Encrypt(
|
||||
CmsRecipientCollection recipients,
|
||||
ContentInfo contentInfo,
|
||||
AlgorithmIdentifier contentEncryptionAlgorithm,
|
||||
X509Certificate2Collection originatorCerts,
|
||||
CryptographicAttributeObjectCollection unprotectedAttributes)
|
||||
{
|
||||
byte[] encryptedContent = EncryptContent(
|
||||
contentInfo,
|
||||
contentEncryptionAlgorithm,
|
||||
out byte[] cek,
|
||||
out byte[] parameterBytes);
|
||||
|
||||
// Pin the CEK to prevent it from getting copied during heap compaction.
|
||||
fixed (byte* pinnedCek = cek)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Encrypt(
|
||||
recipients,
|
||||
contentInfo,
|
||||
contentEncryptionAlgorithm,
|
||||
originatorCerts,
|
||||
unprotectedAttributes,
|
||||
encryptedContent,
|
||||
cek,
|
||||
parameterBytes);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Array.Clear(cek, 0, cek.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] Encrypt(
|
||||
CmsRecipientCollection recipients,
|
||||
ContentInfo contentInfo,
|
||||
AlgorithmIdentifier contentEncryptionAlgorithm,
|
||||
X509Certificate2Collection originatorCerts,
|
||||
CryptographicAttributeObjectCollection unprotectedAttributes,
|
||||
byte[] encryptedContent,
|
||||
byte[] cek,
|
||||
byte[] parameterBytes)
|
||||
{
|
||||
EnvelopedDataAsn envelopedData = new EnvelopedDataAsn
|
||||
{
|
||||
EncryptedContentInfo =
|
||||
{
|
||||
ContentType = contentInfo.ContentType.Value,
|
||||
|
||||
ContentEncryptionAlgorithm =
|
||||
{
|
||||
Algorithm = contentEncryptionAlgorithm.Oid,
|
||||
Parameters = parameterBytes,
|
||||
},
|
||||
|
||||
EncryptedContent = encryptedContent,
|
||||
},
|
||||
};
|
||||
|
||||
if (unprotectedAttributes != null && unprotectedAttributes.Count > 0)
|
||||
{
|
||||
List<AttributeAsn> attrList = CmsSigner.BuildAttributes(unprotectedAttributes);
|
||||
|
||||
envelopedData.UnprotectedAttributes = Helpers.NormalizeSet(attrList.ToArray());
|
||||
}
|
||||
|
||||
if (originatorCerts != null && originatorCerts.Count > 0)
|
||||
{
|
||||
CertificateChoiceAsn[] certs = new CertificateChoiceAsn[originatorCerts.Count];
|
||||
|
||||
for (int i = 0; i < originatorCerts.Count; i++)
|
||||
{
|
||||
certs[i].Certificate = originatorCerts[i].RawData;
|
||||
}
|
||||
|
||||
envelopedData.OriginatorInfo = new OriginatorInfoAsn
|
||||
{
|
||||
CertificateSet = certs,
|
||||
};
|
||||
}
|
||||
|
||||
envelopedData.RecipientInfos = new RecipientInfoAsn[recipients.Count];
|
||||
|
||||
bool allRecipientsVersion0 = true;
|
||||
|
||||
for (var i = 0; i < recipients.Count; i++)
|
||||
{
|
||||
CmsRecipient recipient = recipients[i];
|
||||
bool v0Recipient;
|
||||
|
||||
switch (recipient.Certificate.GetKeyAlgorithm())
|
||||
{
|
||||
case Oids.Rsa:
|
||||
envelopedData.RecipientInfos[i].Ktri = MakeKtri(cek, recipient, out v0Recipient);
|
||||
break;
|
||||
default:
|
||||
throw new CryptographicException(
|
||||
SR.Cryptography_Cms_UnknownAlgorithm,
|
||||
recipient.Certificate.GetKeyAlgorithm());
|
||||
}
|
||||
|
||||
allRecipientsVersion0 = allRecipientsVersion0 && v0Recipient;
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc5652#section-6.1
|
||||
//
|
||||
// v4 (RFC 3852):
|
||||
// * OriginatorInfo contains certificates with type other (not supported)
|
||||
// * OriginatorInfo contains crls with type other (not supported)
|
||||
// v3 (RFC 3369):
|
||||
// * OriginatorInfo contains v2 attribute certificates (not supported)
|
||||
// * Any PWRI (password) recipients are present (not supported)
|
||||
// * Any ORI (other) recipients are present (not supported)
|
||||
// v2 (RFC 2630):
|
||||
// * OriginatorInfo is present
|
||||
// * Any RecipientInfo has a non-zero version number
|
||||
// * UnprotectedAttrs is present
|
||||
// v1 (not defined for EnvelopedData)
|
||||
// v0 (RFC 2315):
|
||||
// * Anything not already matched
|
||||
|
||||
if (envelopedData.OriginatorInfo != null ||
|
||||
!allRecipientsVersion0 ||
|
||||
envelopedData.UnprotectedAttributes != null)
|
||||
{
|
||||
envelopedData.Version = 2;
|
||||
}
|
||||
|
||||
return Helpers.EncodeContentInfo(envelopedData, Oids.Pkcs7Enveloped);
|
||||
}
|
||||
|
||||
private byte[] EncryptContent(
|
||||
ContentInfo contentInfo,
|
||||
AlgorithmIdentifier contentEncryptionAlgorithm,
|
||||
out byte[] cek,
|
||||
out byte[] parameterBytes)
|
||||
{
|
||||
using (SymmetricAlgorithm alg = OpenAlgorithm(contentEncryptionAlgorithm))
|
||||
using (ICryptoTransform encryptor = alg.CreateEncryptor())
|
||||
{
|
||||
cek = alg.Key;
|
||||
|
||||
if (alg is RC2)
|
||||
{
|
||||
Rc2CbcParameters rc2Params = new Rc2CbcParameters(alg.IV, alg.KeySize);
|
||||
|
||||
using (AsnWriter writer = AsnSerializer.Serialize(rc2Params, AsnEncodingRules.DER))
|
||||
{
|
||||
parameterBytes = writer.Encode();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterBytes = EncodeOctetString(alg.IV);
|
||||
}
|
||||
|
||||
byte[] toEncrypt = contentInfo.Content;
|
||||
|
||||
if (contentInfo.ContentType.Value == Oids.Pkcs7Data)
|
||||
{
|
||||
toEncrypt = EncodeOctetString(toEncrypt);
|
||||
}
|
||||
|
||||
return encryptor.OneShot(toEncrypt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
public override Exception CreateRecipientsNotFoundException()
|
||||
{
|
||||
return new CryptographicException(SR.Cryptography_Cms_RecipientNotFound);
|
||||
}
|
||||
|
||||
public override Exception CreateRecipientInfosAfterEncryptException()
|
||||
{
|
||||
return CreateInvalidMessageTypeException();
|
||||
}
|
||||
|
||||
public override Exception CreateDecryptAfterEncryptException()
|
||||
{
|
||||
return CreateInvalidMessageTypeException();
|
||||
}
|
||||
|
||||
public override Exception CreateDecryptTwiceException()
|
||||
{
|
||||
return CreateInvalidMessageTypeException();
|
||||
}
|
||||
|
||||
private static Exception CreateInvalidMessageTypeException()
|
||||
{
|
||||
// Windows CRYPT_E_INVALID_MSG_TYPE
|
||||
return new CryptographicException(SR.Cryptography_Cms_InvalidMessageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.Pkcs;
|
||||
using System.Security.Cryptography.Pkcs.Asn1;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
private sealed class ManagedKeyAgreePal : KeyAgreeRecipientInfoPal
|
||||
{
|
||||
private readonly KeyAgreeRecipientInfoAsn _asn;
|
||||
private readonly int _index;
|
||||
|
||||
internal ManagedKeyAgreePal(KeyAgreeRecipientInfoAsn asn, int index)
|
||||
{
|
||||
_asn = asn;
|
||||
_index = index;
|
||||
}
|
||||
|
||||
public override byte[] EncryptedKey =>
|
||||
_asn.RecipientEncryptedKeys[_index].EncryptedKey.ToArray();
|
||||
|
||||
public override AlgorithmIdentifier KeyEncryptionAlgorithm =>
|
||||
_asn.KeyEncryptionAlgorithm.ToPresentationObject();
|
||||
|
||||
public override SubjectIdentifier RecipientIdentifier =>
|
||||
new SubjectIdentifier(
|
||||
_asn.RecipientEncryptedKeys[_index].Rid.IssuerAndSerialNumber,
|
||||
_asn.RecipientEncryptedKeys[_index].Rid.RKeyId?.SubjectKeyIdentifier);
|
||||
|
||||
public override int Version => _asn.Version;
|
||||
|
||||
public override DateTime Date
|
||||
{
|
||||
get
|
||||
{
|
||||
KeyAgreeRecipientIdentifierAsn rid = _asn.RecipientEncryptedKeys[_index].Rid;
|
||||
|
||||
if (rid.RKeyId == null)
|
||||
{
|
||||
throw new InvalidOperationException(SR.Cryptography_Cms_Key_Agree_Date_Not_Available);
|
||||
}
|
||||
|
||||
if (rid.RKeyId.Date == null)
|
||||
{
|
||||
// Compatibility with Windows/NetFX.
|
||||
return DateTime.FromFileTimeUtc(0);
|
||||
}
|
||||
|
||||
return rid.RKeyId.Date.Value.LocalDateTime;
|
||||
}
|
||||
}
|
||||
|
||||
public override SubjectIdentifierOrKey OriginatorIdentifierOrKey =>
|
||||
_asn.Originator.ToSubjectIdentifierOrKey();
|
||||
|
||||
public override CryptographicAttributeObject OtherKeyAttribute
|
||||
{
|
||||
get
|
||||
{
|
||||
KeyAgreeRecipientIdentifierAsn rid = _asn.RecipientEncryptedKeys[_index].Rid;
|
||||
|
||||
if (rid.RKeyId == null)
|
||||
{
|
||||
// Yes, "date" (Windows compat)
|
||||
throw new InvalidOperationException(SR.Cryptography_Cms_Key_Agree_Date_Not_Available);
|
||||
}
|
||||
|
||||
if (rid.RKeyId.Other == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Oid oid = new Oid(rid.RKeyId.Other.Value.KeyAttrId);
|
||||
byte[] rawData = Array.Empty<byte>();
|
||||
|
||||
if (rid.RKeyId.Other.Value.KeyAttr != null)
|
||||
{
|
||||
rawData = rid.RKeyId.Other.Value.KeyAttr.Value.ToArray();
|
||||
}
|
||||
|
||||
Pkcs9AttributeObject pkcs9AttributeObject = new Pkcs9AttributeObject(oid, rawData);
|
||||
AsnEncodedDataCollection values = new AsnEncodedDataCollection(pkcs9AttributeObject);
|
||||
return new CryptographicAttributeObject(oid, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
// 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.Pkcs;
|
||||
using System.Security.Cryptography.Pkcs.Asn1;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
private static readonly byte[] s_rsaPkcsParameters = { 0x05, 0x00 };
|
||||
private static readonly byte[] s_rsaOaepSha1Parameters = { 0x30, 0x00 };
|
||||
|
||||
private sealed class ManagedKeyTransPal : KeyTransRecipientInfoPal
|
||||
{
|
||||
private readonly KeyTransRecipientInfoAsn _asn;
|
||||
|
||||
internal ManagedKeyTransPal(KeyTransRecipientInfoAsn asn)
|
||||
{
|
||||
_asn = asn;
|
||||
}
|
||||
|
||||
public override byte[] EncryptedKey =>
|
||||
_asn.EncryptedKey.ToArray();
|
||||
|
||||
public override AlgorithmIdentifier KeyEncryptionAlgorithm =>
|
||||
_asn.KeyEncryptionAlgorithm.ToPresentationObject();
|
||||
|
||||
public override SubjectIdentifier RecipientIdentifier =>
|
||||
new SubjectIdentifier(_asn.Rid.IssuerAndSerialNumber, _asn.Rid.SubjectKeyIdentifier);
|
||||
|
||||
public override int Version => _asn.Version;
|
||||
|
||||
internal byte[] DecryptCek(X509Certificate2 cert, out Exception exception)
|
||||
{
|
||||
RSAEncryptionPadding encryptionPadding;
|
||||
ReadOnlyMemory<byte>? parameters = _asn.KeyEncryptionAlgorithm.Parameters;
|
||||
|
||||
switch (_asn.KeyEncryptionAlgorithm.Algorithm.Value)
|
||||
{
|
||||
case Oids.Rsa:
|
||||
if (parameters != null &&
|
||||
!parameters.Value.Span.SequenceEqual(s_rsaPkcsParameters))
|
||||
{
|
||||
exception = new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
return null;
|
||||
}
|
||||
|
||||
encryptionPadding = RSAEncryptionPadding.Pkcs1;
|
||||
break;
|
||||
case Oids.RsaOaep:
|
||||
if (parameters != null &&
|
||||
!parameters.Value.Span.SequenceEqual(s_rsaOaepSha1Parameters))
|
||||
{
|
||||
exception = new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
return null;
|
||||
}
|
||||
|
||||
encryptionPadding = RSAEncryptionPadding.OaepSHA1;
|
||||
break;
|
||||
default:
|
||||
exception = new CryptographicException(
|
||||
SR.Cryptography_Cms_UnknownAlgorithm,
|
||||
_asn.KeyEncryptionAlgorithm.Algorithm.Value);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] cek = null;
|
||||
int cekLength = 0;
|
||||
|
||||
try
|
||||
{
|
||||
using (RSA rsa = cert.GetRSAPrivateKey())
|
||||
{
|
||||
if (rsa == null)
|
||||
{
|
||||
exception = new CryptographicException(SR.Cryptography_Cms_Signing_RequiresPrivateKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
#if netcoreapp
|
||||
cek = ArrayPool<byte>.Shared.Rent(rsa.KeySize / 8);
|
||||
|
||||
if (!rsa.TryDecrypt(_asn.EncryptedKey.Span, cek, encryptionPadding, out cekLength))
|
||||
{
|
||||
Debug.Fail("TryDecrypt wanted more space than the key size");
|
||||
exception = new CryptographicException();
|
||||
return null;
|
||||
}
|
||||
|
||||
exception = null;
|
||||
return new Span<byte>(cek, 0, cekLength).ToArray();
|
||||
#else
|
||||
exception = null;
|
||||
return rsa.Decrypt(_asn.EncryptedKey.Span.ToArray(), encryptionPadding);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
catch (CryptographicException e)
|
||||
{
|
||||
exception = e;
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (cek != null)
|
||||
{
|
||||
Array.Clear(cek, 0, cekLength);
|
||||
ArrayPool<byte>.Shared.Return(cek);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static KeyTransRecipientInfoAsn MakeKtri(
|
||||
byte[] cek,
|
||||
CmsRecipient recipient,
|
||||
out bool v0Recipient)
|
||||
{
|
||||
KeyTransRecipientInfoAsn ktri = new KeyTransRecipientInfoAsn();
|
||||
|
||||
if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)
|
||||
{
|
||||
ktri.Version = 2;
|
||||
ktri.Rid.SubjectKeyIdentifier = recipient.Certificate.GetSubjectKeyIdentifier();
|
||||
}
|
||||
else if (recipient.RecipientIdentifierType == SubjectIdentifierType.IssuerAndSerialNumber)
|
||||
{
|
||||
byte[] serial = recipient.Certificate.GetSerialNumber();
|
||||
Array.Reverse(serial);
|
||||
|
||||
IssuerAndSerialNumberAsn iasn = new IssuerAndSerialNumberAsn
|
||||
{
|
||||
Issuer = recipient.Certificate.IssuerName.RawData,
|
||||
SerialNumber = serial,
|
||||
};
|
||||
|
||||
ktri.Rid.IssuerAndSerialNumber = iasn;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new CryptographicException(
|
||||
SR.Cryptography_Cms_Invalid_Subject_Identifier_Type,
|
||||
recipient.RecipientIdentifierType.ToString());
|
||||
}
|
||||
|
||||
RSAEncryptionPadding padding;
|
||||
|
||||
switch (recipient.Certificate.GetKeyAlgorithm())
|
||||
{
|
||||
case Oids.RsaOaep:
|
||||
padding = RSAEncryptionPadding.OaepSHA1;
|
||||
ktri.KeyEncryptionAlgorithm.Algorithm = new Oid(Oids.RsaOaep, Oids.RsaOaep);
|
||||
ktri.KeyEncryptionAlgorithm.Parameters = s_rsaOaepSha1Parameters;
|
||||
break;
|
||||
default:
|
||||
padding = RSAEncryptionPadding.Pkcs1;
|
||||
ktri.KeyEncryptionAlgorithm.Algorithm = new Oid(Oids.Rsa, Oids.Rsa);
|
||||
ktri.KeyEncryptionAlgorithm.Parameters = s_rsaPkcsParameters;
|
||||
break;
|
||||
}
|
||||
|
||||
using (RSA rsa = recipient.Certificate.GetRSAPublicKey())
|
||||
{
|
||||
ktri.EncryptedKey = rsa.Encrypt(cek, padding);
|
||||
}
|
||||
|
||||
v0Recipient = (ktri.Version == 0);
|
||||
return ktri;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
// 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;
|
||||
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;
|
||||
|
||||
namespace Internal.Cryptography.Pal.AnyOS
|
||||
{
|
||||
internal sealed partial class ManagedPkcsPal : PkcsPal
|
||||
{
|
||||
public override void AddCertsFromStoreForDecryption(X509Certificate2Collection certs)
|
||||
{
|
||||
certs.AddRange(Helpers.GetStoreCertificates(StoreName.My, StoreLocation.CurrentUser, openExistingOnly: false));
|
||||
|
||||
try
|
||||
{
|
||||
// This store exists on macOS, but not Linux
|
||||
certs.AddRange(
|
||||
Helpers.GetStoreCertificates(StoreName.My, StoreLocation.LocalMachine, openExistingOnly: false));
|
||||
}
|
||||
catch (CryptographicException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private static SymmetricAlgorithm OpenAlgorithm(AlgorithmIdentifierAsn contentEncryptionAlgorithm)
|
||||
{
|
||||
SymmetricAlgorithm alg = OpenAlgorithm(contentEncryptionAlgorithm.Algorithm);
|
||||
|
||||
if (alg is RC2)
|
||||
{
|
||||
if (contentEncryptionAlgorithm.Parameters == null)
|
||||
{
|
||||
// Windows issues CRYPT_E_BAD_DECODE
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
Rc2CbcParameters rc2Params = AsnSerializer.Deserialize<Rc2CbcParameters>(
|
||||
contentEncryptionAlgorithm.Parameters.Value,
|
||||
AsnEncodingRules.BER);
|
||||
|
||||
alg.KeySize = rc2Params.GetEffectiveKeyBits();
|
||||
alg.IV = rc2Params.Iv.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (contentEncryptionAlgorithm.Parameters == null)
|
||||
{
|
||||
// Windows issues CRYPT_E_BAD_DECODE
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
AsnReader reader = new AsnReader(contentEncryptionAlgorithm.Parameters.Value, AsnEncodingRules.BER);
|
||||
|
||||
if (reader.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> primitiveBytes))
|
||||
{
|
||||
alg.IV = primitiveBytes.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] iv = new byte[alg.BlockSize / 8];
|
||||
|
||||
if (!reader.TryCopyOctetStringBytes(iv, out int bytesWritten) ||
|
||||
bytesWritten != iv.Length)
|
||||
{
|
||||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
|
||||
alg.IV = iv;
|
||||
}
|
||||
}
|
||||
|
||||
return alg;
|
||||
}
|
||||
|
||||
private static SymmetricAlgorithm OpenAlgorithm(AlgorithmIdentifier algorithmIdentifier)
|
||||
{
|
||||
SymmetricAlgorithm alg = OpenAlgorithm(algorithmIdentifier.Oid);
|
||||
|
||||
if (alg is RC2)
|
||||
{
|
||||
if (algorithmIdentifier.KeyLength != 0)
|
||||
{
|
||||
alg.KeySize = algorithmIdentifier.KeyLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
alg.KeySize = KeyLengths.Rc2_128Bit;
|
||||
}
|
||||
}
|
||||
|
||||
return alg;
|
||||
}
|
||||
|
||||
private static SymmetricAlgorithm OpenAlgorithm(Oid algorithmIdentifier)
|
||||
{
|
||||
Debug.Assert(algorithmIdentifier != null);
|
||||
|
||||
SymmetricAlgorithm alg;
|
||||
|
||||
switch (algorithmIdentifier.Value)
|
||||
{
|
||||
case Oids.Rc2Cbc:
|
||||
#pragma warning disable CA5351
|
||||
alg = RC2.Create();
|
||||
#pragma warning restore CA5351
|
||||
break;
|
||||
case Oids.DesCbc:
|
||||
#pragma warning disable CA5351
|
||||
alg = DES.Create();
|
||||
#pragma warning restore CA5351
|
||||
break;
|
||||
case Oids.TripleDesCbc:
|
||||
#pragma warning disable CA5350
|
||||
alg = TripleDES.Create();
|
||||
#pragma warning restore CA5350
|
||||
break;
|
||||
case Oids.Aes128Cbc:
|
||||
alg = Aes.Create();
|
||||
alg.KeySize = 128;
|
||||
break;
|
||||
case Oids.Aes192Cbc:
|
||||
alg = Aes.Create();
|
||||
alg.KeySize = 192;
|
||||
break;
|
||||
case Oids.Aes256Cbc:
|
||||
alg = Aes.Create();
|
||||
alg.KeySize = 256;
|
||||
break;
|
||||
default:
|
||||
throw new CryptographicException(SR.Cryptography_Cms_UnknownAlgorithm, algorithmIdentifier.Value);
|
||||
}
|
||||
|
||||
// These are the defaults, but they're restated here for clarity.
|
||||
alg.Padding = PaddingMode.PKCS7;
|
||||
alg.Mode = CipherMode.CBC;
|
||||
return alg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,220 +2,12 @@
|
||||
// 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;
|
||||
using Internal.Cryptography.Pal.AnyOS;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
private static readonly PkcsPal s_instance = new ManagedPkcsPal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +359,7 @@ namespace Internal.Cryptography.Pal.Windows
|
||||
throw new CryptographicException();
|
||||
}
|
||||
|
||||
int provType = BinaryPrimitives.ReadMachineEndian<int>(stackSpan.Slice(0, size));
|
||||
int provType = MemoryMarshal.Read<int>(stackSpan.Slice(0, size));
|
||||
|
||||
size = stackSpan.Length;
|
||||
if (!Interop.Advapi32.CryptGetProvParam(handle, CryptProvParam.PP_KEYSET_TYPE, stackSpan, ref size))
|
||||
@@ -373,7 +373,7 @@ namespace Internal.Cryptography.Pal.Windows
|
||||
throw new CryptographicException();
|
||||
}
|
||||
|
||||
int keysetType = BinaryPrimitives.ReadMachineEndian<int>(stackSpan.Slice(0, size));
|
||||
int keysetType = MemoryMarshal.Read<int>(stackSpan.Slice(0, size));
|
||||
|
||||
// Only CRYPT_MACHINE_KEYSET is described as coming back, but be defensive.
|
||||
CspProviderFlags provFlags =
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# These members don't belong in netstandard reference because of type unification with netfx (the members are new in net472).
|
||||
MembersMustExist : Member 'System.Security.Cryptography.Pkcs.SignerInfo.GetSignature()' does not exist in the implementation but it does exist in the contract.
|
||||
MembersMustExist : Member 'System.Security.Cryptography.Pkcs.SignerInfo.SignatureAlgorithm.get()' does not exist in the implementation but it does exist in the contract.
|
||||
@@ -199,6 +199,12 @@
|
||||
<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_RecipientNotFound" xml:space="preserve">
|
||||
<value>The enveloped-data message does not contain the specified recipient.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_RecipientType_NotSupported" xml:space="preserve">
|
||||
<value>The recipient type '{0}' is not supported for encryption or decryption on this platform.</value>
|
||||
</data>
|
||||
<data name="Cryptography_Cms_Sign_Empty_Content" xml:space="preserve">
|
||||
<value>Cannot create CMS signature for empty content.</value>
|
||||
</data>
|
||||
@@ -244,6 +250,21 @@
|
||||
<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="Cryptography_TimestampReq_BadNonce" xml:space="preserve">
|
||||
<value>The response from the timestamping server did not match the request nonce.</value>
|
||||
</data>
|
||||
<data name="Cryptography_TimestampReq_BadResponse" xml:space="preserve">
|
||||
<value>The response from the timestamping server was not understood.</value>
|
||||
</data>
|
||||
<data name="Cryptography_TimestampReq_Failure" xml:space="preserve">
|
||||
<value>The timestamping server did not grant the request. The request status is '{0}' with failure info '{1}'.</value>
|
||||
</data>
|
||||
<data name="Cryptography_TimestampReq_NoCertFound" xml:space="preserve">
|
||||
<value>The timestamping request required the TSA certificate in the response, but it was not found.</value>
|
||||
</data>
|
||||
<data name="Cryptography_TimestampReq_UnexpectedCertFound" xml:space="preserve">
|
||||
<value>The timestamping request required the TSA certificate not be included in the response, but certificates were present.</value>
|
||||
</data>
|
||||
<data name="InvalidOperation_DuplicateItemNotAllowed" xml:space="preserve">
|
||||
<value>Duplicate items are not allowed in the collection.</value>
|
||||
</data>
|
||||
|
||||
@@ -175,7 +175,30 @@
|
||||
</ItemGroup>
|
||||
<!-- Internal types (platform: AnyOS) -->
|
||||
<ItemGroup Condition="'$(TargetsWindows)' != 'true' AND '$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\AsnHelpers.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.Asn.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.Decode.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.Decrypt.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.Encrypt.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.Exceptions.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.KeyAgree.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\ManagedPal.KeyTrans.cs" />
|
||||
<Compile Include="Internal\Cryptography\Pal\AnyOS\PkcsPal.AnyOS.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\EncryptedContentInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\EnvelopedDataAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\KeyAgreeRecipientIdentifierAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\KeyAgreeRecipientInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\KeyTransRecipientInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\OriginatorIdentifierOrKeyAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\OriginatorInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\OriginatorPublicKeyAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\OtherKeyAttributeAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\Rc2CbcParameters.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\RecipientEncryptedKeyAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\RecipientIdentifierAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\RecipientInfoAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\RecipientKeyIdentifier.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' == 'true'">
|
||||
<Reference Include="mscorlib" />
|
||||
@@ -225,11 +248,19 @@
|
||||
<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\GeneralName.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\IssuerAndSerialNumberAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\MessageImprint.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\PssParamsAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\Rfc3161Accuracy.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\Rfc3161TimeStampReq.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\Rfc3161TimeStampResp.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\Rfc3161TstInfo.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\Asn1\SigningCertificateAsn.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Asn1\X509ExtensionAsn.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" />
|
||||
@@ -242,6 +273,10 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp'">
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\CmsSignature.DSA.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Rfc3161RequestResponseStatus.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Rfc3161TimestampRequest.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Rfc3161TimestampToken.cs" />
|
||||
<Compile Include="System\Security\Cryptography\Pkcs\Rfc3161TimestampTokenInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user