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); }
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); }
/// <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); }
internal Asn1Tag PeekTag() { return(Asn1Tag.Decode(_span, out _)); }