Imported Upstream version 6.0.0.172

Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-04-12 14:10:50 +00:00
parent 8016999e4d
commit 64ac736ec5
32155 changed files with 3981439 additions and 75368 deletions

View File

@@ -2,7 +2,8 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.0.3.0</AssemblyVersion>
<AssemblyVersion>4.0.3.2</AssemblyVersion>
<PackageVersion>4.5.2</PackageVersion>
<AssemblyKey>MSFT</AssemblyKey>
</PropertyGroup>
</Project>
</Project>

View File

@@ -421,15 +421,6 @@ namespace Internal.Cryptography
}
}
internal static void DigestWriter(IncrementalHash hasher, AsnWriter writer)
{
#if netcoreapp
hasher.AppendData(writer.EncodeAsSpan());
#else
hasher.AppendData(writer.Encode());
#endif
}
internal static byte[] OneShot(this ICryptoTransform transform, byte[] data)
{
return OneShot(transform, data, 0, data.Length);

View File

@@ -19,6 +19,10 @@ namespace Internal.Cryptography
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 RsaPkcs1Sha1 = "1.2.840.113549.1.1.5";
public const string RsaPkcs1Sha256 = "1.2.840.113549.1.1.11";
public const string RsaPkcs1Sha384 = "1.2.840.113549.1.1.12";
public const string RsaPkcs1Sha512 = "1.2.840.113549.1.1.13";
public const string Esdh = "1.2.840.113549.1.9.16.3.5";
// Cryptographic Attribute Types

View File

@@ -136,6 +136,10 @@ namespace Internal.Cryptography.Pal.AnyOS
}
}
}
else
{
decrypted = GetAsnSequenceWithContentNoValidation(decrypted);
}
exception = null;
return new ContentInfo(
@@ -143,6 +147,23 @@ namespace Internal.Cryptography.Pal.AnyOS
decrypted);
}
private static byte[] GetAsnSequenceWithContentNoValidation(ReadOnlySpan<byte> content)
{
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.BER))
{
// Content may be invalid ASN.1 data.
// We will encode it as octet string to bypass validation
writer.WriteOctetString(content);
byte[] encoded = writer.Encode();
// and replace octet string tag (0x04) with sequence tag (0x30 or constructed 0x10)
Debug.Assert(encoded[0] == 0x04);
encoded[0] = 0x30;
return encoded;
}
}
private byte[] DecryptContent(ReadOnlyMemory<byte> encryptedContent, byte[] cek, out Exception exception)
{
exception = null;

View File

@@ -177,9 +177,20 @@ namespace Internal.Cryptography.Pal.AnyOS
if (contentInfo.ContentType.Value == Oids.Pkcs7Data)
{
toEncrypt = EncodeOctetString(toEncrypt);
return encryptor.OneShot(toEncrypt);
}
else
{
if (contentInfo.Content.Length == 0)
{
return encryptor.OneShot(contentInfo.Content);
}
else
{
AsnReader reader = new AsnReader(contentInfo.Content, AsnEncodingRules.BER);
return encryptor.OneShot(reader.PeekContentBytes().ToArray());
}
}
return encryptor.OneShot(toEncrypt);
}
}
}

View File

@@ -15,12 +15,13 @@ using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
using Microsoft.Win32.SafeHandles;
using static Interop.Crypt32;
using System.Security.Cryptography.Asn1;
namespace Internal.Cryptography.Pal.Windows
{
internal sealed partial class PkcsPalWindows : PkcsPal
{
public sealed override byte[] Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes)
public sealed unsafe override byte[] Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes)
{
using (SafeCryptMsgHandle hCryptMsg = EncodeHelpers.CreateCryptMsgHandleToEncode(recipients, contentInfo.ContentType, contentEncryptionAlgorithm, originatorCerts, unprotectedAttributes))
{
@@ -40,12 +41,33 @@ namespace Internal.Cryptography.Pal.Windows
else
{
encodedContent = contentInfo.Content;
if (encodedContent.Length > 0)
{
// Windows will throw if it encounters indefinite length encoding.
// Let's reencode if that is the case
ReencodeIfUsingIndefiniteLengthEncodingOnOuterStructure(ref encodedContent);
}
}
if (encodedContent.Length > 0)
{
if (!Interop.Crypt32.CryptMsgUpdate(hCryptMsg, encodedContent, encodedContent.Length, fFinal: true))
throw Marshal.GetLastWin32Error().ToCryptographicException();
// Pin to avoid copy during heap compaction
fixed (byte* pinnedContent = encodedContent)
{
try
{
if (!Interop.Crypt32.CryptMsgUpdate(hCryptMsg, encodedContent, encodedContent.Length, fFinal: true))
throw Marshal.GetLastWin32Error().ToCryptographicException();
}
finally
{
if (!object.ReferenceEquals(encodedContent, contentInfo.Content))
{
Array.Clear(encodedContent, 0, encodedContent.Length);
}
}
}
}
byte[] encodedMessage = hCryptMsg.GetMsgParamAsByteArray(CryptMsgParamType.CMSG_CONTENT_PARAM);
@@ -53,6 +75,25 @@ namespace Internal.Cryptography.Pal.Windows
}
}
private static void ReencodeIfUsingIndefiniteLengthEncodingOnOuterStructure(ref byte[] encodedContent)
{
AsnReader reader = new AsnReader(encodedContent, AsnEncodingRules.BER);
Asn1Tag tag = reader.ReadTagAndLength(out int? contentsLength, out int _);
if (contentsLength != null)
{
// definite length, do nothing
return;
}
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.BER))
{
// Tag doesn't matter here as we won't write it into the document
writer.WriteOctetString(reader.PeekContentBytes().Span);
encodedContent = writer.Encode();
}
}
//
// The methods in this class have some pretty terrifying contracts with each other regarding the lifetimes of the pointers they hand around so we'll encapsulate them in a nested class so that
// only the top level method is accessible to everyone else.

View File

@@ -35,9 +35,9 @@ namespace System.Security.Cryptography.Pkcs.Asn1
public AlgorithmIdentifierAsn DigestAlgorithm;
[ExpectedTag(0)]
[SetOf]
[OptionalValue]
public AttributeAsn[] SignedAttributes;
[AnyValue]
public ReadOnlyMemory<byte>? SignedAttributes;
public AlgorithmIdentifierAsn SignatureAlgorithm;
@@ -49,4 +49,16 @@ namespace System.Security.Cryptography.Pkcs.Asn1
[OptionalValue]
public AttributeAsn[] UnsignedAttributes;
}
// This type is not properly from the ASN module, but it exists to allow for
// deserialization on demand of the signed attributes, so the deserialization
// and reserialization process does not modify the contents of the signed
// attributes.
[Choice]
internal struct SignedAttributesSet
{
[ExpectedTag(0)]
[SetOf]
public AttributeAsn[] SignedAttributes;
}
}

View File

