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