예제 #1
0
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out X509ExtensionAsn decoded)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = default;
            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader defaultReader;

            decoded.ExtnId = sequenceReader.ReadObjectIdentifier();

            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.Boolean))
            {
                decoded.Critical = sequenceReader.ReadBoolean();
            }
            else
            {
                defaultReader    = new AsnReader(s_defaultCritical, AsnEncodingRules.DER);
                decoded.Critical = defaultReader.ReadBoolean();
            }


            if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpExtnValue))
            {
                decoded.ExtnValue = tmpExtnValue;
            }
            else
            {
                decoded.ExtnValue = sequenceReader.ReadOctetString();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
예제 #2
0
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out EncryptedPrivateKeyInfoAsn 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.EncryptionAlgorithm);

            if (sequenceReader.TryReadPrimitiveOctetStringBytes(out ReadOnlyMemory <byte> tmpEncryptedData))
            {
                decoded.EncryptedData = tmpEncryptedData;
            }
            else
            {
                decoded.EncryptedData = sequenceReader.ReadOctetString();
            }


            sequenceReader.ThrowIfNotEmpty();
        }
예제 #3
0
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out SubjectPublicKeyInfoAsn 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.Algorithm);

            if (sequenceReader.TryReadPrimitiveBitStringValue(out _, out ReadOnlyMemory <byte> tmpSubjectPublicKey))
            {
                decoded.SubjectPublicKey = tmpSubjectPublicKey;
            }
            else
            {
                decoded.SubjectPublicKey = sequenceReader.ReadBitString(out _);
            }


            sequenceReader.ThrowIfNotEmpty();
        }
예제 #4
0
        internal static void Decode(AsnReader reader, out GeneralNameAsn decoded)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = default;
            Asn1Tag   tag = reader.PeekTag();
            AsnReader explicitReader;

            if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0)))
            {
                System.Security.Cryptography.Asn1.OtherNameAsn tmpOtherName;
                System.Security.Cryptography.Asn1.OtherNameAsn.Decode(reader, new Asn1Tag(TagClass.ContextSpecific, 0), out tmpOtherName);
                decoded.OtherName = tmpOtherName;
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                decoded.Rfc822Name = reader.GetCharacterString(new Asn1Tag(TagClass.ContextSpecific, 1), UniversalTagNumber.IA5String);
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2)))
            {
                decoded.DnsName = reader.GetCharacterString(new Asn1Tag(TagClass.ContextSpecific, 2), UniversalTagNumber.IA5String);
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 3)))
            {
                decoded.X400Address = reader.GetEncodedValue();
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 4)))
            {
                explicitReader        = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 4));
                decoded.DirectoryName = explicitReader.GetEncodedValue();
                explicitReader.ThrowIfNotEmpty();
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 5)))
            {
                System.Security.Cryptography.Asn1.EdiPartyNameAsn tmpEdiPartyName;
                System.Security.Cryptography.Asn1.EdiPartyNameAsn.Decode(reader, new Asn1Tag(TagClass.ContextSpecific, 5), out tmpEdiPartyName);
                decoded.EdiPartyName = tmpEdiPartyName;
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 6)))
            {
                decoded.Uri = reader.GetCharacterString(new Asn1Tag(TagClass.ContextSpecific, 6), UniversalTagNumber.IA5String);
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 7)))
            {
                if (reader.TryGetPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 7), out ReadOnlyMemory <byte> tmpIPAddress))
                {
                    decoded.IPAddress = tmpIPAddress;
                }
                else
                {
                    decoded.IPAddress = reader.ReadOctetString(new Asn1Tag(TagClass.ContextSpecific, 7));
                }
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 8)))
            {
                decoded.RegisteredId = reader.ReadObjectIdentifierAsString(new Asn1Tag(TagClass.ContextSpecific, 8));
            }
            else
            {
                throw new CryptographicException();
            }
        }
