1 package org.bouncycastle.asn1;
2 
3 import java.io.IOException;
4 
5 /**
6  * Definite length SEQUENCE, encoding tells explicit number of bytes
7  * that the content of this sequence occupies.
8  * <p>
9  * For X.690 syntax rules, see {@link ASN1Sequence}.
10  */
11 public class DERSequence
12     extends ASN1Sequence
13 {
convert(ASN1Sequence seq)14     public static DERSequence convert(ASN1Sequence seq)
15     {
16         return (DERSequence)seq.toDERObject();
17     }
18 
19     private int bodyLength = -1;
20 
21     /**
22      * Create an empty sequence
23      */
DERSequence()24     public DERSequence()
25     {
26     }
27 
28     /**
29      * Create a sequence containing one object
30      * @param element the object to go in the sequence.
31      */
DERSequence(ASN1Encodable element)32     public DERSequence(ASN1Encodable element)
33     {
34         super(element);
35     }
36 
37     /**
38      * Create a sequence containing a vector of objects.
39      * @param elementVector the vector of objects to make up the sequence.
40      */
DERSequence(ASN1EncodableVector elementVector)41     public DERSequence(ASN1EncodableVector elementVector)
42     {
43         super(elementVector);
44     }
45 
46     /**
47      * Create a sequence containing an array of objects.
48      * @param elements the array of objects to make up the sequence.
49      */
DERSequence(ASN1Encodable[] elements)50     public DERSequence(ASN1Encodable[] elements)
51     {
52         super(elements);
53     }
54 
DERSequence(ASN1Encodable[] elements, boolean clone)55     DERSequence(ASN1Encodable[] elements, boolean clone)
56     {
57         super(elements, clone);
58     }
59 
getBodyLength()60     private int getBodyLength() throws IOException
61     {
62         if (bodyLength < 0)
63         {
64             int count = elements.length;
65             int totalLength = 0;
66 
67             for (int i = 0; i < count; ++i)
68             {
69                 ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject();
70                 totalLength += derObject.encodedLength();
71             }
72 
73             this.bodyLength = totalLength;
74         }
75 
76         return bodyLength;
77     }
78 
encodedLength()79     int encodedLength() throws IOException
80     {
81         int length = getBodyLength();
82 
83         return 1 + StreamUtil.calculateBodyLength(length) + length;
84     }
85 
86     /*
87      * A note on the implementation:
88      * <p>
89      * As DER requires the constructed, definite-length model to
90      * be used for structured types, this varies slightly from the
91      * ASN.1 descriptions given. Rather than just outputting SEQUENCE,
92      * we also have to specify CONSTRUCTED, and the objects length.
93      */
encode(ASN1OutputStream out, boolean withTag)94     void encode(ASN1OutputStream out, boolean withTag) throws IOException
95     {
96         if (withTag)
97         {
98             out.write(BERTags.SEQUENCE | BERTags.CONSTRUCTED);
99         }
100 
101         DEROutputStream derOut = out.getDERSubStream();
102 
103         int count = elements.length;
104         if (bodyLength >= 0 || count > 16)
105         {
106             out.writeLength(getBodyLength());
107 
108             for (int i = 0; i < count; ++i)
109             {
110                 ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject();
111                 derObject.encode(derOut, true);
112             }
113         }
114         else
115         {
116             int totalLength = 0;
117 
118             ASN1Primitive[] derObjects = new ASN1Primitive[count];
119             for (int i = 0; i < count; ++i)
120             {
121                 ASN1Primitive derObject = elements[i].toASN1Primitive().toDERObject();
122                 derObjects[i] = derObject;
123                 totalLength += derObject.encodedLength();
124             }
125 
126             this.bodyLength = totalLength;
127             out.writeLength(totalLength);
128 
129             for (int i = 0; i < count; ++i)
130             {
131                 derObjects[i].encode(derOut, true);
132             }
133         }
134     }
135 
toDERObject()136     ASN1Primitive toDERObject()
137     {
138         return this;
139     }
140 
toDLObject()141     ASN1Primitive toDLObject()
142     {
143         return this;
144     }
145 }
146