private ReadOnlyMemory <byte> GetIntegerContents( Asn1Tag expectedTag, UniversalTagNumber tagNumber, out int headerLength) { Asn1Tag tag = ReadTagAndLength(out int?length, out headerLength); CheckExpectedTag(tag, expectedTag, tagNumber); // T-REC-X.690-201508 sec 8.3.1 if (tag.IsConstructed || length < 1) { throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding")); } // Slice first so that an out of bounds value triggers a CryptographicException. ReadOnlyMemory <byte> contents = Slice(_data, headerLength, length.Value); ReadOnlySpan <byte> contentSpan = contents.Span; // T-REC-X.690-201508 sec 8.3.2 if (contents.Length > 1) { ushort bigEndianValue = (ushort)(contentSpan[0] << 8 | contentSpan[1]); const ushort RedundancyMask = 0b1111_1111_1000_0000; ushort masked = (ushort)(bigEndianValue & RedundancyMask); // If the first 9 bits are all 0 or are all 1, the value is invalid. if (masked == 0 || masked == RedundancyMask) { throw new CryptographicException(SR.Resource("Cryptography_Der_Invalid_Encoding")); } } return(contents); }
/// <summary> /// Write the provided string using the specified encoding type using the specified /// tag corresponding to the encoding type. /// </summary> /// <param name="tag">The tag to write.</param> /// <param name="encodingType"> /// The <see cref="UniversalTagNumber"/> corresponding to the encoding to use. /// </param> /// <param name="str">The string to write.</param> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a restricted character string encoding type --OR-- /// <paramref name="encodingType"/> is a restricted character string encoding type that is not /// currently supported by this method /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="tag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="tag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for /// the method /// </exception> /// <exception cref="ObjectDisposedException">The writer has been Disposed.</exception> public void WriteCharacterString(Asn1Tag tag, UniversalTagNumber encodingType, ReadOnlySpan <char> str) { CheckUniversalTag(tag, encodingType); Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); this.WriteCharacterStringCore(tag, encoding, str); }
private bool TryReadPrimitiveOctetStringBytes( Asn1Tag expectedTag, out Asn1Tag actualTag, out int?contentLength, out int headerLength, out ReadOnlySpan <byte> contents, UniversalTagNumber universalTagNumber = UniversalTagNumber.OctetString) { actualTag = ReadTagAndLength(out contentLength, out headerLength); CheckExpectedTag(actualTag, expectedTag, universalTagNumber); if (actualTag.IsConstructed) { if (RuleSet == AsnEncodingRules.DER) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } contents = default; return(false); } Debug.Assert(contentLength.HasValue); ReadOnlySpan <byte> encodedValue = Slice(_data, headerLength, contentLength.Value); if (RuleSet == AsnEncodingRules.CER && encodedValue.Length > MaxCERSegmentSize) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); } contents = encodedValue; return(true); }
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); }
/// <summary> /// Write the provided string using the specified encoding type using the specified /// tag corresponding to the encoding type. /// </summary> /// <param name="encodingType"> /// One of the enumeration values representing the encoding to use. /// </param> /// <param name="str">The string to write.</param> /// <param name="tag"> /// The tag to write, or <see langword="null"/> for the universal tag that is appropriate to /// the requested encoding type. /// </param> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a restricted character string encoding type. /// /// -or- /// /// <paramref name="encodingType"/> is a restricted character string encoding type that is not /// currently supported by this method. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="tag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="tag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for /// the method. /// </exception> public void WriteCharacterString(UniversalTagNumber encodingType, ReadOnlySpan <char> str, Asn1Tag?tag = null) { CheckUniversalTag(tag, encodingType); Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); WriteCharacterStringCore(tag ?? new Asn1Tag(encodingType), encoding, str); }
/// <summary> /// Attempts to get an unprocessed character string value from <paramref name="source"/> with a /// specified tag under the specified encoding rules, if the value is contained in a single /// (primitive) encoding. /// </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="expectedTag"> /// The tag to check for before reading. /// </param> /// <param name="value"> /// On success, receives a slice of the input buffer that corresponds to /// the value of the Bit String. /// 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> /// <see langword="true"/> if the character string value has a primitive encoding; /// otherwise, <see langword="false"/>. /// </returns> /// <remarks> /// This method does not determine if the string used only characters defined by the encoding. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="ruleSet"/> is not defined. /// </exception> /// <exception cref="AsnContentException"> /// the next value does not have the correct tag. /// /// -or- /// /// the length encoding is not valid under the current encoding rules. /// /// -or- /// /// the contents are not valid under the current encoding rules. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not a character /// string tag type. /// </exception> /// <seealso cref="TryReadCharacterStringBytes"/> public static bool TryReadPrimitiveCharacterStringBytes( ReadOnlySpan <byte> source, AsnEncodingRules ruleSet, Asn1Tag expectedTag, out ReadOnlySpan <byte> value, out int bytesConsumed) { // This doesn't matter, except for universal tags. It's eventually used to check that // we're not expecting the wrong universal tag; but we'll remove the need for that by // IsCharacterStringEncodingType. UniversalTagNumber universalTagNumber = UniversalTagNumber.IA5String; if (expectedTag.TagClass == TagClass.Universal) { universalTagNumber = (UniversalTagNumber)expectedTag.TagValue; if (!IsCharacterStringEncodingType(universalTagNumber)) { throw new ArgumentException(SR.Argument_Tag_NotCharacterString, nameof(expectedTag)); } } // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings. return(TryReadPrimitiveOctetStringCore( source, ruleSet, expectedTag, universalTagNumber, contentLength: out _, headerLength: out _, out value, out bytesConsumed)); }
private void EncodeComponent( string oid, ReadOnlySpan <char> value, UniversalTagNumber stringEncodingType, [CallerArgumentExpression("value")] string?paramName = null) { _writer.Reset(); using (_writer.PushSetOf()) using (_writer.PushSequence()) { _writer.WriteObjectIdentifier(oid); try { _writer.WriteCharacterString(stringEncodingType, value); } catch (EncoderFallbackException) { throw new ArgumentException(SR.Format(SR.Argument_Asn1_InvalidStringContents, stringEncodingType), paramName); } } _encodedComponents.Add(_writer.Encode()); }
internal static Text.Encoding GetEncoding(UniversalTagNumber encodingType) { switch (encodingType) { case UniversalTagNumber.UTF8String: return(s_utf8Encoding); case UniversalTagNumber.PrintableString: return(s_printableStringEncoding); case UniversalTagNumber.IA5String: return(s_ia5Encoding); case UniversalTagNumber.VisibleString: return(s_visibleStringEncoding); case UniversalTagNumber.BMPString: return(s_bmpEncoding); case UniversalTagNumber.T61String: return(s_t61Encoding); default: throw new ArgumentOutOfRangeException(nameof(encodingType), encodingType, null); } }
internal static Text.Encoding GetEncoding(UniversalTagNumber encodingType) { switch (encodingType) { case UniversalTagNumber.UTF8String: return(Utf8Encoding); case UniversalTagNumber.NumericString: return(NumericStringEncoding); case UniversalTagNumber.PrintableString: return(PrintableStringEncoding); case UniversalTagNumber.IA5String: return(Ia5Encoding); case UniversalTagNumber.GeneralString: return(GeneralStringEncoding); case UniversalTagNumber.VisibleString: return(VisibleStringEncoding); case UniversalTagNumber.BMPString: return(BmpEncoding); case UniversalTagNumber.T61String: return(T61Encoding); default: throw new ArgumentOutOfRangeException(nameof(encodingType), encodingType, null); } }
internal string ReadCharacterString(UniversalTagNumber encodingType, Asn1Tag?expectedTag = default) { string ret = AsnDecoder.ReadCharacterString(_span, _ruleSet, encodingType, out int consumed, expectedTag); _span = _span.Slice(consumed); return(ret); }
private bool TryReadSignedInteger( int sizeLimit, Asn1Tag expectedTag, UniversalTagNumber tagNumber, out long value) { Debug.Assert(sizeLimit <= sizeof(long)); ReadOnlyMemory <byte> contents = GetIntegerContents(expectedTag, tagNumber, out int headerLength); if (contents.Length > sizeLimit) { value = 0; return(false); } ReadOnlySpan <byte> contentSpan = contents.Span; bool isNegative = (contentSpan[0] & 0x80) != 0; long accum = isNegative ? -1 : 0; for (int i = 0; i < contents.Length; i++) { accum <<= 8; accum |= contentSpan[i]; } _data = _data.Slice(headerLength + contents.Length); value = accum; return(true); }
private static ReadOnlySpan <byte> GetOctetStringContents( ReadOnlySpan <byte> source, AsnEncodingRules ruleSet, Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, out int bytesConsumed, ref byte[]?rented, Span <byte> tmpSpace = default) { Debug.Assert(rented == null); if (TryReadPrimitiveOctetStringCore( source, ruleSet, expectedTag, universalTagNumber, out int?contentLength, out int headerLength, out ReadOnlySpan <byte> contents, out bytesConsumed)) { return(contents); } // If we get here, the tag was appropriate, but the encoding was constructed. // Guaranteed long enough contents = source.Slice(headerLength); int tooBig = contentLength ?? SeekEndOfContents(contents, ruleSet); if (tmpSpace.Length > 0 && tooBig > tmpSpace.Length) { bool isIndefinite = contentLength == null; tooBig = CountConstructedOctetString(contents, ruleSet, isIndefinite); } if (tooBig > tmpSpace.Length) { rented = CryptoPool.Rent(tooBig); tmpSpace = rented; } if (TryCopyConstructedOctetStringContents( Slice(source, headerLength, contentLength), ruleSet, tmpSpace, contentLength == null, out int bytesRead, out int bytesWritten)) { bytesConsumed = headerLength + bytesRead; return(tmpSpace.Slice(0, bytesWritten)); } Debug.Fail("TryCopyConstructedOctetStringContents failed with a pre-allocated buffer"); throw new AsnContentException(); }
/// <summary> /// Write the provided string using the specified encoding type using the specified /// tag corresponding to the encoding type. /// </summary> /// <param name="encodingType"> /// One of the enumeration values representing the encoding to use. /// </param> /// <param name="value">The string to write.</param> /// <param name="tag"> /// The tag to write, or <see langword="null"/> for the universal tag that is appropriate to /// the requested encoding type. /// </param> /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/></exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a restricted character string encoding type. /// /// -or- /// /// <paramref name="encodingType"/> is a restricted character string encoding type that is not /// currently supported by this method. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="tag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="tag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for /// the method. /// </exception> public void WriteCharacterString(UniversalTagNumber encodingType, string value, Asn1Tag?tag = null) { if (value == null) { throw new ArgumentNullException(nameof(value)); } WriteCharacterString(encodingType, value.AsSpan(), tag); }
private static void WriteRdn(AsnWriter writer, string oid, string value, UniversalTagNumber valueType) { writer.PushSetOf(); writer.PushSequence(); writer.WriteObjectIdentifier(oid); writer.WriteCharacterString(valueType, value); writer.PopSequence(); writer.PopSetOf(); }
/// <summary> /// Write the provided string using the specified encoding type using the specified /// tag corresponding to the encoding type. /// </summary> /// <param name="tag">The tag to write.</param> /// <param name="encodingType"> /// The <see cref="UniversalTagNumber"/> corresponding to the encoding to use. /// </param> /// <param name="str">The string to write.</param> /// <exception cref="ArgumentNullException"><paramref name="str"/> is <c>null</c></exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a restricted character string encoding type --OR-- /// <paramref name="encodingType"/> is a restricted character string encoding type that is not /// currently supported by this method /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="tag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="tag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for /// the method /// </exception> /// <exception cref="ObjectDisposedException">The writer has been Disposed.</exception> public void WriteCharacterString(Asn1Tag tag, UniversalTagNumber encodingType, string str) { if (str == null) { throw new ArgumentNullException(nameof(str)); } WriteCharacterString(tag, encodingType, str.AsSpan()); }
/// <summary> /// Adds a Relative Distinguished Name attribute identified by an OID. /// </summary> /// <param name="oidValue">The OID of the attribute.</param> /// <param name="value">The value of the attribute.</param> /// <param name="stringEncodingType"> /// The encoding type to use when encoding the <paramref name="value" /> /// in to the attribute. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="oidValue" /> or <paramref name="value" /> is <see langword="null" />. /// </exception> /// <exception cref="ArgumentException"> /// <para> /// <paramref name="oidValue" /> is an empty string or not a valid OID. /// </para> /// <para>-or-</para> /// <para> /// <paramref name="stringEncodingType" /> is not a type for character strings. /// </para> /// <para>-or-</para> /// <para> /// <paramref name="value" /> is not encodable as defined by <paramref name="stringEncodingType" />. /// </para> /// </exception> public void Add(string oidValue, string value, UniversalTagNumber?stringEncodingType = null) { ArgumentNullException.ThrowIfNull(value); ArgumentException.ThrowIfNullOrEmpty(oidValue); UniversalTagNumber tag = GetAndValidateTagNumber(stringEncodingType); EncodeComponent(oidValue, value, tag); }
/// <summary> /// Reads the next value as character string with the specified tag and /// encoding type, copying the decoded value into a provided destination buffer. /// </summary> /// <param name="expectedTag">The tag to check for before reading.</param> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="charsWritten"> /// On success, receives the number of chars written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules --OR-- /// the string did not successfully decode /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as /// <paramref name="encodingType"/>. /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(Asn1Tag,UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="TryCopyCharacterStringBytes(Asn1Tag,UniversalTagNumber,Span{byte},out int)"/> /// <seealso cref="ReadCharacterString(Asn1Tag,UniversalTagNumber)"/> public bool TryCopyCharacterString( Asn1Tag expectedTag, UniversalTagNumber encodingType, Span <char> destination, out int charsWritten) { Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); return(TryCopyCharacterString(expectedTag, encodingType, encoding, destination, out charsWritten)); }
/// <summary> /// Reads the next value as character string with a UNIVERSAL tag appropriate to the specified /// encoding type, returning the contents as an unprocessed <see cref="ReadOnlyMemory{T}"/> /// over the original data. /// </summary> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="contents"> /// On success, receives a <see cref="ReadOnlyMemory{T}"/> over the original data /// corresponding to the contents of the character string. /// </param> /// <returns> /// <c>true</c> and advances the reader if the value had a primitive encoding, /// <c>false</c> and does not advance the reader if it had a constructed encoding. /// </returns> /// <remarks> /// This method does not determine if the string used only characters defined by the encoding. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules /// </exception> /// <seealso cref="TryCopyCharacterStringBytes(UniversalTagNumber,Span{byte},out int)"/> public bool TryReadPrimitiveCharacterStringBytes( UniversalTagNumber encodingType, out ReadOnlyMemory <byte> contents) { return(TryReadPrimitiveCharacterStringBytes( new Asn1Tag(encodingType), encodingType, out contents)); }
/// <summary> /// Reads the next value as a character with a specified tag, returning the contents /// as an unprocessed <see cref="ReadOnlyMemory{T}"/> over the original data. /// </summary> /// <param name="expectedTag">The tag to check for before reading.</param> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="contents"> /// On success, receives a <see cref="ReadOnlyMemory{T}"/> over the original data /// corresponding to the value of the OCTET STRING. /// </param> /// <returns> /// <c>true</c> and advances the reader if the OCTET STRING value had a primitive encoding, /// <c>false</c> and does not advance the reader if it had a constructed encoding. /// </returns> /// <remarks> /// This method does not determine if the string used only characters defined by the encoding. /// </remarks> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as /// <paramref name="encodingType"/>. /// </exception> /// <seealso cref="TryCopyCharacterStringBytes(Asn1Tag,UniversalTagNumber,Span{byte},out int)"/> public bool TryReadPrimitiveCharacterStringBytes( Asn1Tag expectedTag, UniversalTagNumber encodingType, out ReadOnlyMemory <byte> contents) { CheckCharacterStringEncodingType(encodingType); // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings. return(TryReadPrimitiveOctetStringBytes(expectedTag, encodingType, out contents)); }
/// <summary> /// Reads the next value as character string with a UNIVERSAL tag appropriate to the specified /// encoding type, copying the decoded value into a provided destination buffer. /// </summary> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="charsWritten"> /// On success, receives the number of chars written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules --OR-- /// the string did not successfully decode /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="ReadCharacterString(UniversalTagNumber)"/> /// <seealso cref="TryCopyCharacterStringBytes(UniversalTagNumber,ArraySegment{byte},out int)"/> /// <seealso cref="TryCopyCharacterString(Asn1Tag,UniversalTagNumber,ArraySegment{char},out int)"/> public bool TryCopyCharacterString( UniversalTagNumber encodingType, ArraySegment <char> destination, out int charsWritten) { return(TryCopyCharacterString( new Asn1Tag(encodingType), encodingType, destination.AsSpan(), out charsWritten)); }
/// <summary> /// Reads the next value as character string with a UNIVERSAL tag appropriate to the specified /// encoding type, copying the value into a provided destination buffer. /// </summary> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="bytesWritten"> /// On success, receives the number of bytes written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <remarks> /// This method does not determine if the string used only characters defined by the encoding. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="ReadCharacterString(UniversalTagNumber)"/> /// <seealso cref="TryCopyCharacterString(UniversalTagNumber,Span{char},out int)"/> public bool TryCopyCharacterStringBytes( UniversalTagNumber encodingType, Span <byte> destination, out int bytesWritten) { return(TryCopyCharacterStringBytes( new Asn1Tag(encodingType), encodingType, destination, out bytesWritten)); }
/// <summary> /// Reads the next value as character string with a UNIVERSAL tag appropriate to the specified /// encoding type, copying the decoded value into a provided destination buffer. /// </summary> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="charsWritten"> /// On success, receives the number of chars written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules --OR-- /// the string did not successfully decode /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="ReadCharacterString(UniversalTagNumber)"/> /// <seealso cref="TryCopyCharacterStringBytes(UniversalTagNumber,Span{byte},out int)"/> public bool TryCopyCharacterString( UniversalTagNumber encodingType, Span <char> destination, out int charsWritten) { return(this.TryCopyCharacterString( new Asn1Tag(encodingType), encodingType, destination, out charsWritten)); }
/// <summary> /// Reads the next value as character string with a UNIVERSAL tag appropriate to the specified /// encoding type, copying the value into a provided destination buffer. /// </summary> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="bytesWritten"> /// On success, receives the number of bytes written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <remarks> /// This method does not determine if the string used only characters defined by the encoding. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="ReadCharacterString(UniversalTagNumber)"/> /// <seealso cref="TryCopyCharacterString(UniversalTagNumber,Span{char},out int)"/> public bool TryCopyCharacterStringBytes( UniversalTagNumber encodingType, ArraySegment <byte> destination, out int bytesWritten) { return(this.TryCopyCharacterStringBytes( new Asn1Tag(encodingType), encodingType, destination.AsSpan(), out bytesWritten)); }
/// <summary> /// Reads the next value as character string with the specified tag and /// encoding type, copying the value into a provided destination buffer. /// </summary> /// <param name="expectedTag">The tag to check for before reading.</param> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="bytesWritten"> /// On success, receives the number of bytes written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <remarks> /// This method does not determine if the string used only characters defined by the encoding. /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as /// <paramref name="encodingType"/>. /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(Asn1Tag,UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="ReadCharacterString(Asn1Tag,UniversalTagNumber)"/> /// <seealso cref="TryCopyCharacterString(Asn1Tag,UniversalTagNumber,Span{char},out int)"/> public bool TryCopyCharacterStringBytes( Asn1Tag expectedTag, UniversalTagNumber encodingType, ArraySegment <byte> destination, out int bytesWritten) { return(TryCopyCharacterStringBytes( expectedTag, encodingType, destination.AsSpan(), out bytesWritten)); }
private Scope PushTag(Asn1Tag tag, UniversalTagNumber tagType) { _nestingStack ??= new Stack <StackFrame>(); Debug.Assert(tag.IsConstructed); WriteTag(tag); _nestingStack.Push(new StackFrame(tag, _offset, tagType)); // Indicate that the length is indefinite. // We'll come back and clean this up (as appropriate) in PopTag. WriteLength(-1); return(new Scope(this)); }
/// <summary> /// Reads the next value as character string with the specified tag and /// encoding type, returning the decoded value as a string. /// </summary> /// <param name="encodingType"> /// One of the enumeration values representing the value type to process. /// </param> /// <param name="expectedTag"> /// The tag to check for before reading, or <see langword="null"/> for the universal tag that is /// appropriate to the requested encoding type. /// </param> /// <returns> /// The decoded value. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="AsnContentException"> /// the next value does not have the correct tag. /// /// -or- /// /// the length encoding is not valid under the current encoding rules. /// /// -or- /// /// the contents are not valid under the current encoding rules. /// /// -or- /// /// the string did not successfully decode. /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as /// <paramref name="encodingType"/>. /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes"/> /// <seealso cref="TryReadCharacterStringBytes"/> /// <seealso cref="TryReadCharacterString"/> public string ReadCharacterString(UniversalTagNumber encodingType, Asn1Tag?expectedTag = null) { string ret = AsnDecoder.ReadCharacterString( _data.Span, RuleSet, encodingType, out int consumed, expectedTag); _data = _data.Slice(consumed); return(ret); }
/// <summary> /// Reads the next value as character string with the specified tag and /// encoding type, copying the decoded value into a provided destination buffer. /// </summary> /// <param name="expectedTag">The tag to check for before reading.</param> /// <param name="encodingType"> /// A <see cref="UniversalTagNumber"/> corresponding to the value type to process. /// </param> /// <param name="destination">The buffer in which to write.</param> /// <param name="charsWritten"> /// On success, receives the number of chars written to <paramref name="destination"/>. /// </param> /// <returns> /// <c>true</c> and advances the reader if <paramref name="destination"/> had sufficient /// length to receive the value, otherwise /// <c>false</c> and the reader does not advance. /// </returns> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="encodingType"/> is not a known character string type. /// </exception> /// <exception cref="CryptographicException"> /// the next value does not have the correct tag --OR-- /// the length encoding is not valid under the current encoding rules --OR-- /// the contents are not valid under the current encoding rules --OR-- /// the string did not successfully decode /// </exception> /// <exception cref="ArgumentException"> /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is /// <see cref="TagClass.Universal"/>, but /// <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not the same as /// <paramref name="encodingType"/>. /// </exception> /// <seealso cref="TryReadPrimitiveCharacterStringBytes(Asn1Tag,UniversalTagNumber,out ReadOnlyMemory{byte})"/> /// <seealso cref="TryCopyCharacterStringBytes(Asn1Tag,UniversalTagNumber,ArraySegment{byte},out int)"/> /// <seealso cref="ReadCharacterString(Asn1Tag,UniversalTagNumber)"/> public bool TryCopyCharacterString( Asn1Tag expectedTag, UniversalTagNumber encodingType, ArraySegment <char> destination, out int charsWritten) { return(this.TryCopyCharacterString( expectedTag, encodingType, destination.AsSpan(), out charsWritten)); }
// T-REC-X.690-201508 sec 8.23 private static bool TryReadCharacterStringBytesCore( ReadOnlySpan <byte> source, AsnEncodingRules ruleSet, Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, Span <byte> destination, out int bytesConsumed, out int bytesWritten) { // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings. if (TryReadPrimitiveOctetStringCore( source, ruleSet, expectedTag, universalTagNumber, out int?contentLength, out int headerLength, out ReadOnlySpan <byte> contents, out int consumed)) { if (contents.Length > destination.Length) { bytesWritten = 0; bytesConsumed = 0; return(false); } contents.CopyTo(destination); bytesWritten = contents.Length; bytesConsumed = consumed; return(true); } bool copied = TryCopyConstructedOctetStringContents( Slice(source, headerLength, contentLength), ruleSet, destination, contentLength == null, out int bytesRead, out bytesWritten); if (copied) { bytesConsumed = headerLength + bytesRead; } else { bytesConsumed = 0; } return(copied); }
private static bool TryReadUnsignedInteger( ReadOnlySpan <byte> source, AsnEncodingRules ruleSet, int sizeLimit, Asn1Tag expectedTag, UniversalTagNumber tagNumber, out ulong value, out int bytesConsumed) { Debug.Assert(sizeLimit <= sizeof(ulong)); ReadOnlySpan <byte> contents = GetIntegerContents( source, ruleSet, expectedTag, tagNumber, out int consumed); bool isNegative = (contents[0] & 0x80) != 0; if (isNegative) { bytesConsumed = 0; value = 0; return(false); } // Ignore any padding zeros. if (contents.Length > 1 && contents[0] == 0) { contents = contents.Slice(1); } if (contents.Length > sizeLimit) { bytesConsumed = 0; value = 0; return(false); } ulong accum = 0; for (int i = 0; i < contents.Length; i++) { accum <<= 8; accum |= contents[i]; } bytesConsumed = consumed; value = accum; return(true); }
private string ReadCharacterString( Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, Text.Encoding encoding) { byte[] rented = null; // T-REC-X.690-201508 sec 8.23.3, all character strings are encoded as octet strings. ReadOnlySpan <byte> contents = GetOctetStringContents( expectedTag, universalTagNumber, out int bytesRead, ref rented); try { string str; if (contents.Length == 0) { str = string.Empty; } else { unsafe { fixed(byte *bytePtr = &MemoryMarshal.GetReference(contents)) { try { str = encoding.GetString(bytePtr, contents.Length); } catch (DecoderFallbackException e) { throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e); } } } } _data = _data.Slice(bytesRead); return(str); } finally { if (rented != null) { Array.Clear(rented, 0, contents.Length); ArrayPool <byte> .Shared.Return(rented); } } }