public static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out Rc2CbcParameters decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
        private int CopyConstructedOctetString(
            ReadOnlySpan <byte> source,
            Span <byte> destination,
            bool write,
            bool isIndefinite,
            out int bytesRead)
        {
            bytesRead = 0;
            int lastSegmentLength = MaxCERSegmentSize;

            ReadOnlySpan <byte> originalSpan = _data;
            AsnValueReader      tmpReader    = OpenUnchecked(source, RuleSet);
            Stack <(int Offset, int Length, bool IsIndefinite, int BytesRead)>?readerStack = null;
            int         totalLength = 0;
            Asn1Tag     tag         = Asn1Tag.ConstructedBitString;
            Span <byte> curDest     = destination;

            while (true)
            {
                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.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.
                        ReadOnlySpan <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.Cryptography_Der_Invalid_Encoding);
                        }

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

                        bytesRead += headerLength;

                        if (readerStack?.Count > 0)
                        {
                            (int topOffset, int topLength, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();
                            ReadOnlySpan <byte> topSpan = originalSpan.Slice(topOffset, topLength);
                            tmpReader._data = topSpan.Slice(bytesRead);

                            bytesRead   += pushedBytesRead;
                            isIndefinite = wasIndefinite;
                        }
                        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.Cryptography_Der_Invalid_Encoding);
                        }

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

                        if (!originalSpan.Overlaps(tmpReader._data, out int curOffset))
                        {
                            Debug.Fail("Non-overlapping data encountered...");
                            throw new CryptographicException();
                        }

                        readerStack.Push((curOffset, tmpReader._data.Length, isIndefinite, bytesRead));

                        tmpReader._data = Slice(tmpReader._data, headerLength, length);
                        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)
                {
                    (int topOffset, int topLength, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();
                    ReadOnlySpan <byte> topSpan = originalSpan.Slice(topOffset, topLength);

                    tmpReader._data = topSpan.Slice(bytesRead);

                    isIndefinite = wasIndefinite;
                    bytesRead   += pushedBytesRead;
                }
                else
                {
                    return(totalLength);
                }
            }
        }
예제 #3
0
 internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out SubjectPublicKeyInfoAsn decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
예제 #4
0
 internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out CurveAsn decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
 public static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebind, out X509ExtensionAsn decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
 internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out EncryptedPrivateKeyInfoAsn decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
예제 #7
0
        private int ProcessConstructedBitString(
            ReadOnlySpan <byte> source,
            Span <byte> destination,
            BitStringCopyAction?copyAction,
            bool isIndefinite,
            out int lastUnusedBitCount,
            out int bytesRead)
        {
            lastUnusedBitCount = 0;
            bytesRead          = 0;
            int lastSegmentLength = MaxCERSegmentSize;

            ReadOnlySpan <byte> originalSpan = _data;
            AsnValueReader      tmpReader    = OpenUnchecked(source, RuleSet);
            Stack <(int Offset, int Length, bool Indefinite, int BytesRead)>?readerStack = null;
            int         totalLength = 0;
            Asn1Tag     tag         = Asn1Tag.ConstructedBitString;
            Span <byte> curDest     = destination;

            while (true)
            {
                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);
                        ReadOnlySpan <byte> encodedValue = Slice(tmpReader._data, headerLength, length.Value);

                        ParsePrimitiveBitStringContents(
                            encodedValue,
                            out lastUnusedBitCount,
                            out ReadOnlySpan <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)
                        {
                            (int topOffset, int topLength, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();
                            ReadOnlySpan <byte> topSpan = originalSpan.Slice(topOffset, topLength);
                            tmpReader._data = topSpan.Slice(bytesRead);

                            bytesRead   += pushedBytesRead;
                            isIndefinite = wasIndefinite;
                        }
                        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 <(int, int, bool, int)>();
                        }

                        if (!originalSpan.Overlaps(tmpReader._data, out int curOffset))
                        {
                            Debug.Fail("Non-overlapping data encountered...");
                            throw new CryptographicException();
                        }

                        readerStack.Push((curOffset, tmpReader._data.Length, isIndefinite, bytesRead));

                        tmpReader._data = Slice(tmpReader._data, headerLength, length);
                        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)
                {
                    (int topOffset, int topLength, bool wasIndefinite, int pushedBytesRead) = readerStack.Pop();

                    ReadOnlySpan <byte> tmpSpan = originalSpan.Slice(topOffset, topLength);
                    tmpReader._data = tmpSpan.Slice(bytesRead);

                    isIndefinite = wasIndefinite;
                    bytesRead   += pushedBytesRead;
                }
                else
                {
                    return(totalLength);
                }
            }
        }