@@ -15,12 +15,25 @@ namespace System.Security.Cryptography.Pkcs
{
static partial void PrepareRegistrationRsa(Dictionary<string, CmsSignature> lookup)
{
lookup.Add(Oids.Rsa, new RSAPkcs1CmsSignature());
lookup.Add(Oids.Rsa, new RSAPkcs1CmsSignature(null, null));
lookup.Add(Oids.RsaPkcs1Sha1, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha1, HashAlgorithmName.SHA1));
lookup.Add(Oids.RsaPkcs1Sha256, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha256, HashAlgorithmName.SHA256));
lookup.Add(Oids.RsaPkcs1Sha384, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha384, HashAlgorithmName.SHA384));
lookup.Add(Oids.RsaPkcs1Sha512, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha512, HashAlgorithmName.SHA512));
lookup.Add(Oids.RsaPss, new RSAPssCmsSignature());
}
private abstract class RSACmsSignature : CmsSignature
{
private readonly string _signatureAlgorithm;
private readonly HashAlgorithmName? _expectedDigest;
protected RSACmsSignature(string signatureAlgorithm, HashAlgorithmName? expectedDigest)
{
_signatureAlgorithm = signatureAlgorithm;
_expectedDigest = expectedDigest;
}
internal override bool VerifySignature(
#if netcoreapp
ReadOnlySpan<byte> valueHash,
@@ -34,6 +47,15 @@ namespace System.Security.Cryptography.Pkcs
ReadOnlyMemory<byte>? signatureParameters,
X509Certificate2 certificate)
{
if (_expectedDigest.HasValue && _expectedDigest.Value != digestAlgorithmName)
{
throw new CryptographicException(
SR.Format(
SR.Cryptography_Cms_InvalidSignerHashForSignatureAlg,
digestAlgorithmOid,
_signatureAlgorithm));
}
RSASignaturePadding padding = GetSignaturePadding(
signatureParameters,
digestAlgorithmOid,
@@ -67,6 +89,11 @@ namespace System.Security.Cryptography.Pkcs
private sealed class RSAPkcs1CmsSignature : RSACmsSignature
{
public RSAPkcs1CmsSignature(string signatureAlgorithm, HashAlgorithmName? expectedDigest)
: base(signatureAlgorithm, expectedDigest)
{
}
protected override RSASignaturePadding GetSignaturePadding(
ReadOnlyMemory<byte>? signatureParameters,
string digestAlgorithmOid,
@@ -147,6 +174,10 @@ namespace System.Security.Cryptography.Pkcs
private class RSAPssCmsSignature : RSACmsSignature
{
public RSAPssCmsSignature() : base(null, null)
{
}
protected override RSASignaturePadding GetSignaturePadding(
ReadOnlyMemory<byte>? signatureParameters,
string digestAlgorithmOid,

View File

@@ -168,7 +168,8 @@ namespace System.Security.Cryptography.Pkcs
}
// Use the serializer/deserializer to DER-normalize the attribute order.
newSignerInfo.SignedAttributes = Helpers.NormalizeSet(
SignedAttributesSet signedAttrsSet = new SignedAttributesSet();
signedAttrsSet.SignedAttributes = Helpers.NormalizeSet(
signedAttrs.ToArray(),
normalized =>
{
@@ -176,6 +177,14 @@ namespace System.Security.Cryptography.Pkcs
hasher.AppendData(reader.PeekContentBytes().Span);
});
// Since this contains user data in a context where BER is permitted, use BER.
// There shouldn't be any observable difference here between BER and DER, though,
// since the top level fields were written by NormalizeSet.
using (AsnWriter attrsWriter = AsnSerializer.Serialize(signedAttrsSet, AsnEncodingRules.BER))
{
newSignerInfo.SignedAttributes = attrsWriter.Encode();
}
dataHash = hasher.GetHashAndReset();
}

View File

@@ -250,6 +250,39 @@ namespace System.Security.Cryptography.Pkcs
bool requestSignerCertificates = false,
X509ExtensionCollection extensions = null)
{
// Normalize the nonce:
if (nonce.HasValue)
{
ReadOnlyMemory<byte> nonceMemory = nonce.Value;
ReadOnlySpan<byte> nonceSpan = nonceMemory.Span;
// If it's empty, or it would be negative, insert the requisite byte.
if (nonceSpan.Length == 0 || nonceSpan[0] >= 0x80)
{
byte[] temp = new byte[nonceSpan.Length + 1];
nonceSpan.CopyTo(temp.AsSpan(1));
nonce = temp;
}
else
{
int slice = 0;
// Find all extra leading 0x00 values and trim them off.
while (slice < nonceSpan.Length && nonceSpan[slice] == 0)
{
slice++;
}
// Back up one if it was all zero, or we turned the number negative.
if (slice == nonceSpan.Length || nonceSpan[slice] >= 0x80)
{
slice--;
}
nonce = nonceMemory.Slice(slice);
}
}
var req = new Rfc3161TimeStampReq
{
Version = 1,

View File

@@ -104,7 +104,38 @@ namespace System.Security.Cryptography.Pkcs
throw new InvalidOperationException(SR.Cryptography_Cms_MessageNotSigned);
}
return Helpers.EncodeContentInfo(_signedData, Oids.Pkcs7Signed);
try
{
return Helpers.EncodeContentInfo(_signedData, Oids.Pkcs7Signed);
}
catch (CryptographicException)
{
if (Detached)
{
throw;
}
// If we can't write the contents back out then the most likely culprit is an
// indefinite length encoding in the content field. To preserve as much input data
// as possible while still maintaining our expectations of sorting any SET OF values,
// do the following:
// * Write the DER normalized version of the SignedData in detached mode.
// * BER-decode that structure
// * Copy the content field over
// * BER-write the modified structure.
SignedDataAsn copy = _signedData;
copy.EncapContentInfo.Content = null;
Debug.Assert(_signedData.EncapContentInfo.Content != null);
using (AsnWriter detachedWriter = AsnSerializer.Serialize(copy, AsnEncodingRules.DER))
{
copy = AsnSerializer.Deserialize<SignedDataAsn>(detachedWriter.Encode(), AsnEncodingRules.BER);
}
copy.EncapContentInfo.Content = _signedData.EncapContentInfo.Content;
return Helpers.EncodeContentInfo(copy, Oids.Pkcs7Signed, AsnEncodingRules.BER);
}
}
public void Decode(byte[] encodedMessage)
@@ -207,8 +238,12 @@ namespace System.Security.Cryptography.Pkcs
return rented.AsSpan(0, bytesWritten).ToArray();
}
catch (Exception) when (contentType != Oids.Pkcs7Data)
catch (Exception)
{
if (contentType == Oids.Pkcs7Data)
{
throw;
}
}
finally
{

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography.Asn1;
using System.Security.Cryptography.Pkcs.Asn1;
@@ -20,6 +21,7 @@ namespace System.Security.Cryptography.Pkcs
private readonly Oid _digestAlgorithm;
private readonly AttributeAsn[] _signedAttributes;
private readonly ReadOnlyMemory<byte>? _signedAttributesMemory;
private readonly Oid _signatureAlgorithm;
private readonly ReadOnlyMemory<byte>? _signatureAlgorithmParameters;
private readonly ReadOnlyMemory<byte> _signature;
@@ -36,12 +38,22 @@ namespace System.Security.Cryptography.Pkcs
Version = parsedData.Version;
SignerIdentifier = new SubjectIdentifier(parsedData.Sid);
_digestAlgorithm = parsedData.DigestAlgorithm.Algorithm;
_signedAttributes = parsedData.SignedAttributes;
_signedAttributesMemory = parsedData.SignedAttributes;
_signatureAlgorithm = parsedData.SignatureAlgorithm.Algorithm;
_signatureAlgorithmParameters = parsedData.SignatureAlgorithm.Parameters;
_signature = parsedData.SignatureValue;
_unsignedAttributes = parsedData.UnsignedAttributes;
if (_signedAttributesMemory.HasValue)
{
SignedAttributesSet signedSet = AsnSerializer.Deserialize<SignedAttributesSet>(
_signedAttributesMemory.Value,
AsnEncodingRules.BER);
_signedAttributes = signedSet.SignedAttributes;
Debug.Assert(_signedAttributes != null);
}
_document = ownerDocument;
}
@@ -385,15 +397,27 @@ namespace System.Security.Cryptography.Pkcs
public void CheckHash()
{
IncrementalHash hasher = PrepareDigest();
byte[] expectedSignature = hasher.GetHashAndReset();
if (!_signature.Span.SequenceEqual(expectedSignature))
if (!CheckHash(compatMode: false) && !CheckHash(compatMode: true))
{
throw new CryptographicException(SR.Cryptography_BadSignature);
}
}
private bool CheckHash(bool compatMode)
{
using (IncrementalHash hasher = PrepareDigest(compatMode))
{
if (hasher == null)
{
Debug.Assert(compatMode, $"{nameof(PrepareDigest)} returned null for the primary check");
return false;
}
byte[] expectedSignature = hasher.GetHashAndReset();
return _signature.Span.SequenceEqual(expectedSignature);
}
}
private X509Certificate2 FindSignerCertificate()
{
return FindSignerCertificate(SignerIdentifier, _document.Certificates);
@@ -456,7 +480,7 @@ namespace System.Security.Cryptography.Pkcs
return match;
}
private IncrementalHash PrepareDigest()
private IncrementalHash PrepareDigest(bool compatMode)
{
HashAlgorithmName hashAlgorithmName = GetDigestAlgorithm();
@@ -500,7 +524,19 @@ namespace System.Security.Cryptography.Pkcs
using (AsnWriter writer = new AsnWriter(AsnEncodingRules.DER))
{
writer.PushSetOf();
// Some CMS implementations exist which do not sort the attributes prior to
// generating the signature. While they are not, technically, validly signed,
// Windows and OpenSSL both support trying in the document order rather than
// a sorted order. To accomplish this we will build as a SEQUENCE OF, but feed
// the SET OF into the hasher.
if (compatMode)
{
writer.PushSequence();
}
else
{
writer.PushSetOf();
}
foreach (AttributeAsn attr in _signedAttributes)
{
@@ -529,10 +565,39 @@ namespace System.Security.Cryptography.Pkcs
}
}
writer.PopSetOf();
Helpers.DigestWriter(hasher, writer);
if (compatMode)
{
writer.PopSequence();
#if netcoreapp
Span<byte> setOfTag = stackalloc byte[1];
setOfTag[0] = 0x31;
hasher.AppendData(setOfTag);
hasher.AppendData(writer.EncodeAsSpan().Slice(1));
#else
byte[] encoded = writer.Encode();
encoded[0] = 0x31;
hasher.AppendData(encoded);
#endif
}
else
{
writer.PopSetOf();
#if netcoreapp
hasher.AppendData(writer.EncodeAsSpan());
#else
hasher.AppendData(writer.Encode());
#endif
}
}
}
else if (compatMode)
{
// If there were no signed attributes there's nothing to be compatible about.
return null;
}
if (invalid)
{
@@ -547,7 +612,6 @@ namespace System.Security.Cryptography.Pkcs
X509Certificate2 certificate,
bool verifySignatureOnly)
{
IncrementalHash hasher = PrepareDigest();
CmsSignature signatureProcessor = CmsSignature.Resolve(SignatureAlgorithm.Value);
if (signatureProcessor == null)
@@ -555,32 +619,9 @@ namespace System.Security.Cryptography.Pkcs
throw new CryptographicException(SR.Cryptography_Cms_UnknownAlgorithm, SignatureAlgorithm.Value);
}
#if netcoreapp
// SHA-2-512 is the biggest digest type we know about.
Span<byte> digestValue = stackalloc byte[512 / 8];
ReadOnlySpan<byte> digest = digestValue;
ReadOnlyMemory<byte> signature = _signature;
if (hasher.TryGetHashAndReset(digestValue, out int bytesWritten))
{
digest = digestValue.Slice(0, bytesWritten);
}
else
{
digest = hasher.GetHashAndReset();
}
#else
byte[] digest = hasher.GetHashAndReset();
byte[] signature = _signature.ToArray();
#endif
bool signatureValid = signatureProcessor.VerifySignature(
digest,
signature,
DigestAlgorithm.Value,
hasher.AlgorithmName,
_signatureAlgorithmParameters,
certificate);
bool signatureValid =
VerifySignature(signatureProcessor, certificate, compatMode: false) ||
VerifySignature(signatureProcessor, certificate, compatMode: true);
if (!signatureValid)
{
@@ -624,6 +665,48 @@ namespace System.Security.Cryptography.Pkcs
}
}
private bool VerifySignature(
CmsSignature signatureProcessor,
X509Certificate2 certificate,
bool compatMode)
{
using (IncrementalHash hasher = PrepareDigest(compatMode))
{
if (hasher == null)
{
Debug.Assert(compatMode, $"{nameof(PrepareDigest)} returned null for the primary check");
return false;
}
#if netcoreapp
// SHA-2-512 is the biggest digest type we know about.
Span<byte> digestValue = stackalloc byte[512 / 8];
ReadOnlySpan<byte> digest = digestValue;
ReadOnlyMemory<byte> signature = _signature;
if (hasher.TryGetHashAndReset(digestValue, out int bytesWritten))
{
digest = digestValue.Slice(0, bytesWritten);
}
else
{
digest = hasher.GetHashAndReset();
}
#else
byte[] digest = hasher.GetHashAndReset();
byte[] signature = _signature.ToArray();
#endif
return signatureProcessor.VerifySignature(
digest,
signature,
DigestAlgorithm.Value,
hasher.AlgorithmName,
_signatureAlgorithmParameters,
certificate);
}
}
private HashAlgorithmName GetDigestAlgorithm()
{
return Helpers.GetDigestAlgorithm(DigestAlgorithm.Value);

View File

@@ -1 +1 @@
b19fad719d04d44b34744aaa09c0b81b2e3a59ae
f8ff3af854c0c0981dc1869bb00b9822ea08c66e

View File

@@ -14,6 +14,7 @@ namespace System.Security.Cryptography.Pkcs.EnvelopedCmsTests.Tests
public static partial class DecryptTests
{
public static bool SupportsCngCertificates { get; } = (!PlatformDetection.IsFullFramework || PlatformDetection.IsNetfx462OrNewer);
public static bool SupportsIndefiniteLengthEncoding { get; } = !PlatformDetection.IsFullFramework;
[ConditionalFact(nameof(SupportsCngCertificates))]
[OuterLoop(/* Leaks key on disk if interrupted */)]
@@ -241,6 +242,47 @@ namespace System.Security.Cryptography.Pkcs.EnvelopedCmsTests.Tests
Assert.Equal<byte>(content, contentInfo.Content);
}
[Fact]
public static void EncryptToNegativeSerialNumber()
{
CertLoader negativeSerial = Certificates.NegativeSerialNumber;
const string expectedSerial = "FD319CB1514B06AF49E00522277E43C8";
byte[] content = { 1, 2, 3 };
ContentInfo contentInfo = new ContentInfo(content);
EnvelopedCms cms = new EnvelopedCms(contentInfo);
using (X509Certificate2 cert = negativeSerial.GetCertificate())
{
Assert.Equal(expectedSerial, cert.SerialNumber);
CmsRecipient recipient = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, cert);
cms.Encrypt(recipient);
}
EnvelopedCms cms2 = new EnvelopedCms();
cms2.Decode(cms.Encode());
RecipientInfoCollection recipients = cms2.RecipientInfos;
Assert.Equal(1, recipients.Count);
RecipientInfo recipientInfo = recipients[0];
Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, recipientInfo.RecipientIdentifier.Type);
X509IssuerSerial issuerSerial = (X509IssuerSerial)recipientInfo.RecipientIdentifier.Value;
Assert.Equal(expectedSerial, issuerSerial.SerialNumber);
using (X509Certificate2 cert = negativeSerial.TryGetCertificateWithPrivateKey())
{
Assert.Equal(expectedSerial, cert.SerialNumber);
cms2.Decrypt(new X509Certificate2Collection(cert));
}
Assert.Equal(content, cms2.ContentInfo.Content);
}
[Fact]
[OuterLoop(/* Leaks key on disk if interrupted */)]
public static void TestDecryptSimpleAes128_IssuerAndSerial()
@@ -464,14 +506,228 @@ namespace System.Security.Cryptography.Pkcs.EnvelopedCmsTests.Tests
VerifySimpleDecrypt(encryptedMessage, certLoader, expectedContentInfo);
}
private static void TestSimpleDecrypt_RoundTrip(CertLoader certLoader, ContentInfo contentInfo, string algorithmOidValue, SubjectIdentifierType type)
[Fact]
[OuterLoop(/* Leaks key on disk if interrupted */)]
public static void TestDecryptSimple_Pkcs7Signed_GeneratedOnWindows()
{
byte[] expectedContent =
("3082032506092a864886f70d010702a082031630820312020101310b300906052b0e03021a0500301206092a864886f70d01"
+ "0701a0050403010203a08202103082020c30820179a00302010202105d2ffff863babc9b4d3c80ab178a4cca300906052b0e"
+ "03021d0500301e311c301a060355040313135253414b65795472616e736665724361706931301e170d313530343135303730"
+ "3030305a170d3235303431353037303030305a301e311c301a060355040313135253414b65795472616e7366657243617069"
+ "3130819f300d06092a864886f70d010101050003818d0030818902818100aa272700586c0cc41b05c65c7d846f5a2bc27b03"
+ "e301c37d9bff6d75b6eb6671ba9596c5c63ba2b1af5c318d9ca39e7400d10c238ac72630579211b86570d1a1d44ec86aa8f6"
+ "c9d2b4e283ea3535923f398a312a23eaeacd8d34faaca965cd910b37da4093ef76c13b337c1afab7d1d07e317b41a336baa4"
+ "111299f99424408d0203010001a3533051304f0603551d0104483046801015432db116b35d07e4ba89edb2469d7aa120301e"
+ "311c301a060355040313135253414b65795472616e73666572436170693182105d2ffff863babc9b4d3c80ab178a4cca3009"
+ "06052b0e03021d05000381810081e5535d8eceef265acbc82f6c5f8bc9d84319265f3ccf23369fa533c8dc1938952c593166"
+ "2d9ecd8b1e7b81749e48468167e2fce3d019fa70d54646975b6dc2a3ba72d5a5274c1866da6d7a5df47938e034a075d11957"
+ "d653b5c78e5291e4401045576f6d4eda81bef3c369af56121e49a083c8d1adb09f291822e99a4296463181d73081d4020101"
+ "3032301e311c301a060355040313135253414b65795472616e73666572436170693102105d2ffff863babc9b4d3c80ab178a"
+ "4cca300906052b0e03021a0500300d06092a864886f70d010101050004818031a718ea1483c88494661e1d3dedfea0a3d97e"
+ "eb64c3e093a628b257c0cfc183ecf11697ac84f2af882b8de0c793572af38dc15d1b6f3d8f2392ba1cc71210e177c146fd16"
+ "b77a583b6411e801d7a2640d612f2fe99d87e9718e0e505a7ab9536d71dbde329da21816ce7da1416a74a3e0a112b86b33af"
+ "336a2ba6ae2443d0ab").HexToByteArray();
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Signed), expectedContent);
byte[] encodedMessage = Convert.FromBase64String(
"MIIERwYJKoZIhvcNAQcDoIIEODCCBDQCAQAxgcwwgckCAQAwMjAeMRwwGgYDVQQDExNSU0FLZXlU" +
"cmFuc2ZlckNhcGkxAhBdL//4Y7q8m008gKsXikzKMA0GCSqGSIb3DQEBAQUABIGAngdmU69zGsgJ" +
"mx+hXmTjlefr1oazKRK8VGOeqNMm++J3yHxwz68CLoN4FIEyS/HE3NQE6qb3M80HOpk5fmVVMw7Z" +
"3mrsZlPLOEjJIxEFqAC/JFEzvyE/BL+1OvwRoHpxHsAvZNlz5f9g18wQVE7X5TkkbOJV/6F2disK" +
"H0jik68wggNeBgkqhkiG9w0BBwIwHQYJYIZIAWUDBAEqBBDr3I8NYAnetX+2h9D/nVAggIIDMOlW" +
"7mDuuScuXhCXgZaPy0/zEWy/sYDzxhj1G1X2qBwhB7m6Ez6giibAEYwfRNYaOiVIitIJAUU9LSKg" +
"n0FL1o0eCcgvo04w+zoaBH8pFFk78kuR+T73kflz+O3Eno1pIFpy+2cz2B0QvQSC7lYikbZ4J+/C" +
"7F/uqRoK7sdafNdyUnKhDL+vvP6ToGf9C4g0TjoFEC2ycyJxIBh1F57pqjht6HMQcYm+/fQoBtkt" +
"NrvZxJPlBhbQad/9pSCd0G6NDoPnDuFAicaxGVa7yI2BbvGTCc6NSnbdCzv2EgvsI10Yko+XO4/i" +
"oPnk9pquZBzC3p61XRKbBDrd5RsbkvPDXUHJKD5NQ3W3z9Bnc3bjNyilgDSIB01dE4AcWzdg+RGb" +
"TA7iAbAQKp2zjxb/prmxw1mhO9g6OkDovSTqmQQt7MlHFYFcX9wH8yEe+huIechmiy7famofluJX" +
"vBIz4m3JozlodyNX0nu9QwW58WWcFu6OyoPjFhlB+tLIHUElq9/AAEgwwgfsAj6jEQaHiFG+CYSJ" +
"RjX9+DHFJXMDyzW+eJw8Z/mvbZzzKF553xlAGpfUHHq4CywTyVTHn4nu9HPOeFzoirj1lzFvqmQd" +
"Dgp3T8NOPrns9ZIUBmdNNs/vUxNZqEeN4d0nD5lBG4aZnjsxr4i25rR3Jpe3kKrFtJQ74efkRM37" +
"1ntz9HGiA95G41fuaMw7lgOOfTL+AENNvwRGRCAhinajvQLDkFEuX5ErTtmBxJWU3ZET46u/vRiK" +
"NiRteFiN0hLv1jy+RJK+d+B/QEH3FeVMm3Tz5ll2LfO2nn/QR51hth7qFsvtFpwQqkkhMac6dMf/" +
"bb62pZY15U3y2x5jSn+MZVrNbL4ZK/JO5JFomqKVRjLH1/IZ+kuFNaaTrKFWB4U2gxrMdcjMCZvx" +
"ylbuf01Ajxo74KhPY9sIRztG4BU8ZaE69Ke50wJTE3ulm+g6hzNECdQS/yjuA8AUReGRj2NH/U4M" +
"lEUiR/rMHB/Mq/Vj6lsRFEVxHJSzek6jvrQ4UzVgWGrH4KnP3Rca8CfBTQX79RcZPu+0kI3KI+4H" +
"0Q+UBbb72FHnWsw3uqPEyA==");
CertLoader certLoader = Certificates.RSAKeyTransferCapi1;
VerifySimpleDecrypt(encodedMessage, certLoader, expectedContentInfo);
}
[Fact]
[OuterLoop(/* Leaks key on disk if interrupted */)]
public static void TestDecryptSimple_Pkcs7Signed_GeneratedOnLinux()
{
byte[] expectedContent =
("3082032506092a864886f70d010702a082031630820312020101310b300906052b0e03021a0500301206092a864886f70d01"
+ "0701a0050403010203a08202103082020c30820179a00302010202105d2ffff863babc9b4d3c80ab178a4cca300906052b0e"
+ "03021d0500301e311c301a060355040313135253414b65795472616e736665724361706931301e170d313530343135303730"
+ "3030305a170d3235303431353037303030305a301e311c301a060355040313135253414b65795472616e7366657243617069"
+ "3130819f300d06092a864886f70d010101050003818d0030818902818100aa272700586c0cc41b05c65c7d846f5a2bc27b03"
+ "e301c37d9bff6d75b6eb6671ba9596c5c63ba2b1af5c318d9ca39e7400d10c238ac72630579211b86570d1a1d44ec86aa8f6"
+ "c9d2b4e283ea3535923f398a312a23eaeacd8d34faaca965cd910b37da4093ef76c13b337c1afab7d1d07e317b41a336baa4"
+ "111299f99424408d0203010001a3533051304f0603551d0104483046801015432db116b35d07e4ba89edb2469d7aa120301e"
+ "311c301a060355040313135253414b65795472616e73666572436170693182105d2ffff863babc9b4d3c80ab178a4cca3009"
+ "06052b0e03021d05000381810081e5535d8eceef265acbc82f6c5f8bc9d84319265f3ccf23369fa533c8dc1938952c593166"
+ "2d9ecd8b1e7b81749e48468167e2fce3d019fa70d54646975b6dc2a3ba72d5a5274c1866da6d7a5df47938e034a075d11957"
+ "d653b5c78e5291e4401045576f6d4eda81bef3c369af56121e49a083c8d1adb09f291822e99a4296463181d73081d4020101"
+ "3032301e311c301a060355040313135253414b65795472616e73666572436170693102105d2ffff863babc9b4d3c80ab178a"
+ "4cca300906052b0e03021a0500300d06092a864886f70d010101050004818031a718ea1483c88494661e1d3dedfea0a3d97e"
+ "eb64c3e093a628b257c0cfc183ecf11697ac84f2af882b8de0c793572af38dc15d1b6f3d8f2392ba1cc71210e177c146fd16"
+ "b77a583b6411e801d7a2640d612f2fe99d87e9718e0e505a7ab9536d71dbde329da21816ce7da1416a74a3e0a112b86b33af"
+ "336a2ba6ae2443d0ab").HexToByteArray();
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Signed), expectedContent);
byte[] encodedMessage = Convert.FromBase64String(
"MIIERwYJKoZIhvcNAQcDoIIEODCCBDQCAQAxgcwwgckCAQAwMjAeMRwwGgYDVQQDExNSU0FLZXlU" +
"cmFuc2ZlckNhcGkxAhBdL//4Y7q8m008gKsXikzKMA0GCSqGSIb3DQEBAQUABIGAfsH5F4ZlwIcH" +
"nzqn8sOn+ZwK884en7HZrQbgEfedy5ti0ituKn70yTDz4iuNJtpguukCfCAsOT/n3eQn+T6etIa9" +
"byRGQst3F6QtgjAzdb5P1N6c5Mpz1o6k0mbNP/f0FqAaNtuAOnYwlEMwWOz9x4eEYpOhhlc6agRG" +
"qWItNVgwggNeBgkqhkiG9w0BBwIwHQYJYIZIAWUDBAEqBBCA8qaTiT+6IkrO8Ks9WOBggIIDMIkr" +
"7OGlPd3CfzO2CfJA3Sis/1ulDm1ioMCS9V5kLHVx4GWDETORG/YTPA54luxJkvIdU5VwO86+QuXf" +
"rgaly38XHTLZv+RBxUwCaWI0pgvaykEki5CnDu4j9uRQxqz6iU5bY6SKxG3bwcnUzGhWFdQVcNJn" +
"xzuMEcbrix5zfqmoeqemaYyqVqgMPNOnc5kmMOqHrha76qMdbYOSpwx81zYwstBlg+S9+AgOMR+W" +
"qrV9aXJTovjiJEVHPEPJFx0v/wCthhXso51mSU091Cs8qVfvokzlzXcK2dPF5d8EdmZCcmHsoq35" +
"/DfAL4DkfKucwiP9W7rT1a2BmVMquFTMI+KXyDvNhMVasjhKq5eM2G+oUDc3kGa3akaPZ+hNEHA+" +
"BNAS7iIpRft2GMNfTqpkBqnS6pB0+SSf02/JVkcFuHXZ9oZJsvZRm8M1i4WdVauBJ34rInQBdhaO" +
"yaFDx69tBvolclYnMzvdHLiP2TZbiR6kM0vqD1DGjEHNDE+m/jxL7HXcNotW84J9CWlDnm9zaNhL" +
"sB4PJNiNjKhkAsO+2HaNWlEPrmgmWKvNi/Qyrz1qUryqz2/2HGrFDqmjTeEf1+yy35N3Pqv5uvAj" +
"f/ySihknnAh77nI0yOPy0Uto+hbO+xraeujrEifaII8izcz6UG6LHNPxOyscne7HNcqPSAFLsNFJ" +
"1oOlKO0SwhPkGQsk4W5tjVfvLvJiPNcL7SY/eof4vVsRRwX6Op5WUjhJIagY1Vij+4hOcn5TqdmU" +
"OZDh/FC3x4DI556BeMfbWxHNlGvptROQwQ6BasfdiVWCWzMHwLpz27Y47vKbMQ+8TL9668ilT83f" +
"6eo6mHZ590pzuDB+gFrjEK44ov0rvHBK5jHwnSObQvChN0ElizWBdMSUbx9SkcnReH6Fd29SSXdu" +
"RaVspnhmFNXWg7qGYHpEChnIGSr/WIKETZ84f7FRCxCNSYoQtrHs0SskiEGJYEbB6KDMFimEZ4YN" +
"b4cV8VLC9Pxa1Qe1Oa05FBzG2DAP2PfObeKR34afF5wo6vIZfQE0WWoPo9YS326vz1iA5rE0F6qw" +
"zCNmZl8+rW6x73MTEcWhvg==");
CertLoader certLoader = Certificates.RSAKeyTransferCapi1;
VerifySimpleDecrypt(encodedMessage, certLoader, expectedContentInfo);
}
[Fact]
public static void DecryptEnvelopedOctetStringWithDefiniteLength()
{
// enveloped content consists of 5 bytes: <id: 1 byte><length: 1 byte><content: 3 bytes>
// <id>:
// 04 - Octet string
// 30 - Sequence
// <length>: 03 => length is 3 (encoded with definite length)
// <content>: 010203
// Note: we expect invalid ASN.1 sequence
byte[] content = "0403010203".HexToByteArray();
byte[] expectedContent = "3003010203".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
[Fact]
public static void DecryptEnvelopedOctetStringWithInefficientlyEncodedLength()
{
// enveloped content consists of 5 or 6 bytes: <id: 1 byte><length: 1 or 2 bytes><content: 3 bytes>
// <id>:
// 04 - Octet string
// 30 - Sequence
// <length>: 03 => length is 3 (encoded with definite length)
// 81 03 => length is 3 (encoded with inefficiently encoded length)
// <content>: 010203
// Note: we expect invalid ASN.1 sequence
byte[] content = "048103010203".HexToByteArray();
byte[] expectedContent = "3003010203".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
[Fact]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "netfx does not allow it")]
public static void DecryptEnvelopedEmptyArray()
{
byte[] content = Array.Empty<byte>();
byte[] expectedContent = "3000".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
[Fact]
public static void DecryptEnvelopedEmptyOctetString()
{
byte[] content = "0400".HexToByteArray();
byte[] expectedContent = "3000".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
[Fact]
public static void DecryptEnvelopedOctetStringWithExtraData()
{
byte[] content = "04010203".HexToByteArray();
byte[] expectedContent = "300102".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
[Fact]
public static void DecryptEnvelopedDataWithNonPkcs7Oid()
{
byte[] content = "3003010203".HexToByteArray();
string nonPkcs7Oid = "0.0";
ContentInfo contentInfo = new ContentInfo(new Oid(nonPkcs7Oid), content);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber);
}
[ConditionalFact(nameof(SupportsIndefiniteLengthEncoding))]
public static void DecryptEnvelopedEmptyOctetStringWithIndefiniteLength()
{
byte[] content = "30800000".HexToByteArray();
byte[] expectedContent = "3000".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
[ConditionalFact(nameof(SupportsIndefiniteLengthEncoding))]
public static void DecryptEnvelopedOctetStringWithIndefiniteLength()
{
byte[] content = "308004000000".HexToByteArray();
byte[] expectedContent = "30020400".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
ContentInfo expectedContentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), expectedContent);
TestSimpleDecrypt_RoundTrip(Certificates.RSAKeyTransferCapi1, contentInfo, Oids.Aes256, SubjectIdentifierType.IssuerAndSerialNumber, expectedContentInfo);
}
private static void TestSimpleDecrypt_RoundTrip(CertLoader certLoader, ContentInfo contentInfo, string algorithmOidValue, SubjectIdentifierType type, ContentInfo expectedContentInfo = null)
{
// Deep-copy the contentInfo since the real ContentInfo doesn't do this. This defends against a bad implementation changing
// our "expectedContentInfo" to match what it produces.
ContentInfo expectedContentInfo = new ContentInfo(new Oid(contentInfo.ContentType), (byte[])(contentInfo.Content.Clone()));
expectedContentInfo = expectedContentInfo ?? new ContentInfo(new Oid(contentInfo.ContentType), (byte[])(contentInfo.Content.Clone()));
string certSubjectName;
byte[] encodedMessage;
byte[] originalCopy = (byte[])(contentInfo.Content.Clone());
using (X509Certificate2 certificate = certLoader.GetCertificate())
{
certSubjectName = certificate.Subject;
@@ -479,6 +735,7 @@ namespace System.Security.Cryptography.Pkcs.EnvelopedCmsTests.Tests
EnvelopedCms ecms = new EnvelopedCms(contentInfo, alg);
CmsRecipient cmsRecipient = new CmsRecipient(type, certificate);
ecms.Encrypt(cmsRecipient);
Assert.Equal(originalCopy.ByteArrayToHex(), ecms.ContentInfo.Content.ByteArrayToHex());
encodedMessage = ecms.Encode();
}
@@ -501,7 +758,7 @@ namespace System.Security.Cryptography.Pkcs.EnvelopedCmsTests.Tests
ecms.Decrypt(extraStore);
ContentInfo contentInfo = ecms.ContentInfo;
Assert.Equal(expectedContent.ContentType.Value, contentInfo.ContentType.Value);
Assert.Equal<byte>(expectedContent.Content, contentInfo.Content);
Assert.Equal(expectedContent.Content.ByteArrayToHex(), contentInfo.Content.ByteArrayToHex());
}
}
}

