1 package org.bouncycastle.asn1; 2 3 import java.io.IOException; 4 import java.util.Enumeration; 5 6 /** 7 * The DLSet encodes ASN.1 SET value without element ordering, 8 * and always using definite length form. 9 * <hr> 10 * <h2>X.690</h2> 11 * <h3>8: Basic encoding rules</h3> 12 * <h4>8.11 Encoding of a set value </h4> 13 * <b>8.11.1</b> The encoding of a set value shall be constructed 14 * <p> 15 * <b>8.11.2</b> The contents octets shall consist of the complete 16 * encoding of a data value from each of the types listed in the 17 * ASN.1 definition of the set type, in an order chosen by the sender, 18 * unless the type was referenced with the keyword 19 * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>. 20 * <p> 21 * <b>8.11.3</b> The encoding of a data value may, but need not, 22 * be present for a type which was referenced with the keyword 23 * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>. 24 * <blockquote> 25 * NOTE — The order of data values in a set value is not significant, 26 * and places no constraints on the order during transfer 27 * </blockquote> 28 * <h3>9: Canonical encoding rules</h3> 29 * <h4>9.3 Set components</h4> 30 * The encodings of the component values of a set value shall 31 * appear in an order determined by their tags as specified 32 * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1. 33 * Additionally, for the purposes of determining the order in which 34 * components are encoded when one or more component is an untagged 35 * choice type, each untagged choice type is ordered as though it 36 * has a tag equal to that of the smallest tag in that choice type 37 * or any untagged choice types nested within. 38 * <h3>10: Distinguished encoding rules</h3> 39 * <h4>10.3 Set components</h4> 40 * The encodings of the component values of a set value shall appear 41 * in an order determined by their tags as specified 42 * in 8.6 of ITU-T Rec. X.680 | ISO/IEC 8824-1. 43 * <blockquote> 44 * NOTE — Where a component of the set is an untagged choice type, 45 * the location of that component in the ordering will depend on 46 * the tag of the choice component being encoded. 47 * </blockquote> 48 * <h3>11: Restrictions on BER employed by both CER and DER</h3> 49 * <h4>11.5 Set and sequence components with default value </h4> 50 * The encoding of a set value or sequence value shall not include 51 * an encoding for any component value which is equal to 52 * its default value. 53 */ 54 public class DLSet 55 extends ASN1Set 56 { 57 private int bodyLength = -1; 58 59 /** 60 * create an empty set 61 */ 62 public DLSet() 63 { 64 } 65 66 /** 67 * @param obj - a single object that makes up the set. 68 */ 69 public DLSet( 70 ASN1Encodable obj) 71 { 72 super(obj); 73 } 74 75 /** 76 * @param v - a vector of objects making up the set. 77 */ 78 public DLSet( 79 ASN1EncodableVector v) 80 { 81 super(v, false); 82 } 83 84 /** 85 * create a set from an array of objects. 86 */ 87 public DLSet( 88 ASN1Encodable[] a) 89 { 90 super(a, false); 91 } 92 93 private int getBodyLength() 94 throws IOException 95 { 96 if (bodyLength < 0) 97 { 98 int length = 0; 99 100 for (Enumeration e = this.getObjects(); e.hasMoreElements();) 101 { 102 Object obj = e.nextElement(); 103 104 length += ((ASN1Encodable)obj).toASN1Primitive().toDLObject().encodedLength(); 105 } 106 107 bodyLength = length; 108 } 109 110 return bodyLength; 111 } 112 113 int encodedLength() 114 throws IOException 115 { 116 int length = getBodyLength(); 117 118 return 1 + StreamUtil.calculateBodyLength(length) + length; 119 } 120 121 /** 122 * A note on the implementation: 123 * <p> 124 * As DL requires the constructed, definite-length model to 125 * be used for structured types, this varies slightly from the 126 * ASN.1 descriptions given. Rather than just outputting SET, 127 * we also have to specify CONSTRUCTED, and the objects length. 128 */ 129 void encode( 130 ASN1OutputStream out) 131 throws IOException 132 { 133 ASN1OutputStream dOut = out.getDLSubStream(); 134 int length = getBodyLength(); 135 136 out.write(BERTags.SET | BERTags.CONSTRUCTED); 137 out.writeLength(length); 138 139 for (Enumeration e = this.getObjects(); e.hasMoreElements();) 140 { 141 Object obj = e.nextElement(); 142 143 dOut.writeObject((ASN1Encodable)obj); 144 } 145 } 146 }