Пример #1
0
        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");
        }
Пример #2
0
        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();
        }
Пример #4
0
        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]));
        }
Пример #5
0
        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();
            }
        }
Пример #6
0
        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();
        }
Пример #9
0
        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);
                    }
                }
            }
        }
Пример #10
0
        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();
        }
Пример #11
0
        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);
        }
Пример #12
0
        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();
        }
Пример #13
0
        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();
        }
Пример #14
0
        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");
        }
Пример #15
0
        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());
        }
Пример #17
0
        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);
        }
Пример #18
0
        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);
        }
Пример #19
0
        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}");
        }
Пример #21
0
        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);
        }
Пример #22
0
        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));
        }
Пример #23
0
        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();
        }
Пример #24
0
        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();
        }
Пример #25
0
        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();
        }
Пример #26
0
        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();
        }
Пример #27
0
        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();
        }
Пример #28
0
            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));
            }
Пример #29
0
            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 !));
            }
Пример #30
0
        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
            });
        }