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