public static void TagMustBeCorrect_Custom(PublicEncodingRules ruleSet) { byte[] inputData = { 0x87, 2, 0, 0x80 }; AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); AssertExtensions.Throws <ArgumentException>( "expectedTag", () => reader.TryReadPrimitiveOctetStringBytes(Asn1Tag.Null, out _)); Assert.True(reader.HasData, "HasData after bad universal tag"); Assert.Throws <CryptographicException>(() => reader.TryReadPrimitiveOctetStringBytes(out _)); Assert.True(reader.HasData, "HasData after default tag"); Assert.Throws <CryptographicException>( () => reader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.Application, 0), out _)); Assert.True(reader.HasData, "HasData after wrong custom class"); Assert.Throws <CryptographicException>( () => reader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 1), out _)); Assert.True(reader.HasData, "HasData after wrong custom tag value"); Assert.True( reader.TryReadPrimitiveOctetStringBytes( new Asn1Tag(TagClass.ContextSpecific, 7), out ReadOnlyMemory <byte> value)); Assert.Equal("0080", value.ByteArrayToHex()); Assert.False(reader.HasData, "HasData after reading value"); }
internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded) where T : KrbPaPkAsReq, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader explicitReader; AsnReader collectionReader; if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out ReadOnlyMemory <byte> tmpSignedAuthPack)) { decoded.SignedAuthPack = tmpSignedAuthPack; } else { decoded.SignedAuthPack = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 0)); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); // Decode SEQUENCE OF for TrustedCertifiers { collectionReader = explicitReader.ReadSequence(); var tmpList = new List <KrbExternalPrincipalIdentifier>(); KrbExternalPrincipalIdentifier tmpItem; while (collectionReader.HasData) { KrbExternalPrincipalIdentifier.Decode <KrbExternalPrincipalIdentifier>(collectionReader, out KrbExternalPrincipalIdentifier tmp); tmpItem = tmp; tmpList.Add(tmpItem); } decoded.TrustedCertifiers = tmpList.ToArray(); } explicitReader.ThrowIfNotEmpty(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) { if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 2), out ReadOnlyMemory <byte> tmpKdcPkId)) { decoded.KdcPkId = tmpKdcPkId; } else { decoded.KdcPkId = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 2)); } } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded) where T : KrbExternalPrincipalIdentifier, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out ReadOnlyMemory <byte> tmpSubjectName)) { decoded.SubjectName = tmpSubjectName; } else { decoded.SubjectName = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 0)); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 1), out ReadOnlyMemory <byte> tmpIssuerAndSerialNumber)) { decoded.IssuerAndSerialNumber = tmpIssuerAndSerialNumber; } else { decoded.IssuerAndSerialNumber = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 1)); } } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2))) { if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 2), out ReadOnlyMemory <byte> tmpSubjectKeyIdentifier)) { decoded.SubjectKeyIdentifier = tmpSubjectKeyIdentifier; } else { decoded.SubjectKeyIdentifier = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 2)); } } sequenceReader.ThrowIfNotEmpty(); }
public static void TryGetOctetStringBytes_Success_CER_MaxLength() { // CER says that the maximum encoding length for an OctetString primitive // is 1000. // // So we need 04 [1000] { 1000 anythings } // 1000 => 0x3E8, so the length encoding is 82 03 E8. // 1000 + 3 + 1 == 1004 byte[] input = new byte[1004]; input[0] = 0x04; input[1] = 0x82; input[2] = 0x03; input[3] = 0xE8; // Contents input[4] = 0x02; input[5] = 0xA0; input[1002] = 0xA5; input[1003] = 0xFC; AsnReader reader = new AsnReader(input, AsnEncodingRules.CER); bool success = reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents); Assert.True(success, "reader.TryReadOctetStringBytes"); Assert.Equal(1000, contents.Length); // Check that it is, in fact, the same memory. No copies with this API. Assert.True( Unsafe.AreSame( ref MemoryMarshal.GetReference(contents.Span), ref input[4])); }
internal static void Decode(AsnReader reader, out SignerIdentifierAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; Asn1Tag tag = reader.PeekTag(); if (tag.HasSameClassAndValue(Asn1Tag.Sequence)) { System.Security.Cryptography.Pkcs.Asn1.IssuerAndSerialNumberAsn tmpIssuerAndSerialNumber; System.Security.Cryptography.Pkcs.Asn1.IssuerAndSerialNumberAsn.Decode(reader, out tmpIssuerAndSerialNumber); decoded.IssuerAndSerialNumber = tmpIssuerAndSerialNumber; } else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { if (reader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out ReadOnlyMemory <byte> tmpSubjectKeyIdentifier)) { decoded.SubjectKeyIdentifier = tmpSubjectKeyIdentifier; } else { decoded.SubjectKeyIdentifier = reader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 0)); } } else { throw new CryptographicException(); } }
public static void ExpectedTag_IgnoresConstructed( PublicEncodingRules ruleSet, string inputHex, PublicTagClass tagClass, int tagValue) { byte[] inputData = inputHex.HexToByteArray(); AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); Assert.True( reader.TryReadPrimitiveOctetStringBytes( new Asn1Tag((TagClass)tagClass, tagValue, true), out ReadOnlyMemory <byte> val1)); Assert.False(reader.HasData); reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); Assert.True( reader.TryReadPrimitiveOctetStringBytes( new Asn1Tag((TagClass)tagClass, tagValue, false), out ReadOnlyMemory <byte> val2)); Assert.False(reader.HasData); Assert.Equal(val1.ByteArrayToHex(), val2.ByteArrayToHex()); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out KeyTransRecipientInfoAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (!sequenceReader.TryReadInt32(out decoded.Version)) { sequenceReader.ThrowIfNotEmpty(); } System.Security.Cryptography.Pkcs.Asn1.RecipientIdentifierAsn.Decode(sequenceReader, out decoded.Rid); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.KeyEncryptionAlgorithm); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpEncryptedKey)) { decoded.EncryptedKey = tmpEncryptedKey; } else { decoded.EncryptedKey = sequenceReader.ReadOctetString(); } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out EncryptedContentInfoAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); decoded.ContentType = sequenceReader.ReadObjectIdentifierAsString(); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.ContentEncryptionAlgorithm); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out ReadOnlyMemory <byte> tmpEncryptedContent)) { decoded.EncryptedContent = tmpEncryptedContent; } else { decoded.EncryptedContent = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 0)); } } sequenceReader.ThrowIfNotEmpty(); }
private static byte[] Decrypt(byte[] payload, byte[] key) { var enveloped = new EnvelopedCms(); enveloped.Decode(payload); var recipientInfo = enveloped.RecipientInfos[0]; var unwrappedKey = KeyWrapAlgorithm.UnwrapKey(key, recipientInfo.EncryptedKey); using (var aes = Aes.Create()) { aes.Padding = PaddingMode.PKCS7; aes.Mode = CipherMode.CBC; aes.KeySize = 128; aes.Key = unwrappedKey; AsnReader reader = new AsnReader(enveloped.ContentEncryptionAlgorithm.Parameters, AsnEncodingRules.BER); if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> primitiveBytes)) { aes.IV = primitiveBytes.ToArray(); } using (var decryptor = aes.CreateDecryptor(unwrappedKey, aes.IV)) { using (MemoryStream memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Write)) { cryptoStream.Write(enveloped.ContentInfo.Content, 0, enveloped.ContentInfo.Content.Length); } var result = memoryStream.ToArray(); return(result); } } } }
public static ReadOnlyMemory <byte> DecodeOctetStringAsMemory(ReadOnlyMemory <byte> encodedOctetString) { AsnReader reader = new AsnReader(encodedOctetString, AsnEncodingRules.BER); if (reader.PeekEncodedValue().Length != encodedOctetString.Length) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } // Almost everything in X.509 is DER-encoded, which means Octet String values are // encoded as a primitive (non-segmented) // // Even in BER Octet Strings are usually encoded as a primitive. if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> primitiveContents)) { return(primitiveContents); } byte[] tooBig = new byte[encodedOctetString.Length]; if (reader.TryCopyOctetStringBytes(tooBig, out int bytesWritten)) { return(tooBig.AsMemory(0, bytesWritten)); } Debug.Fail("TryCopyOctetStringBytes failed with an over-allocated array"); throw new CryptographicException(); }
public override byte[] GetSubjectKeyIdentifier(X509Certificate2 certificate) { Debug.Assert(certificate != null); X509Extension?extension = certificate.Extensions[Oids.SubjectKeyIdentifier]; if (extension == null) { // Construct the value from the public key info. extension = new X509SubjectKeyIdentifierExtension( certificate.PublicKey, X509SubjectKeyIdentifierHashAlgorithm.CapiSha1, false); } // Certificates are DER encoded. AsnReader reader = new AsnReader(extension.RawData, AsnEncodingRules.DER); if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents)) { reader.ThrowIfNotEmpty(); return(contents.ToArray()); } // TryGetPrimitiveOctetStringBytes will have thrown if the next tag wasn't // Universal (primitive) OCTET STRING, since we're in DER mode. // So there's really no way we can get here. Debug.Fail($"TryGetPrimitiveOctetStringBytes returned false in DER mode"); throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out EssCertId decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpHash)) { decoded.Hash = tmpHash; } else { decoded.Hash = sequenceReader.ReadOctetString(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence)) { System.Security.Cryptography.Pkcs.Asn1.CadesIssuerSerial tmpIssuerSerial; System.Security.Cryptography.Pkcs.Asn1.CadesIssuerSerial.Decode(sequenceReader, out tmpIssuerSerial); decoded.IssuerSerial = tmpIssuerSerial; } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out SignerInfoAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader collectionReader; if (!sequenceReader.TryReadInt32(out decoded.Version)) { sequenceReader.ThrowIfNotEmpty(); } System.Security.Cryptography.Pkcs.Asn1.SignerIdentifierAsn.Decode(sequenceReader, out decoded.Sid); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.DigestAlgorithm); if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0))) { decoded.SignedAttributes = sequenceReader.ReadEncodedValue(); } System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.SignatureAlgorithm); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpSignatureValue)) { decoded.SignatureValue = tmpSignatureValue; } else { decoded.SignatureValue = sequenceReader.ReadOctetString(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { // Decode SEQUENCE OF for UnsignedAttributes { collectionReader = sequenceReader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 1)); var tmpList = new List <System.Security.Cryptography.Asn1.AttributeAsn>(); System.Security.Cryptography.Asn1.AttributeAsn tmpItem; while (collectionReader.HasData) { System.Security.Cryptography.Asn1.AttributeAsn.Decode(collectionReader, out tmpItem); tmpList.Add(tmpItem); } decoded.UnsignedAttributes = tmpList.ToArray(); } } sequenceReader.ThrowIfNotEmpty(); }
public static void TagMustBeCorrect_Universal(PublicEncodingRules ruleSet) { byte[] inputData = { 4, 1, 0x7E }; AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); AssertExtensions.Throws <ArgumentException>( "expectedTag", () => reader.TryReadPrimitiveOctetStringBytes(Asn1Tag.Null, out _)); Assert.True(reader.HasData, "HasData after bad universal tag"); Assert.Throws <CryptographicException>( () => reader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out _)); Assert.True(reader.HasData, "HasData after wrong tag"); Assert.True(reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> value)); Assert.Equal("7E", value.ByteArrayToHex()); Assert.False(reader.HasData, "HasData after read"); }
public static void TryGetOctetStringBytes_Throws( string description, PublicEncodingRules ruleSet, string inputHex) { byte[] inputData = inputHex.HexToByteArray(); AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); Assert.Throws <CryptographicException>( () => reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents)); }
internal static byte[] DecodeX509SubjectKeyIdentifierExtension(byte[] encoded) { AsnReader reader = new AsnReader(encoded, AsnEncodingRules.BER); ReadOnlyMemory <byte> contents; if (!reader.TryReadPrimitiveOctetStringBytes(out contents)) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } reader.ThrowIfNotEmpty(); return(contents.ToArray()); }
internal static ReadOnlyMemory <byte> GetContent( ReadOnlyMemory <byte> wrappedContent, string contentType) { // Read the input. // // PKCS7's id-data is written in both PKCS#7 and CMS as an OCTET STRING wrapping // the arbitrary bytes, so the OCTET STRING must always be present. // // For other types, CMS says to always write an OCTET STRING, and to put the properly // encoded data within it. // PKCS#7 originally ommitted the OCTET STRING wrapper for this model, so this is the // dynamic adapter. // // See https://tools.ietf.org/html/rfc5652#section-5.2.1 byte[] rented = null; int bytesWritten = 0; try { AsnReader reader = new AsnReader(wrappedContent, AsnEncodingRules.BER); if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> inner)) { return(inner); } rented = ArrayPool <byte> .Shared.Rent(wrappedContent.Length); if (!reader.TryCopyOctetStringBytes(rented, out bytesWritten)) { Debug.Fail($"TryCopyOctetStringBytes failed with an array larger than the encoded value"); throw new CryptographicException(); } return(rented.AsSpan(0, bytesWritten).ToArray()); } catch (Exception) when(contentType != Oids.Pkcs7Data) { } finally { if (rented != null) { rented.AsSpan(0, bytesWritten).Clear(); ArrayPool <byte> .Shared.Return(rented); } } // PKCS#7 encoding for something other than id-data. Debug.Assert(contentType != Oids.Pkcs7Data); return(wrappedContent); }
public static void TryGetOctetStringBytes_Fails( string description, PublicEncodingRules ruleSet, string inputHex) { byte[] inputData = inputHex.HexToByteArray(); AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); bool didRead = reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents); Assert.False(didRead, "reader.TryReadOctetStringBytes"); Assert.Equal(0, contents.Length); }
public static void TryGetOctetStringBytes_Success( PublicEncodingRules ruleSet, int expectedLength, string inputHex) { byte[] inputData = inputHex.HexToByteArray(); AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet); bool didRead = reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents); Assert.True(didRead, "reader.TryReadOctetStringBytes"); Assert.Equal(expectedLength, contents.Length); }
private static void AssertExtension(AsnReader extensions, string oid, bool critical, int index, byte[] bytes) { AsnReader extension = extensions.ReadSequence(); Assert.Equal(oid, extension.ReadObjectIdentifierAsString()); if (critical) { Assert.True(extension.ReadBoolean(), $"{oid} is critical"); } Assert.True(extension.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> extensionBytes)); AssertRefSame(extensionBytes, ref bytes[index], $"{oid} extension value is at byte {index}"); }
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 = Rc2CbcParameters.Decode( 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.TryReadPrimitiveOctetStringBytes(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); }
public static void TryGetOctetStringBytes_Throws_CER_TooLong() { // CER says that the maximum encoding length for an OctetString primitive // is 1000. // // So we need 04 [1001] { 1001 0x00s } // 1001 => 0x3E9, so the length encoding is 82 03 E9. // 1001 + 3 + 1 == 1005 byte[] input = new byte[1005]; input[0] = 0x04; input[1] = 0x82; input[2] = 0x03; input[3] = 0xE9; AsnReader reader = new AsnReader(input, AsnEncodingRules.CER); Assert.Throws <CryptographicException>( () => reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents)); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out MacData decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader defaultReader; System.Security.Cryptography.Asn1.DigestInfoAsn.Decode(sequenceReader, out decoded.Mac); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpMacSalt)) { decoded.MacSalt = tmpMacSalt; } else { decoded.MacSalt = sequenceReader.ReadOctetString(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Integer)) { if (!sequenceReader.TryReadInt32(out decoded.IterationCount)) { sequenceReader.ThrowIfNotEmpty(); } } else { defaultReader = new AsnReader(s_defaultIterationCount, AsnEncodingRules.DER); if (!defaultReader.TryReadInt32(out decoded.IterationCount)) { defaultReader.ThrowIfNotEmpty(); } } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode <T>(AsnReader reader, Asn1Tag expectedTag, out T decoded) where T : KrbDHReplyInfo, new() { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = new T(); AsnReader sequenceReader = reader.ReadSequence(expectedTag); AsnReader explicitReader; if (sequenceReader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 0), out ReadOnlyMemory <byte> tmpDHSignedData)) { decoded.DHSignedData = tmpDHSignedData; } else { decoded.DHSignedData = sequenceReader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 0)); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1))) { explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1)); if (explicitReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpServerDHNonce)) { decoded.ServerDHNonce = tmpServerDHNonce; } else { decoded.ServerDHNonce = explicitReader.ReadOctetString(); } explicitReader.ThrowIfNotEmpty(); } sequenceReader.ThrowIfNotEmpty(); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out RecipientKeyIdentifier decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpSubjectKeyIdentifier)) { decoded.SubjectKeyIdentifier = tmpSubjectKeyIdentifier; } else { decoded.SubjectKeyIdentifier = sequenceReader.ReadOctetString(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.GeneralizedTime)) { decoded.Date = sequenceReader.ReadGeneralizedTime(); } if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Sequence)) { System.Security.Cryptography.Pkcs.Asn1.OtherKeyAttributeAsn tmpOther; System.Security.Cryptography.Pkcs.Asn1.OtherKeyAttributeAsn.Decode(sequenceReader, out tmpOther); decoded.Other = tmpOther; } sequenceReader.ThrowIfNotEmpty(); }
public static ReadOnlyMemory <byte> DecodeOctetStringAsMemory(ReadOnlyMemory <byte> encodedOctetString) { AsnReader reader = new AsnReader(encodedOctetString, AsnEncodingRules.BER); if (reader.PeekEncodedValue().Length != encodedOctetString.Length) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> primitiveContents)) { return(primitiveContents); } byte[] tooBig = new byte[encodedOctetString.Length]; if (reader.TryCopyOctetStringBytes(tooBig, out int bytesWritten)) { return(tooBig.AsMemory(0, bytesWritten)); } Debug.Fail("TryCopyOctetStringBytes failed with an over-allocated array"); throw new CryptographicException(); }
internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out DigestInfoAsn decoded) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } decoded = default; AsnReader sequenceReader = reader.ReadSequence(expectedTag); System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(sequenceReader, out decoded.DigestAlgorithm); if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpDigest)) { decoded.Digest = tmpDigest; } else { decoded.Digest = sequenceReader.ReadOctetString(); } sequenceReader.ThrowIfNotEmpty(); }
public static unsafe ContentInfo TryDecryptCore( byte[] cek, string contentType, ReadOnlyMemory <byte>?content, AlgorithmIdentifierAsn contentEncryptionAlgorithm, out Exception exception) { if (content == null) { exception = null; return(new ContentInfo( new Oid(contentType), Array.Empty <byte>())); } byte[] decrypted = DecryptContent(content.Value, cek, contentEncryptionAlgorithm, out exception); if (exception != null) { return(null); } if (contentType == Oids.Pkcs7Data) { byte[] tmp = null; try { AsnReader reader = new AsnReader(decrypted, AsnEncodingRules.BER); if (reader.TryReadPrimitiveOctetStringBytes(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); } } } else { decrypted = GetAsnSequenceWithContentNoValidation(decrypted); } exception = null; return(new ContentInfo( new Oid(contentType), decrypted)); }
public static unsafe ContentInfo?TryDecryptCore( byte[] cek, string contentType, ReadOnlyMemory <byte>?content, AlgorithmIdentifierAsn contentEncryptionAlgorithm, out Exception?exception) { if (content == null) { exception = null; return(new ContentInfo( new Oid(contentType), Array.Empty <byte>())); } byte[]? decrypted = DecryptContent(content.Value, cek, contentEncryptionAlgorithm, out exception); if (exception != null) { return(null); } // Compat: Previous versions of the managed PAL encryptor would wrap the contents in an octet stream // which is not correct and is incompatible with other CMS readers. To maintain compatibility with // existing CMS that have the incorrect wrapping, we attempt to remove it. if (contentType == Oids.Pkcs7Data) { byte[]? tmp = null; try { AsnReader reader = new AsnReader(decrypted, AsnEncodingRules.BER); if (reader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> contents)) { decrypted = contents.ToArray(); } else { tmp = CryptoPool.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 CryptoPool.Return(tmp, clearSize: 0); } } } else { decrypted = GetAsnSequenceWithContentNoValidation(decrypted); } exception = null; return(new ContentInfo( new Oid(contentType), decrypted !)); }
internal static AlgorithmIdentifier ToPresentationObject(this AlgorithmIdentifierAsn asn) { int keyLength; byte[] parameters = Array.Empty <byte>(); switch (asn.Algorithm.Value) { case Oids.Rc2Cbc: { if (asn.Parameters == null) { keyLength = 0; break; } Rc2CbcParameters rc2Params = Rc2CbcParameters.Decode( 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.TryReadPrimitiveOctetStringBytes(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; case Oids.RsaOaep when !asn.HasNullEquivalentParameters(): keyLength = 0; parameters = asn.Parameters.Value.ToArray(); 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) { Parameters = parameters }); }