예제 #5
0
        private int ProcessConstructedBitString(
            ReadOnlyMemory <byte> source,
            Span <byte> destination,
            BitStringCopyAction copyAction,
            bool isIndefinite,
            out int lastUnusedBitCount,
            out int bytesRead)
        {
            lastUnusedBitCount = 0;
            bytesRead          = 0;
            int lastSegmentLength = MaxCERSegmentSize;

            AsnReader tmpReader = new AsnReader(source, RuleSet);
            Stack <(AsnReader, bool, int)> readerStack = null;
            int         totalLength = 0;
            Asn1Tag     tag         = Asn1Tag.ConstructedBitString;
            Span <byte> curDest     = destination;

            do
            {
                while (tmpReader.HasData)
                {
                    tag = tmpReader.ReadTagAndLength(out int?length, out int headerLength);

                    if (tag == Asn1Tag.PrimitiveBitString)
                    {
                        if (lastUnusedBitCount != 0)
                        {
                            // T-REC-X.690-201508 sec 8.6.4, only the last segment may have
                            // a number of bits not a multiple of 8.
                            throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                        }

                        if (RuleSet == AsnEncodingRules.CER && lastSegmentLength != MaxCERSegmentSize)
                        {
                            // T-REC-X.690-201508 sec 9.2
                            throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                        }

                        Debug.Assert(length != null);
                        ReadOnlyMemory <byte> encodedValue = Slice(tmpReader._data, headerLength, length.Value);

                        ParsePrimitiveBitStringContents(
                            encodedValue,
                            out lastUnusedBitCount,
                            out ReadOnlyMemory <byte> contents,
                            out byte normalizedLastByte);

                        int localLen = headerLength + encodedValue.Length;
                        tmpReader._data = tmpReader._data.Slice(localLen);

                        bytesRead        += localLen;
                        totalLength      += contents.Length;
                        lastSegmentLength = encodedValue.Length;

                        if (copyAction != null)
                        {
                            copyAction(contents, normalizedLastByte, curDest);
                            curDest = curDest.Slice(contents.Length);
                        }
                    }
                    else if (tag == Asn1Tag.EndOfContents && isIndefinite)
                    {
                        ValidateEndOfContents(tag, length, headerLength);

                        bytesRead += headerLength;

                        if (readerStack?.Count > 0)
                        {
                            (AsnReader topReader, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();
                            topReader._data = topReader._data.Slice(bytesRead);

                            bytesRead   += pushedBytesRead;
                            isIndefinite = wasIndefinite;
                            tmpReader    = topReader;
                        }
                        else
                        {
                            // We have matched the EndOfContents that brought us here.
                            break;
                        }
                    }
                    else if (tag == Asn1Tag.ConstructedBitString)
                    {
                        if (RuleSet == AsnEncodingRules.CER)
                        {
                            // T-REC-X.690-201508 sec 9.2
                            throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                        }

                        if (readerStack == null)
                        {
                            readerStack = new Stack <(AsnReader, bool, int)>();
                        }

                        readerStack.Push((tmpReader, isIndefinite, bytesRead));

                        tmpReader = new AsnReader(
                            Slice(tmpReader._data, headerLength, length),
                            RuleSet);

                        bytesRead    = headerLength;
                        isIndefinite = (length == null);
                    }
                    else
                    {
                        // T-REC-X.690-201508 sec 8.6.4.1 (in particular, Note 2)
                        throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                    }
                }

                if (isIndefinite && tag != Asn1Tag.EndOfContents)
                {
                    throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
                }

                if (readerStack?.Count > 0)
                {
                    (AsnReader topReader, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();

                    tmpReader       = topReader;
                    tmpReader._data = tmpReader._data.Slice(bytesRead);

                    isIndefinite = wasIndefinite;
                    bytesRead   += pushedBytesRead;
                }
                else
                {
                    tmpReader = null;
                }
            } while (tmpReader != null);

            return(totalLength);
        }
예제 #6
0
        internal static void Decode(AsnReader reader, Asn1Tag expectedTag, out PssParamsAsn decoded)
        {
            if (reader == null)
            {
                throw new ArgumentNullException(nameof(reader));
            }

            decoded = default;
            AsnReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnReader explicitReader;
            AsnReader defaultReader;


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));
                System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(explicitReader, out decoded.HashAlgorithm);
                explicitReader.ThrowIfNotEmpty();
            }
            else
            {
                defaultReader = new AsnReader(s_defaultHashAlgorithm, AsnEncodingRules.DER);
                System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(defaultReader, out decoded.HashAlgorithm);
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1));
                System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(explicitReader, out decoded.MaskGenAlgorithm);
                explicitReader.ThrowIfNotEmpty();
            }
            else
            {
                defaultReader = new AsnReader(s_defaultMaskGenAlgorithm, AsnEncodingRules.DER);
                System.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(defaultReader, out decoded.MaskGenAlgorithm);
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 2));

                if (!explicitReader.TryReadInt32(out decoded.SaltLength))
                {
                    explicitReader.ThrowIfNotEmpty();
                }

                explicitReader.ThrowIfNotEmpty();
            }
            else
            {
                defaultReader = new AsnReader(s_defaultSaltLength, AsnEncodingRules.DER);

                if (!defaultReader.TryReadInt32(out decoded.SaltLength))
                {
                    defaultReader.ThrowIfNotEmpty();
                }
            }


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 3)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3));

                if (!explicitReader.TryReadInt32(out decoded.TrailerField))
                {
                    explicitReader.ThrowIfNotEmpty();
                }

                explicitReader.ThrowIfNotEmpty();
            }
            else
            {
                defaultReader = new AsnReader(s_defaultTrailerField, AsnEncodingRules.DER);

                if (!defaultReader.TryReadInt32(out decoded.TrailerField))
                {
                    defaultReader.ThrowIfNotEmpty();
                }
            }


            sequenceReader.ThrowIfNotEmpty();
        }
