1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 6c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by 7c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * a [n] where n is some number - these are assumed to follow the construction 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * rules (as with sequences). 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic abstract class ASN1TaggedObject 11c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom extends ASN1Object 12c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom implements ASN1TaggedObjectParser 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int tagNo; 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean empty = false; 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean explicit = true; 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam DEREncodable obj = null; 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam static public ASN1TaggedObject getInstance( 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam ASN1TaggedObject obj, 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean explicit) 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (explicit) 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return (ASN1TaggedObject)obj.getObject(); 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException("implicitly tagged tagged object"); 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam static public ASN1TaggedObject getInstance( 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam Object obj) 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (obj == null || obj instanceof ASN1TaggedObject) 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return (ASN1TaggedObject)obj; 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 39c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Create a tagged object in the explicit style. 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param tagNo the tag number for this object. 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param obj the tagged object. 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public ASN1TaggedObject( 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int tagNo, 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam DEREncodable obj) 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.explicit = true; 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.tagNo = tagNo; 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.obj = obj; 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Create a tagged object with the style given by the value of explicit. 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * If the object implements ASN1Choice the tag style will always be changed 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * to explicit in accordance with the ASN.1 encoding rules. 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * </p> 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param explicit true if the object is explicitly tagged. 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param tagNo the tag number for this object. 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param obj the tagged object. 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public ASN1TaggedObject( 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean explicit, 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int tagNo, 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam DEREncodable obj) 71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (obj instanceof ASN1Choice) 73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.explicit = true; 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.explicit = explicit; 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.tagNo = tagNo; 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.obj = obj; 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 85c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean asn1Equals( 86c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom DERObject o) 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (!(o instanceof ASN1TaggedObject)) 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return false; 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam ASN1TaggedObject other = (ASN1TaggedObject)o; 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (tagNo != other.tagNo || empty != other.empty || explicit != other.explicit) 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return false; 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if(obj == null) 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 102c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (other.obj != null) 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return false; 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 109c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (!(obj.getDERObject().equals(other.obj.getDERObject()))) 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return false; 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return true; 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int hashCode() 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int code = tagNo; 121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 122c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // TODO: actually this is wrong - the problem is that a re-encoded 123c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // object may end up with a different hashCode due to implicit 124c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // tagging. As implicit tagging is ambiguous if a sequence is involved 125c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // it seems the only correct method for both equals and hashCode is to 126c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // compare the encodings... 127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (obj != null) 128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam code ^= obj.hashCode(); 130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return code; 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int getTagNo() 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return tagNo; 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return whether or not the object may be explicitly tagged. 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Note: if the object has been read from an input stream, the only 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * time you can be sure if isExplicit is returning the true state of 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * affairs is if it returns false. An implicitly tagged object may appear 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * to be explicitly tagged, so you need to understand the context under 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * which the reading was done as well, see getObject below. 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public boolean isExplicit() 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return explicit; 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public boolean isEmpty() 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return empty; 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return whatever was following the tag. 161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * <p> 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Note: tagged objects are generally context dependent if you're 163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * trying to extract a tagged object you should be going via the 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * appropriate getInstance method. 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public DERObject getObject() 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (obj != null) 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return obj.getDERObject(); 171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return null; 174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 176c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom /** 177c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * Return the object held in this tagged object as a parser assuming it has 178c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * the type of the passed in tag. If the object doesn't have a parser 179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * associated with it, the base object is returned. 180c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom */ 181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public DEREncodable getObjectParser( 182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int tag, 183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean isExplicit) 184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom switch (tag) 186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 187c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom case DERTags.SET: 188c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return ASN1Set.getInstance(this, isExplicit).parser(); 189c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom case DERTags.SEQUENCE: 190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return ASN1Sequence.getInstance(this, isExplicit).parser(); 191c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom case DERTags.OCTET_STRING: 192c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return ASN1OctetString.getInstance(this, isExplicit).parser(); 193c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 194c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 195c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (isExplicit) 196c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 197c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return getObject(); 198c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 199c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 200c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new RuntimeException("implicit tagging not implemented for tag: " + tag); 201c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 202c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 2036e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom public DERObject getLoadedObject() 2046e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom { 2056e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom return this.getDERObject(); 2066e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom } 2076e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom 208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam abstract void encode(DEROutputStream out) 209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException; 210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public String toString() 212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return "[" + tagNo + "]" + obj; 214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 216