View File

@@ -519,6 +519,38 @@ namespace System.Security.Cryptography.Pkcs.EnvelopedCmsTests.Tests
object ignore;
Assert.Throws<InvalidOperationException>(() => ignore = new CryptographicAttributeObject(wrongOid, col));
}
[Fact]
public static void EncryptEnvelopedOctetStringWithIncompleteContent()
{
byte[] content = "04040203".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
using (X509Certificate2 certificate = Certificates.RSAKeyTransferCapi1.GetCertificate())
{
string certSubjectName = certificate.Subject;
AlgorithmIdentifier alg = new AlgorithmIdentifier(new Oid(Oids.Aes256));
EnvelopedCms ecms = new EnvelopedCms(contentInfo, alg);
CmsRecipient cmsRecipient = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
Assert.ThrowsAny<CryptographicException>(() => ecms.Encrypt(cmsRecipient));
}
}
[Fact]
public static void EncryptEnvelopedOneByteArray()
{
byte[] content = "04".HexToByteArray();
ContentInfo contentInfo = new ContentInfo(new Oid(Oids.Pkcs7Enveloped), content);
using (X509Certificate2 certificate = Certificates.RSAKeyTransferCapi1.GetCertificate())
{
string certSubjectName = certificate.Subject;
AlgorithmIdentifier alg = new AlgorithmIdentifier(new Oid(Oids.Aes256));
EnvelopedCms ecms = new EnvelopedCms(contentInfo, alg);
CmsRecipient cmsRecipient = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
Assert.ThrowsAny<CryptographicException>(() => ecms.Encrypt(cmsRecipient));
}
}
}
}

