예제 #1
0
        // T-REC-X.690-201508 sec 9.2, 8.6
        private void WriteConstructedCerBitString(Asn1Tag tag, ReadOnlySpan <byte> payload, int unusedBitCount)
        {
            const int MaxCERSegmentSize = AsnReader.MaxCERSegmentSize;

            // Every segment has an "unused bit count" byte.
            const int MaxCERContentSize = MaxCERSegmentSize - 1;

            Debug.Assert(payload.Length > MaxCERContentSize);

            int expectedSize = DetermineCerBitStringTotalLength(tag, payload.Length);

            this.EnsureWriteCapacity(expectedSize);
            int savedOffset = this._offset;

            this.WriteTag(tag.AsConstructed());

            // T-REC-X.690-201508 sec 9.1
            // Constructed CER uses the indefinite form.
            this.WriteLength(-1);

            byte[] ensureNoExtraCopy = this._buffer;

            ReadOnlySpan <byte> remainingData = payload;
            Span <byte>         dest;
            Asn1Tag             primitiveBitString = Asn1Tag.PrimitiveBitString;

            while (remainingData.Length > MaxCERContentSize)
            {
                // T-REC-X.690-201508 sec 8.6.4.1
                this.WriteTag(primitiveBitString);
                this.WriteLength(MaxCERSegmentSize);

                // 0 unused bits in this segment.
                this._buffer[this._offset] = 0;
                this._offset++;

                dest = this._buffer.AsSpan(this._offset);
                remainingData.Slice(0, MaxCERContentSize).CopyTo(dest);

                remainingData = remainingData.Slice(MaxCERContentSize);
                this._offset += MaxCERContentSize;
            }

            this.WriteTag(primitiveBitString);
            this.WriteLength(remainingData.Length + 1);

            this._buffer[this._offset] = (byte)unusedBitCount;
            this._offset++;

            dest = this._buffer.AsSpan(this._offset);
            remainingData.CopyTo(dest);
            this._offset += remainingData.Length;

            this.WriteEndOfContents();

            Debug.Assert(this._offset - savedOffset == expectedSize, $"expected size was {expectedSize}, actual was {this._offset - savedOffset}");
            Debug.Assert(this._buffer == ensureNoExtraCopy, $"_buffer was replaced during {nameof(this.WriteConstructedCerBitString)}");
        }
예제 #2
0
        // T-REC-X.690-201508 sec 9.2, 8.6
        private void WriteConstructedCerBitString(Asn1Tag tag, ReadOnlySpan <byte> payload, int unusedBitCount)
        {
            const int MaxCERSegmentSize = AsnReader.MaxCERSegmentSize;
            // Every segment has an "unused bit count" byte.
            const int MaxCERContentSize = MaxCERSegmentSize - 1;

            Debug.Assert(payload.Length > MaxCERContentSize);

            WriteTag(tag.AsConstructed());
            // T-REC-X.690-201508 sec 9.1
            // Constructed CER uses the indefinite form.
            WriteLength(-1);

            int fullSegments = Math.DivRem(payload.Length, MaxCERContentSize, out int lastContentSize);

            // The tag size is 1 byte.
            // The length will always be encoded as 82 03 E8 (3 bytes)
            // And 1000 content octets (by T-REC-X.690-201508 sec 9.2)
            const int FullSegmentEncodedSize = 1004;

            Debug.Assert(
                FullSegmentEncodedSize == 1 + 1 + MaxCERSegmentSize + GetEncodedLengthSubsequentByteCount(MaxCERSegmentSize));

            int remainingEncodedSize;

            if (lastContentSize == 0)
            {
                remainingEncodedSize = 0;
            }
            else
            {
                // One byte of tag, minimum one byte of length, and one byte of unused bit count.
                remainingEncodedSize = 3 + lastContentSize + GetEncodedLengthSubsequentByteCount(lastContentSize);
            }

            // Reduce the number of copies by pre-calculating the size.
            // +2 for End-Of-Contents
            int expectedSize = fullSegments * FullSegmentEncodedSize + remainingEncodedSize + 2;

            EnsureWriteCapacity(expectedSize);

            byte[] ensureNoExtraCopy = _buffer;
            int    savedOffset       = _offset;

            ReadOnlySpan <byte> remainingData = payload;
            Span <byte>         dest;
            Asn1Tag             primitiveBitString = Asn1Tag.PrimitiveBitString;

            while (remainingData.Length > MaxCERContentSize)
            {
                // T-REC-X.690-201508 sec 8.6.4.1
                WriteTag(primitiveBitString);
                WriteLength(MaxCERSegmentSize);
                // 0 unused bits in this segment.
                _buffer[_offset] = 0;
                _offset++;

                dest = _buffer.AsSpan(_offset);
                remainingData.Slice(0, MaxCERContentSize).CopyTo(dest);

                remainingData = remainingData.Slice(MaxCERContentSize);
                _offset      += MaxCERContentSize;
            }

            WriteTag(primitiveBitString);
            WriteLength(remainingData.Length + 1);

            _buffer[_offset] = (byte)unusedBitCount;
            _offset++;

            dest = _buffer.AsSpan(_offset);
            remainingData.CopyTo(dest);
            _offset += remainingData.Length;

            WriteEndOfContents();

            Debug.Assert(_offset - savedOffset == expectedSize, $"expected size was {expectedSize}, actual was {_offset - savedOffset}");
            Debug.Assert(_buffer == ensureNoExtraCopy, $"_buffer was replaced during {nameof(WriteConstructedCerBitString)}");
        }
