예제 #1
0
        private static ReadOnlySpan <byte> GetPrimitiveContentSpan(
            ReadOnlySpan <byte> source,
            AsnEncodingRules ruleSet,
            Asn1Tag expectedTag,
            UniversalTagNumber tagNumber,
            out int bytesConsumed)
        {
            CheckEncodingRules(ruleSet);

            Asn1Tag localTag      = Asn1Tag.Decode(source, out int tagLength);
            int?    encodedLength = ReadLength(source.Slice(tagLength), ruleSet, out int lengthLength);
            int     headerLength  = tagLength + lengthLength;

            // Get caller(-of-my-caller) errors out of the way, first.
            CheckExpectedTag(localTag, expectedTag, tagNumber);

            // T-REC-X.690-201508 sec 8.1.3.2 says primitive encodings must use a definite form,
            // and the caller says they only want primitive values.
            if (localTag.IsConstructed)
            {
                throw new AsnContentException(
                          SR.Format(SR.ContentException_PrimitiveEncodingRequired, tagNumber));
            }

            if (encodedLength == null)
            {
                throw new AsnContentException();
            }

            ReadOnlySpan <byte> ret = Slice(source, headerLength, encodedLength.Value);

            bytesConsumed = headerLength + ret.Length;
            return(ret);
        }
예제 #2
0
        private static Asn1Tag ReadTagAndLength(
            ReadOnlySpan <byte> source,
            AsnEncodingRules ruleSet,
            out int?contentsLength,
            out int bytesRead)
        {
            Asn1Tag tag    = Asn1Tag.Decode(source, out int tagBytesRead);
            int?    length = ReadLength(source.Slice(tagBytesRead), ruleSet, out int lengthBytesRead);

            int allBytesRead = tagBytesRead + lengthBytesRead;

            if (tag.IsConstructed)
            {
                // T-REC-X.690-201508 sec 9.1 (CER: Length forms) says constructed is always indefinite.
                if (ruleSet == AsnEncodingRules.CER && length != null)
                {
                    throw GetValidityException(LengthValidity.CerRequiresIndefinite);
                }
            }
            else if (length == null)
            {
                // T-REC-X.690-201508 sec 8.1.3.2 says primitive encodings must use a definite form.
                throw GetValidityException(LengthValidity.PrimitiveEncodingRequiresDefinite);
            }

            bytesRead      = allBytesRead;
            contentsLength = length;
            return(tag);
        }
예제 #3
0
        /// <summary>
        ///   Locates the contents range for the encoded value at the beginning of the
        ///   <paramref name="source"/> buffer using the specified encoding rules.
        /// </summary>
        /// <param name="source">The buffer containing encoded data.</param>
        /// <param name="ruleSet">The encoding constraints to use when interpreting the data.</param>
        /// <param name="contentOffset">
        ///   When this method returns, the offset of the content payload relative to the start of
        ///   <paramref name="source"/>.
        ///   This parameter is treated as uninitialized.
        /// </param>
        /// <param name="contentLength">
        ///   When this method returns, the number of bytes in the content payload (which may be 0).
        ///   This parameter is treated as uninitialized.
        /// </param>
        /// <param name="bytesConsumed">
        ///   When this method returns, the total number of bytes for the encoded value.
        ///   This parameter is treated as uninitialized.
        /// </param>
        /// <returns>
        ///   The tag identifying the content.
        /// </returns>
        /// <remarks>
        ///   <para>
        ///     This method performs very little validation on the contents.
        ///     If the encoded value uses a definite length, the contents are not inspected at all.
        ///     If the encoded value uses an indefinite length, the contents are only inspected
        ///     as necessary to determine the location of the relevant end-of-contents marker.
        ///   </para>
        ///   <para>
        ///     When the encoded value uses an indefinite length, the <paramref name="bytesConsumed"/>
        ///     value will be larger than the sum of <paramref name="contentOffset"/> and
        ///     <paramref name="contentLength"/> to account for the end-of-contents marker.
        ///   </para>
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException">
        ///   <paramref name="ruleSet"/> is not defined.
        /// </exception>
        /// <exception cref="AsnContentException">
        ///   <paramref name="source"/> does not represent a value encoded under the specified
        ///   encoding rules.
        /// </exception>
        public static Asn1Tag ReadEncodedValue(
            ReadOnlySpan <byte> source,
            AsnEncodingRules ruleSet,
            out int contentOffset,
            out int contentLength,
            out int bytesConsumed)
        {
            CheckEncodingRules(ruleSet);

            Asn1Tag tag           = Asn1Tag.Decode(source, out int tagLength);
            int?    encodedLength = ReadLength(source.Slice(tagLength), ruleSet, out int lengthLength);
            int     headerLength  = tagLength + lengthLength;

            LengthValidity validity = ValidateLength(
                source.Slice(headerLength),
                ruleSet,
                tag,
                encodedLength,
                out int len,
                out int consumed);

            if (validity == LengthValidity.Valid)
            {
                contentOffset = headerLength;
                contentLength = len;
                bytesConsumed = headerLength + consumed;
                return(tag);
            }

            throw GetValidityException(validity);
        }
예제 #4
0
 internal Asn1Tag PeekTag()
 {
     return(Asn1Tag.Decode(_span, out _));
 }