View File

@@ -23,6 +23,7 @@ namespace System.Security.Cryptography.Pkcs.Tests
// Asymmetric encryption algorithms
public const string Rsa = "1.2.840.113549.1.1.1";
public const string RsaPkcs1Sha256 = "1.2.840.113549.1.1.11";
public const string Esdh = "1.2.840.113549.1.9.16.3.5";
public const string Dh = "1.2.840.10046.2.1";

View File

@@ -15,6 +15,7 @@ namespace System.Security.Cryptography.Pkcs.Tests
[Theory]
[InlineData(nameof(TimestampTokenTestData.FreeTsaDotOrg1))]
[InlineData(nameof(TimestampTokenTestData.Symantec1))]
[InlineData(nameof(TimestampTokenTestData.DigiCert1))]
public static void CreateFromParameters(string testDataName)
{
TimestampTokenTestData testData = TimestampTokenTestData.GetTestData(testDataName);
@@ -124,6 +125,8 @@ namespace System.Security.Cryptography.Pkcs.Tests
[InlineData(nameof(TimestampTokenTestData.FreeTsaDotOrg1), true)]
[InlineData(nameof(TimestampTokenTestData.Symantec1), false)]
[InlineData(nameof(TimestampTokenTestData.Symantec1), true)]
[InlineData(nameof(TimestampTokenTestData.DigiCert1), false)]
[InlineData(nameof(TimestampTokenTestData.DigiCert1), true)]
public static void CreateFromValue(string testDataName, bool viaTry)
{
TimestampTokenTestData testData = TimestampTokenTestData.GetTestData(testDataName);

View File

@@ -48,6 +48,8 @@ namespace System.Security.Cryptography.Pkcs.Tests
return FreeTsaDotOrg1;
case nameof(Symantec1):
return Symantec1;
case nameof(DigiCert1):
return DigiCert1;
}
throw new ArgumentOutOfRangeException(nameof(testDataName), testDataName, "No registered value");
@@ -297,5 +299,145 @@ DgUIrLjqguolBSdvPJ2io9O0rTi7+IQr2jb8JEgpH1WNwC3R4A==");
data.TsaNameBytes = data.TokenInfoBytes.Slice(117, 134);
return data;
}))();
internal static readonly TimestampTokenTestData DigiCert1 = ((Func<TimestampTokenTestData>)(() =>
{
var data = new TimestampTokenTestData(
"30820EC406092A864886F70D010702A0820EB530820EB1020103310F300D0609" +
"608648016503040201050030818A060B2A864886F70D0109100104A07B047930" +
"7702010106096086480186FD6C07013031300D06096086480165030402010500" +
"04205A3B99F86CE06F5639C3ED7D0E16AE44A5CD58ABA0F6853A2AF389F91B6C" +
"7D7F02104E640CDE5C761BFF32FA0ADEA58C5F56180F32303138303731373136" +
"313732315A0211457A3006B9483730D09772076C4B74BDF8A0820BBB30820682" +
"3082056AA003020102021009C0FC46C8044213B5598BAF284F4E41300D06092A" +
"864886F70D01010B05003072310B300906035504061302555331153013060355" +
"040A130C446967694365727420496E6331193017060355040B13107777772E64" +
"696769636572742E636F6D3131302F0603550403132844696769436572742053" +
"48413220417373757265642049442054696D657374616D70696E67204341301E" +
"170D3137303130343030303030305A170D3238303131383030303030305A304C" +
"310B30090603550406130255533111300F060355040A13084469676943657274" +
"312A302806035504031321446967694365727420534841322054696D65737461" +
"6D7020526573706F6E64657230820122300D06092A864886F70D010101050003" +
"82010F003082010A02820101009E95986A343B731BA87EFCC7BE296989C76826" +
"465F3D8D62738781A3A19CF0B75B24375A92D4F459D77689E4DCD527F0D566BC" +
"0AEEB42B3167AC58C54A91592B451E0901D664B359EE8D664DFB235ECC100D0B" +
"8A67EF52AEA00890C252F7F5A8B56E9B2C7B9DE7B53EFB78CD325018BF40B54C" +
"8CBB57F4A04F11456C4242B9E5AFD6DFF4A77C0A68960FD25F2957CEFB1D32FF" +
"F411A11322FB12CBEFD753D2EB97CBA2AC1B1D9D58215182C2C2DEEA2B3F2C22" +
"84D043EC3B3B3F47C4F656DC453798B46B74B559AF785769C80F090278DDD853" +
"C199DB60C49DEAAEAFE07E864A5CA95861A85E748A012868724EA7869DB50252" +
"87706648D38EEF8124CCDCD8650203010001A382033830820334300E0603551D" +
"0F0101FF040403020780300C0603551D130101FF0402300030160603551D2501" +
"01FF040C300A06082B06010505070308308201BF0603551D20048201B6308201" +
"B2308201A106096086480186FD6C070130820192302806082B06010505070201" +
"161C68747470733A2F2F7777772E64696769636572742E636F6D2F4350533082" +
"016406082B06010505070202308201561E8201520041006E0079002000750073" +
"00650020006F0066002000740068006900730020004300650072007400690066" +
"0069006300610074006500200063006F006E0073007400690074007500740065" +
"007300200061006300630065007000740061006E006300650020006F00660020" +
"007400680065002000440069006700690043006500720074002000430050002F" +
"00430050005300200061006E00640020007400680065002000520065006C0079" +
"0069006E0067002000500061007200740079002000410067007200650065006D" +
"0065006E00740020007700680069006300680020006C0069006D006900740020" +
"006C0069006100620069006C00690074007900200061006E0064002000610072" +
"006500200069006E0063006F00720070006F0072006100740065006400200068" +
"0065007200650069006E0020006200790020007200650066006500720065006E" +
"00630065002E300B06096086480186FD6C0315301F0603551D23041830168014" +
"F4B6E1201DFE29AED2E461A5B2A225B2C817356E301D0603551D0E04160414E1" +
"A7324AEE0121287D54D5F207926EB4070F3D8730710603551D1F046A30683032" +
"A030A02E862C687474703A2F2F63726C332E64696769636572742E636F6D2F73" +
"6861322D617373757265642D74732E63726C3032A030A02E862C687474703A2F" +
"2F63726C342E64696769636572742E636F6D2F736861322D617373757265642D" +
"74732E63726C30818506082B0601050507010104793077302406082B06010505" +
"0730018618687474703A2F2F6F6373702E64696769636572742E636F6D304F06" +
"082B060105050730028643687474703A2F2F636163657274732E646967696365" +
"72742E636F6D2F44696769436572745348413241737375726564494454696D65" +
"7374616D70696E6743412E637274300D06092A864886F70D01010B0500038201" +
"01001EF0418232AEEDF1B43513DC50C2D597AE22229D0E0EAF33D34CFD7CBF6F" +
"0111A79465225CC622A1C889526B9A8C735CD95E3F32DE16604C8B36FD31990A" +
"BDC184B78D1DEF8926130556F347CD475BAD84B238AF6A23B545E31E88324680" +
"D2B7A69922FDC178CFF58BD80C8C0509EE44E680D56D70CC9F531E27DD2A48DE" +
"DA9365AD6E65A399A7C2400E73CC584F8F4528E5BC9C88E628CE605D2D255D8B" +
"732EA50D5B51DA9A4EFF50058928DAF278BBD258788D44A7AC3A009178698964" +
"04D35D96DF2ABFF9A54C2C93FFE68ADD82ACF1D2B3A2869AC15589566A473FFA" +
"D6339543358905785A3A69DA22B80443D36F6835367A143E45E99864860F130C" +
"264A3082053130820419A00302010202100AA125D6D6321B7E41E405DA3697C2" +
"15300D06092A864886F70D01010B05003065310B300906035504061302555331" +
"153013060355040A130C446967694365727420496E6331193017060355040B13" +
"107777772E64696769636572742E636F6D312430220603550403131B44696769" +
"43657274204173737572656420494420526F6F74204341301E170D3136303130" +
"373132303030305A170D3331303130373132303030305A3072310B3009060355" +
"04061302555331153013060355040A130C446967694365727420496E63311930" +
"17060355040B13107777772E64696769636572742E636F6D3131302F06035504" +
"0313284469676943657274205348413220417373757265642049442054696D65" +
"7374616D70696E6720434130820122300D06092A864886F70D01010105000382" +
"010F003082010A0282010100BDD032EE4BCD8F7FDDA9BA8299C539542857B623" +
"4AC40E07453351107DD0F97D4D687EE7B6A0F48DB388E497BF63219098BF13BC" +
"57D3C3E17E08D66A140038F72E1E3BEECCA6F63259FE5F653FE09BEBE3464706" +
"1A557E0B277EC0A2F5A0E0DE223F0EFF7E95FBF3A3BA223E18AC11E4F099036D" +
"3B857C09D3EE5DC89A0B54E3A809716BE0CF22100F75CF71724E0AADDF403A5C" +
"B751E1A17914C64D2423305DBCEC3C606AAC2F07CCFDF0EA47D988505EFD666E" +
"56612729898451E682E74650FD942A2CA7E4753EBA980F847F9F3114D6ADD5F2" +
"64CB7B1E05D084197217F11706EF3DCDD64DEF0642FDA2532A4F851DC41D3CAF" +
"CFDAAC10F5DDACACE956FF930203010001A38201CE308201CA301D0603551D0E" +
"04160414F4B6E1201DFE29AED2E461A5B2A225B2C817356E301F0603551D2304" +
"183016801445EBA2AFF492CB82312D518BA7A7219DF36DC80F30120603551D13" +
"0101FF040830060101FF020100300E0603551D0F0101FF040403020186301306" +
"03551D25040C300A06082B06010505070308307906082B06010505070101046D" +
"306B302406082B060105050730018618687474703A2F2F6F6373702E64696769" +
"636572742E636F6D304306082B060105050730028637687474703A2F2F636163" +
"657274732E64696769636572742E636F6D2F4469676943657274417373757265" +
"644944526F6F7443412E6372743081810603551D1F047A3078303AA038A03686" +
"34687474703A2F2F63726C342E64696769636572742E636F6D2F446967694365" +
"7274417373757265644944526F6F7443412E63726C303AA038A0368634687474" +
"703A2F2F63726C332E64696769636572742E636F6D2F44696769436572744173" +
"73757265644944526F6F7443412E63726C30500603551D20044930473038060A" +
"6086480186FD6C000204302A302806082B06010505070201161C68747470733A" +
"2F2F7777772E64696769636572742E636F6D2F435053300B06096086480186FD" +
"6C0701300D06092A864886F70D01010B05000382010100719512E951875669CD" +
"EFDDDA7CAA637AB378CF06374084EF4B84BFCACF0302FDC5A7C30E20422CAF77" +
"F32B1F0C215A2AB705341D6AAE99F827A266BF09AA60DF76A43A930FF8B2D1D8" +
"7C1962E85E82251EC4BA1C7B2C21E2D65B2C1435430468B2DB7502E072C798D6" +
"3C64E51F4810185F8938614D62462487638C91522CAF2989E5781FD60B14A580" +
"D7124770B375D59385937EB69267FB536189A8F56B96C0F458690D7CC801B1B9" +
"2875B7996385228C61CA79947E59FC8C0FE36FB50126B66CA5EE875121E45860" +
"9BBA0C2D2B6DA2C47EBBC4252B4702087C49AE13B6E17C424228C61856CF4134" +
"B6665DB6747BF55633222F2236B24BA24A95D8F5A68E523182024D3082024902" +
"01013081863072310B300906035504061302555331153013060355040A130C44" +
"6967694365727420496E6331193017060355040B13107777772E646967696365" +
"72742E636F6D3131302F06035504031328446967694365727420534841322041" +
"7373757265642049442054696D657374616D70696E67204341021009C0FC46C8" +
"044213B5598BAF284F4E41300D06096086480165030402010500A08198301A06" +
"092A864886F70D010903310D060B2A864886F70D0109100104301C06092A8648" +
"86F70D010905310F170D3138303731373136313732315A302F06092A864886F7" +
"0D01090431220420E66606A88254749C2E5575722F93AA67174FDDDB7703B7E6" +
"FAD6B3FE000F3DE2302B060B2A864886F70D010910020C311C301A3018301604" +
"14400191475C98891DEBA104AF47091B5EB6D4CBCB300D06092A864886F70D01" +
"01010500048201005AF349DE87550378C702ED31AE6DD6D50E6B24298DB2DFD6" +
"1396C6FA3E465FE7323ACD65AE157C06BCB993551F33702C6D1F6951AECDE74A" +
"969E41A8F0F95188780F990EAF6B129633CDE42FF149501BFAC05C516B6DA9EF" +
"E492488013928BA801D66C32EFE7EEDFF22DC96DDA4783674EEE8231E7A3AD8A" +
"98A506DABB68D6337D7FFDBD2F7112AF2FEE718CF6E7E5544DB7B4BDCD8191EB" +
"C73D568EE4D2A30B8478D676910E3B4EB868010AAF22400198D0593F987C86A9" +
"101711B9C6AC5C5776923C699E772B07864755C1AC50F387655C4E67DB356207" +
"76252A2F4605B97BD3C299D1CD79929273BB86E7DF9E113C92802380ED6D4041" +
"9DA4C01214D4FA24");
data.MessageContent = Encoding.UTF8.GetBytes("My TST signer attributes are sorted incorrectly.");
data.EmbeddedSigningCertificate = data.FullTokenBytes.Slice(188, 1670);
data.TokenInfoBytes = data.FullTokenBytes.Slice(63, 121);
data.PolicyId = "2.16.840.1.114412.7.1";
data.HashAlgorithmId = Oids.Sha256;
data.HashBytes = data.TokenInfoBytes.Slice(35, 32);
data.SerialNumberBytes = data.TokenInfoBytes.Slice(69, 16);
data.Timestamp = new DateTimeOffset(2018, 7, 17, 16, 17, 21, TimeSpan.Zero);
data.AccuracyInMicroseconds = null;
data.IsOrdering = false;
data.TsaNameBytes = null;
data.NonceBytes = data.TokenInfoBytes.Slice(104, 17);
return data;
}))();
}
}

