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