예제 #3
0
        // T-REC-X.690-201508 sec 9.2, 8.7
        private void WriteConstructedCerOctetString(Asn1Tag tag, ReadOnlySpan <byte> payload)
        {
            const int MaxCERSegmentSize = AsnReader.MaxCERSegmentSize;

            Debug.Assert(payload.Length > MaxCERSegmentSize);

            this.WriteTag(tag.AsConstructed());
            this.WriteLength(-1);

            int fullSegments = Math.DivRem(payload.Length, MaxCERSegmentSize, out int lastSegmentSize);

            // The tag size is 1 byte.
            // The length will always be encoded as 82 03 E8 (3 bytes)
            // And 1000 content octets (by T-REC-X.690-201508 sec 9.2)
            const int FullSegmentEncodedSize = 1004;

            Debug.Assert(
                1 + 1 + MaxCERSegmentSize + GetEncodedLengthSubsequentByteCount(MaxCERSegmentSize) == FullSegmentEncodedSize);

            int remainingEncodedSize;

            if (lastSegmentSize == 0)
            {
                remainingEncodedSize = 0;
            }
            else
            {
                // One byte of tag, and minimum one byte of length.
                remainingEncodedSize = 2 + lastSegmentSize + GetEncodedLengthSubsequentByteCount(lastSegmentSize);
            }

            // Reduce the number of copies by pre-calculating the size.
            // +2 for End-Of-Contents
            int expectedSize = (fullSegments * FullSegmentEncodedSize) + remainingEncodedSize + 2;

            this.EnsureWriteCapacity(expectedSize);

            byte[] ensureNoExtraCopy = this._buffer;
            int    savedOffset       = this._offset;

            ReadOnlySpan <byte> remainingData = payload;
            Span <byte>         dest;
            Asn1Tag             primitiveOctetString = Asn1Tag.PrimitiveOctetString;

            while (remainingData.Length > MaxCERSegmentSize)
            {
                // T-REC-X.690-201508 sec 8.7.3.2-note2
                this.WriteTag(primitiveOctetString);
                this.WriteLength(MaxCERSegmentSize);

                dest = this._buffer.AsSpan(this._offset);
                remainingData.Slice(0, MaxCERSegmentSize).CopyTo(dest);

                this._offset += MaxCERSegmentSize;
                remainingData = remainingData.Slice(MaxCERSegmentSize);
            }

            this.WriteTag(primitiveOctetString);
            this.WriteLength(remainingData.Length);
            dest = this._buffer.AsSpan(this._offset);
            remainingData.CopyTo(dest);
            this._offset += remainingData.Length;

            this.WriteEndOfContents();

            Debug.Assert(this._offset - savedOffset == expectedSize, $"expected size was {expectedSize}, actual was {this._offset - savedOffset}");
            Debug.Assert(this._buffer == ensureNoExtraCopy, $"_buffer was replaced during {nameof(this.WriteConstructedCerOctetString)}");
        }