View File

@@ -14,6 +14,7 @@ namespace System.Security.Cryptography.Pkcs.Tests
[Theory]
[InlineData(nameof(TimestampTokenTestData.FreeTsaDotOrg1))]
[InlineData(nameof(TimestampTokenTestData.Symantec1))]
[InlineData(nameof(TimestampTokenTestData.DigiCert1))]
public static void ParseDocument(string testDataName)
{
TimestampTokenTestData testData = TimestampTokenTestData.GetTestData(testDataName);
@@ -24,6 +25,7 @@ namespace System.Security.Cryptography.Pkcs.Tests
[Theory]
[InlineData(nameof(TimestampTokenTestData.FreeTsaDotOrg1))]
[InlineData(nameof(TimestampTokenTestData.Symantec1))]
[InlineData(nameof(TimestampTokenTestData.DigiCert1))]
public static void ParseDocument_ExcessData(string testDataName)
{
TimestampTokenTestData testData = TimestampTokenTestData.GetTestData(testDataName);

View File

@@ -4,6 +4,7 @@
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Xml;
using Test.Cryptography;
using Xunit;
@@ -426,6 +427,38 @@ namespace System.Security.Cryptography.Pkcs.Tests
cms.CheckSignature(true);
}
[Fact]
public static void AddSignerWithNegativeSerial()
{
const string expectedSerial = "FD319CB1514B06AF49E00522277E43C8";
ContentInfo contentInfo = new ContentInfo(new byte[] { 9, 8, 7, 6, 5 });
SignedCms cms = new SignedCms(contentInfo, false);
using (X509Certificate2 cert = Certificates.NegativeSerialNumber.TryGetCertificateWithPrivateKey())
{
Assert.Equal(expectedSerial, cert.SerialNumber);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert);
signer.IncludeOption = X509IncludeOption.EndCertOnly;
cms.ComputeSignature(signer);
}
SignerInfoCollection signers = cms.SignerInfos;
Assert.Equal(1, signers.Count);
SignerInfo signerInfo = signers[0];
Assert.Equal(SubjectIdentifierType.IssuerAndSerialNumber, signerInfo.SignerIdentifier.Type);
X509IssuerSerial issuerSerial = (X509IssuerSerial)signerInfo.SignerIdentifier.Value;
Assert.Equal(expectedSerial, issuerSerial.SerialNumber);
Assert.NotNull(signerInfo.Certificate);
// Assert.NoThrow
cms.CheckSignature(true);
}
[Theory]
[InlineData(SubjectIdentifierType.IssuerAndSerialNumber, false)]
[InlineData(SubjectIdentifierType.IssuerAndSerialNumber, true)]
@@ -891,16 +924,6 @@ namespace System.Security.Cryptography.Pkcs.Tests
cms.CheckSignature(true);
}
[Fact]
public static void SignerInfoCollection_Indexer_MinusOne ()
{
SignedCms cms = new SignedCms();
cms.Decode(SignedDocuments.RsaPkcs1OneSignerIssuerAndSerialNumber);
Assert.Throws<ArgumentOutOfRangeException>(() => cms.SignerInfos[-1]);
Assert.Throws<ArgumentOutOfRangeException>(() => cms.SignerInfos[1]);
}
[Theory]
[InlineData(SubjectIdentifierType.IssuerAndSerialNumber)]
[InlineData(SubjectIdentifierType.SubjectKeyIdentifier)]
@@ -957,8 +980,13 @@ namespace System.Security.Cryptography.Pkcs.Tests
{
signedCms.ComputeSignature(new CmsSigner(cert));
}
catch (CryptographicException) when (netfxProblem)
catch (CryptographicException)
{
if (!netfxProblem)
{
throw;
}
// When no signed or unsigned attributes are present and the signer uses
// IssuerAndSerial as the identifier type, NetFx uses an older PKCS7 encoding
// of the current CMS one. The older encoding fails on these inputs because of a
@@ -977,6 +1005,87 @@ namespace System.Security.Cryptography.Pkcs.Tests
Assert.Equal(contentHex, signedCms.ContentInfo.Content.ByteArrayToHex());
}
[Fact]
public static void VerifyUnsortedAttributeSignature()
{
SignedCms cms = new SignedCms();
cms.Decode(SignedDocuments.DigiCertTimeStampToken);
// Assert.NoThrows
cms.CheckSignature(true);
}
[Fact]
public static void VerifyUnsortedAttributeSignature_ImportExportImport()
{
SignedCms cms = new SignedCms();
cms.Decode(SignedDocuments.DigiCertTimeStampToken);
// Assert.NoThrows
cms.CheckSignature(true);
byte[] exported = cms.Encode();
cms = new SignedCms();
cms.Decode(exported);
// Assert.NoThrows
cms.CheckSignature(true);
}
[Fact]
public static void AddSignerToUnsortedAttributeSignature()
{
SignedCms cms = new SignedCms();
cms.Decode(SignedDocuments.DigiCertTimeStampToken);
// Assert.NoThrows
cms.CheckSignature(true);
using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey())
{
cms.ComputeSignature(
new CmsSigner(
SubjectIdentifierType.IssuerAndSerialNumber,
cert));
cms.ComputeSignature(
new CmsSigner(
SubjectIdentifierType.SubjectKeyIdentifier,
cert));
}
// Assert.NoThrows
cms.CheckSignature(true);
byte[] exported = cms.Encode();
cms = new SignedCms();
cms.Decode(exported);
// Assert.NoThrows
cms.CheckSignature(true);
}
[Fact]
public static void CheckSignature_Pkcs1_RsaWithSha256()
{
SignedCms signedCms = new SignedCms();
signedCms.Decode(SignedDocuments.RsaPkcs1Sha256WithRsa);
// Assert.NoThrows
signedCms.CheckSignature(true);
}
[Fact]
public static void CheckSignature_Pkcs1_Sha1_Declared_Sha256WithRsa()
{
SignedCms signedCms = new SignedCms();
signedCms.Decode(SignedDocuments.RsaPkcs1SignedSha1DeclaredSha256WithRsa);
Assert.Throws<CryptographicException>(() => {
signedCms.CheckSignature(true);
});
}
[Theory]
[InlineData(null, "0102", Oids.Pkcs7Data)]
[InlineData(null, "010100", Oids.Pkcs7Data)]
@@ -1044,6 +1153,22 @@ namespace System.Security.Cryptography.Pkcs.Tests
SubjectIdentifierType.SubjectKeyIdentifier);
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public static void ReadAndWriteDocumentWithIndefiniteLengthContent(bool checkSignature)
{
SignedCms cms = new SignedCms();
cms.Decode(SignedDocuments.IndefiniteLengthContentDocument);
if (checkSignature)
{
cms.CheckSignature(true);
}
cms.Encode();
}
private static void CheckSignedEncrypted(byte[] docBytes, SubjectIdentifierType expectedType)
{
SignedCms signedCms = new SignedCms();

Some files were not shown because too many files have changed in this diff Show More