예제 #7
0
        private int CopyConstructedOctetString(
            ReadOnlyMemory <byte> source,
            Span <byte> destination,
            bool write,
            bool isIndefinite,
            out int bytesRead)
        {
            bytesRead = 0;
            int lastSegmentLength = MaxCERSegmentSize;

            AsnReader tmpReader = new AsnReader(source, RuleSet);
            Stack <(AsnReader, bool, int)> readerStack = null;
            int         totalLength = 0;
            Asn1Tag     tag         = Asn1Tag.ConstructedBitString;
            Span <byte> curDest     = destination;

            do
            {
                while (tmpReader.HasData)
                {
                    tag = tmpReader.ReadTagAndLength(out int?length, out int headerLength);

                    if (tag == Asn1Tag.PrimitiveOctetString)
                    {
                        if (RuleSet == AsnEncodingRules.CER && lastSegmentLength != MaxCERSegmentSize)
                        {
                            // T-REC-X.690-201508 sec 9.2
                            throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding"));
                        }

                        Debug.Assert(length != null);

                        // The call to Slice here sanity checks the data bounds, length.Value is not
                        // reliable unless this call has succeeded.
                        ReadOnlyMemory <byte> contents = Slice(tmpReader._data, headerLength, length.Value);

                        int localLen = headerLength + contents.Length;
                        tmpReader._data = tmpReader._data.Slice(localLen);

                        bytesRead        += localLen;
                        totalLength      += contents.Length;
                        lastSegmentLength = contents.Length;

                        if (RuleSet == AsnEncodingRules.CER && lastSegmentLength > MaxCERSegmentSize)
                        {
                            // T-REC-X.690-201508 sec 9.2
                            throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding"));
                        }

                        if (write)
                        {
                            contents.Span.CopyTo(curDest);
                            curDest = curDest.Slice(contents.Length);
                        }
                    }
                    else if (tag == Asn1Tag.EndOfContents && isIndefinite)
                    {
                        ValidateEndOfContents(tag, length, headerLength);

                        bytesRead += headerLength;

                        if (readerStack?.Count > 0)
                        {
                            (AsnReader topReader, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();
                            topReader._data = topReader._data.Slice(bytesRead);

                            bytesRead   += pushedBytesRead;
                            isIndefinite = wasIndefinite;
                            tmpReader    = topReader;
                        }
                        else
                        {
                            // We have matched the EndOfContents that brought us here.
                            break;
                        }
                    }
                    else if (tag == Asn1Tag.ConstructedOctetString)
                    {
                        if (RuleSet == AsnEncodingRules.CER)
                        {
                            // T-REC-X.690-201508 sec 9.2
                            throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding"));
                        }

                        if (readerStack == null)
                        {
                            readerStack = new Stack <(AsnReader, bool, int)>();
                        }

                        readerStack.Push((tmpReader, isIndefinite, bytesRead));

                        tmpReader = new AsnReader(
                            Slice(tmpReader._data, headerLength, length),
                            RuleSet);

                        bytesRead    = headerLength;
                        isIndefinite = (length == null);
                    }
                    else
                    {
                        // T-REC-X.690-201508 sec 8.6.4.1 (in particular, Note 2)
                        throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding"));
                    }
                }

                if (isIndefinite && tag != Asn1Tag.EndOfContents)
                {
                    throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding"));
                }

                if (readerStack?.Count > 0)
                {
                    (AsnReader topReader, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();

                    tmpReader       = topReader;
                    tmpReader._data = tmpReader._data.Slice(bytesRead);

                    isIndefinite = wasIndefinite;
                    bytesRead   += pushedBytesRead;
                }
                else
                {
                    tmpReader = null;
                }
            } while (tmpReader != null);

            return(totalLength);
        }