예제 #8
0
 public static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out OaepParamsAsn decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
 public static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out AlgorithmIdentifierAsn decoded)
 {
     Decode(ref reader, Asn1Tag.Sequence, rebind, out decoded);
 }
예제 #10
0
        public static void Decode(ref AsnValueReader reader, ReadOnlyMemory <byte> rebind, out GeneralNameAsn decoded)
        {
            decoded = default;
            Asn1Tag             tag = reader.PeekTag();
            AsnValueReader      explicitReader;
            ReadOnlySpan <byte> rebindSpan = rebind.Span;
            int offset;
            ReadOnlySpan <byte> tmpSpan;

            if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 0)))
            {
                Medikit.Security.Cryptography.Asn1.OtherNameAsn tmpOtherName;
                Medikit.Security.Cryptography.Asn1.OtherNameAsn.Decode(ref reader, new Asn1Tag(TagClass.ContextSpecific, 0), rebind, out tmpOtherName);
                decoded.OtherName = tmpOtherName;
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                decoded.Rfc822Name = reader.ReadCharacterString(new Asn1Tag(TagClass.ContextSpecific, 1), UniversalTagNumber.IA5String);
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 2)))
            {
                decoded.DnsName = reader.ReadCharacterString(new Asn1Tag(TagClass.ContextSpecific, 2), UniversalTagNumber.IA5String);
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 3)))
            {
                tmpSpan             = reader.ReadEncodedValue();
                decoded.X400Address = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 4)))
            {
                explicitReader        = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 4));
                tmpSpan               = explicitReader.ReadEncodedValue();
                decoded.DirectoryName = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
                explicitReader.ThrowIfNotEmpty();
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 5)))
            {
                Medikit.Security.Cryptography.Asn1.EdiPartyNameAsn tmpEdiPartyName;
                Medikit.Security.Cryptography.Asn1.EdiPartyNameAsn.Decode(ref reader, new Asn1Tag(TagClass.ContextSpecific, 5), rebind, out tmpEdiPartyName);
                decoded.EdiPartyName = tmpEdiPartyName;
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 6)))
            {
                decoded.Uri = reader.ReadCharacterString(new Asn1Tag(TagClass.ContextSpecific, 6), UniversalTagNumber.IA5String);
            }
            else if (tag.HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 7)))
            {
                if (reader.TryReadPrimitiveOctetStringBytes(new Asn1Tag(TagClass.ContextSpecific, 7), out tmpSpan))
                {
                    decoded.IPAddress = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
                }
                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();
            }
        }
예제 #11
0
        internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory <byte> rebind, out PssParamsAsn decoded)
        {
            decoded = default;
            AsnValueReader sequenceReader = reader.ReadSequence(expectedTag);
            AsnValueReader explicitReader;
            AsnValueReader defaultReader;


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


            if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(new Asn1Tag(TagClass.ContextSpecific, 1)))
            {
                explicitReader = sequenceReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 1));
                Medikit.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(ref explicitReader, rebind, out decoded.MaskGenAlgorithm);
                explicitReader.ThrowIfNotEmpty();
            }
            else
            {
                defaultReader = new AsnValueReader(DefaultMaskGenAlgorithm, AsnEncodingRules.DER);
                Medikit.Security.Cryptography.Asn1.AlgorithmIdentifierAsn.Decode(ref defaultReader, rebind, 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 AsnValueReader(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 AsnValueReader(DefaultTrailerField, AsnEncodingRules.DER);

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


            sequenceReader.ThrowIfNotEmpty();
        }