1 package org.bouncycastle.asn1; 2 3 import java.io.IOException; 4 import java.util.Enumeration; 5 import java.util.Vector; 6 7 /** 8 * ASN.1 <code>SEQUENCE</code> and <code>SEQUENCE OF</code> constructs. 9 * <p> 10 * DER form is always definite form length fields, while 11 * BER support uses indefinite form. 12 * <hr> 13 * <p><b>X.690</b></p> 14 * <p><b>8: Basic encoding rules</b></p> 15 * <p><b>8.9 Encoding of a sequence value </b></p> 16 * 8.9.1 The encoding of a sequence value shall be constructed. 17 * <p> 18 * <b>8.9.2</b> The contents octets shall consist of the complete 19 * encoding of one data value from each of the types listed in 20 * the ASN.1 definition of the sequence type, in the order of 21 * their appearance in the definition, unless the type was referenced 22 * with the keyword <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>. 23 * </p><p> 24 * <b>8.9.3</b> The encoding of a data value may, but need not, 25 * be present for a type which was referenced with the keyword 26 * <b>OPTIONAL</b> or the keyword <b>DEFAULT</b>. 27 * If present, it shall appear in the encoding at the point 28 * corresponding to the appearance of the type in the ASN.1 definition. 29 * </p><p> 30 * <b>8.10 Encoding of a sequence-of value </b> 31 * </p><p> 32 * <b>8.10.1</b> The encoding of a sequence-of value shall be constructed. 33 * <p> 34 * <b>8.10.2</b> The contents octets shall consist of zero, 35 * one or more complete encodings of data values from the type listed in 36 * the ASN.1 definition. 37 * <p> 38 * <b>8.10.3</b> The order of the encodings of the data values shall be 39 * the same as the order of the data values in the sequence-of value to 40 * be encoded. 41 * </p> 42 * <p><b>9: Canonical encoding rules</b></p> 43 * <p><b>9.1 Length forms</b></p> 44 * If the encoding is constructed, it shall employ the indefinite length form. 45 * If the encoding is primitive, it shall include the fewest length octets necessary. 46 * [Contrast with 8.1.3.2 b).] 47 * 48 * <p><b>11: Restrictions on BER employed by both CER and DER</b></p> 49 * <p><b>11.5 Set and sequence components with default value</b></p> 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 abstract class ASN1Sequence 55 extends ASN1Primitive 56 { 57 protected Vector seq = new Vector(); 58 59 /** 60 * Return an ASN1Sequence from the given object. 61 * 62 * @param obj the object we want converted. 63 * @exception IllegalArgumentException if the object cannot be converted. 64 * @return an ASN1Sequence instance, or null. 65 */ getInstance( Object obj)66 public static ASN1Sequence getInstance( 67 Object obj) 68 { 69 if (obj == null || obj instanceof ASN1Sequence) 70 { 71 return (ASN1Sequence)obj; 72 } 73 else if (obj instanceof ASN1SequenceParser) 74 { 75 return ASN1Sequence.getInstance(((ASN1SequenceParser)obj).toASN1Primitive()); 76 } 77 else if (obj instanceof byte[]) 78 { 79 try 80 { 81 return ASN1Sequence.getInstance(fromByteArray((byte[])obj)); 82 } 83 catch (IOException e) 84 { 85 throw new IllegalArgumentException("failed to construct sequence from byte[]: " + e.getMessage()); 86 } 87 } 88 else if (obj instanceof ASN1Encodable) 89 { 90 ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive(); 91 92 if (primitive instanceof ASN1Sequence) 93 { 94 return (ASN1Sequence)primitive; 95 } 96 } 97 98 throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); 99 } 100 101 /** 102 * Return an ASN1 sequence from a tagged object. There is a special 103 * case here, if an object appears to have been explicitly tagged on 104 * reading but we were expecting it to be implicitly tagged in the 105 * normal course of events it indicates that we lost the surrounding 106 * sequence - so we need to add it back (this will happen if the tagged 107 * object is a sequence that contains other sequences). If you are 108 * dealing with implicitly tagged sequences you really <b>should</b> 109 * be using this method. 110 * 111 * @param obj the tagged object. 112 * @param explicit true if the object is meant to be explicitly tagged, 113 * false otherwise. 114 * @exception IllegalArgumentException if the tagged object cannot 115 * be converted. 116 * @return an ASN1Sequence instance. 117 */ getInstance( ASN1TaggedObject obj, boolean explicit)118 public static ASN1Sequence getInstance( 119 ASN1TaggedObject obj, 120 boolean explicit) 121 { 122 if (explicit) 123 { 124 if (!obj.isExplicit()) 125 { 126 throw new IllegalArgumentException("object implicit - explicit expected."); 127 } 128 129 return ASN1Sequence.getInstance(obj.getObject().toASN1Primitive()); 130 } 131 else 132 { 133 // 134 // constructed object which appears to be explicitly tagged 135 // when it should be implicit means we have to add the 136 // surrounding sequence. 137 // 138 if (obj.isExplicit()) 139 { 140 if (obj instanceof BERTaggedObject) 141 { 142 return new BERSequence(obj.getObject()); 143 } 144 else 145 { 146 return new DLSequence(obj.getObject()); 147 } 148 } 149 else 150 { 151 if (obj.getObject() instanceof ASN1Sequence) 152 { 153 return (ASN1Sequence)obj.getObject(); 154 } 155 } 156 } 157 158 throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); 159 } 160 161 /** 162 * Create an empty sequence 163 */ ASN1Sequence()164 protected ASN1Sequence() 165 { 166 } 167 168 /** 169 * Create a sequence containing one object 170 * @param obj the object to be put in the SEQUENCE. 171 */ ASN1Sequence( ASN1Encodable obj)172 protected ASN1Sequence( 173 ASN1Encodable obj) 174 { 175 seq.addElement(obj); 176 } 177 178 /** 179 * Create a sequence containing a vector of objects. 180 * @param v the vector of objects to be put in the SEQUENCE 181 */ ASN1Sequence( ASN1EncodableVector v)182 protected ASN1Sequence( 183 ASN1EncodableVector v) 184 { 185 for (int i = 0; i != v.size(); i++) 186 { 187 seq.addElement(v.get(i)); 188 } 189 } 190 191 /** 192 * Create a sequence containing a vector of objects. 193 */ ASN1Sequence( ASN1Encodable[] array)194 protected ASN1Sequence( 195 ASN1Encodable[] array) 196 { 197 for (int i = 0; i != array.length; i++) 198 { 199 seq.addElement(array[i]); 200 } 201 } 202 toArray()203 public ASN1Encodable[] toArray() 204 { 205 ASN1Encodable[] values = new ASN1Encodable[this.size()]; 206 207 for (int i = 0; i != this.size(); i++) 208 { 209 values[i] = this.getObjectAt(i); 210 } 211 212 return values; 213 } 214 getObjects()215 public Enumeration getObjects() 216 { 217 return seq.elements(); 218 } 219 parser()220 public ASN1SequenceParser parser() 221 { 222 final ASN1Sequence outer = this; 223 224 return new ASN1SequenceParser() 225 { 226 private final int max = size(); 227 228 private int index; 229 230 public ASN1Encodable readObject() throws IOException 231 { 232 if (index == max) 233 { 234 return null; 235 } 236 237 ASN1Encodable obj = getObjectAt(index++); 238 if (obj instanceof ASN1Sequence) 239 { 240 return ((ASN1Sequence)obj).parser(); 241 } 242 if (obj instanceof ASN1Set) 243 { 244 return ((ASN1Set)obj).parser(); 245 } 246 247 return obj; 248 } 249 250 public ASN1Primitive getLoadedObject() 251 { 252 return outer; 253 } 254 255 public ASN1Primitive toASN1Primitive() 256 { 257 return outer; 258 } 259 }; 260 } 261 262 /** 263 * Return the object at the sequence position indicated by index. 264 * 265 * @param index the sequence number (starting at zero) of the object 266 * @return the object at the sequence position indicated by index. 267 */ getObjectAt( int index)268 public ASN1Encodable getObjectAt( 269 int index) 270 { 271 return (ASN1Encodable)seq.elementAt(index); 272 } 273 274 /** 275 * Return the number of objects in this sequence. 276 * 277 * @return the number of objects in this sequence. 278 */ size()279 public int size() 280 { 281 return seq.size(); 282 } 283 hashCode()284 public int hashCode() 285 { 286 Enumeration e = this.getObjects(); 287 int hashCode = size(); 288 289 while (e.hasMoreElements()) 290 { 291 Object o = getNext(e); 292 hashCode *= 17; 293 294 hashCode ^= o.hashCode(); 295 } 296 297 return hashCode; 298 } 299 asn1Equals( ASN1Primitive o)300 boolean asn1Equals( 301 ASN1Primitive o) 302 { 303 if (!(o instanceof ASN1Sequence)) 304 { 305 return false; 306 } 307 308 ASN1Sequence other = (ASN1Sequence)o; 309 310 if (this.size() != other.size()) 311 { 312 return false; 313 } 314 315 Enumeration s1 = this.getObjects(); 316 Enumeration s2 = other.getObjects(); 317 318 while (s1.hasMoreElements()) 319 { 320 ASN1Encodable obj1 = getNext(s1); 321 ASN1Encodable obj2 = getNext(s2); 322 323 ASN1Primitive o1 = obj1.toASN1Primitive(); 324 ASN1Primitive o2 = obj2.toASN1Primitive(); 325 326 if (o1 == o2 || o1.equals(o2)) 327 { 328 continue; 329 } 330 331 return false; 332 } 333 334 return true; 335 } 336 getNext(Enumeration e)337 private ASN1Encodable getNext(Enumeration e) 338 { 339 ASN1Encodable encObj = (ASN1Encodable)e.nextElement(); 340 341 return encObj; 342 } 343 344 /** 345 * Change current SEQUENCE object to be encoded as {@link DERSequence}. 346 * This is part of Distinguished Encoding Rules form serialization. 347 */ toDERObject()348 ASN1Primitive toDERObject() 349 { 350 ASN1Sequence derSeq = new DERSequence(); 351 352 derSeq.seq = this.seq; 353 354 return derSeq; 355 } 356 357 /** 358 * Change current SEQUENCE object to be encoded as {@link DLSequence}. 359 * This is part of Direct Length form serialization. 360 */ toDLObject()361 ASN1Primitive toDLObject() 362 { 363 ASN1Sequence dlSeq = new DLSequence(); 364 365 dlSeq.seq = this.seq; 366 367 return dlSeq; 368 } 369 isConstructed()370 boolean isConstructed() 371 { 372 return true; 373 } 374 encode(ASN1OutputStream out)375 abstract void encode(ASN1OutputStream out) 376 throws IOException; 377 toString()378 public String toString() 379 { 380 return seq.toString(); 381 } 382 } 383