summary refs log tree commit diff
path: root/crypto/src/asn1/DerSequence.cs
blob: e60796091e5584abde6d0e0c672ebadf031c37b1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;

namespace Org.BouncyCastle.Asn1
{
	public class DerSequence
		: Asn1Sequence
	{
		public static readonly DerSequence Empty = new DerSequence();

		public static DerSequence FromVector(Asn1EncodableVector elementVector)
		{
            return elementVector.Count < 1 ? Empty : new DerSequence(elementVector);
		}

        private int m_contentsLengthDer = -1;

        /**
		 * create an empty sequence
		 */
        public DerSequence()
			: base()
		{
		}

		/**
		 * create a sequence containing one object
		 */
		public DerSequence(Asn1Encodable element)
			: base(element)
		{
		}

		public DerSequence(params Asn1Encodable[] elements)
            : base(elements)
		{
		}

		/**
		 * create a sequence containing a vector of objects.
		 */
		public DerSequence(Asn1EncodableVector elementVector)
            : base(elementVector)
		{
		}

        internal DerSequence(Asn1Encodable[] elements, bool clone)
            : base(elements, clone)
        {
        }

        internal override int EncodedLength(int encoding, bool withID)
        {
            return Asn1OutputStream.GetLengthOfEncodingDL(withID, GetContentsLengthDer());
        }

        /*
		 * A note on the implementation:
		 * <p>
		 * As Der requires the constructed, definite-length model to
		 * be used for structured types, this varies slightly from the
		 * ASN.1 descriptions given. Rather than just outputing Sequence,
		 * we also have to specify Constructed, and the objects length.
		 */
        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
        {
            asn1Out = asn1Out.GetDerSubStream();

            asn1Out.WriteIdentifier(withID, Asn1Tags.Constructed | Asn1Tags.Sequence);

            int count = elements.Length;
            if (m_contentsLengthDer >= 0 || count > 16)
            {
                asn1Out.WriteDL(GetContentsLengthDer());

                for (int i = 0; i < count; ++i)
                {
                    Asn1Object asn1Object = elements[i].ToAsn1Object();
                    asn1Object.Encode(asn1Out, true);
                }
            }
            else
            {
                int contentsLength = 0;

                Asn1Object[] asn1Objects = new Asn1Object[count];
                for (int i = 0; i < count; ++i)
                {
                    Asn1Object asn1Object = elements[i].ToAsn1Object();
                    asn1Objects[i] = asn1Object;
                    contentsLength += asn1Object.EncodedLength(asn1Out.Encoding, true);
                }

                this.m_contentsLengthDer = contentsLength;
                asn1Out.WriteDL(contentsLength);

                for (int i = 0; i < count; ++i)
                {
                    asn1Objects[i].Encode(asn1Out, true);
                }
            }
        }

        internal override DerBitString ToAsn1BitString()
        {
            return new DerBitString(BerBitString.FlattenBitStrings(GetConstructedBitStrings()), false);
        }

        internal override DerExternal ToAsn1External()
        {
            return new DerExternal(this);
        }

        internal override Asn1OctetString ToAsn1OctetString()
        {
            return new DerOctetString(BerOctetString.FlattenOctetStrings(GetConstructedOctetStrings()));
        }

        internal override Asn1Set ToAsn1Set()
        {
            // NOTE: DLSet is intentional, we don't want sorting
            return new DLSet(false, elements);
        }

        private int GetContentsLengthDer()
        {
            if (m_contentsLengthDer < 0)
            {
                m_contentsLengthDer = CalculateContentsLength(Asn1OutputStream.EncodingDer);
            }
            return m_contentsLengthDer;
        }
    }
}