1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.ByteArrayOutputStream; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 6c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Arrays; 7c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Base class for an application specific object 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class DERApplicationSpecific 124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom extends ASN1Primitive 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 14c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private final boolean isConstructed; 15c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private final int tag; 16c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private final byte[] octets; 17c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 18c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom DERApplicationSpecific( 19c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean isConstructed, 20c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int tag, 21c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] octets) 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 23c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.isConstructed = isConstructed; 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.tag = tag; 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.octets = octets; 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 27c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 28c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public DERApplicationSpecific( 29c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int tag, 30c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] octets) 31c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 32c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this(false, tag, octets); 33c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 34c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public DERApplicationSpecific( 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int tag, 374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Encodable object) 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 40c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this(true, tag, object); 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 42c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 43c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public DERApplicationSpecific( 44c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean explicit, 45c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int tag, 464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Encodable object) 47c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws IOException 48c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Primitive primitive = object.toASN1Primitive(); 50c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom byte[] data = primitive.getEncoded(ASN1Encoding.DER); 524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom this.isConstructed = explicit || (primitive instanceof ASN1Set || primitive instanceof ASN1Sequence); 54c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.tag = tag; 55c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 56c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (explicit) 57c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 58c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.octets = data; 59c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 60c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 61c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int lenBytes = getLengthOfHeader(data); 63c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] tmp = new byte[data.length - lenBytes]; 64c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom System.arraycopy(data, lenBytes, tmp, 0, tmp.length); 65c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.octets = tmp; 66c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 67c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 68c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 69c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public DERApplicationSpecific(int tagNo, ASN1EncodableVector vec) 70c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 71c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.tag = tagNo; 72c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.isConstructed = true; 73c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 75c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom for (int i = 0; i != vec.size(); i++) 76c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 77c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom try 78c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.DER)); 80c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 81c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom catch (IOException e) 82c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 83c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new ASN1ParsingException("malformed object: " + e, e); 84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 85c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 86c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.octets = bOut.toByteArray(); 87c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 88c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public static DERApplicationSpecific getInstance(Object obj) 90c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (obj == null || obj instanceof DERApplicationSpecific) 924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return (DERApplicationSpecific)obj; 944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else if (obj instanceof byte[]) 964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom try 984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return DERApplicationSpecific.getInstance(ASN1Primitive.fromByteArray((byte[])obj)); 1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom catch (IOException e) 1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("failed to construct object from byte[]: " + e.getMessage()); 1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else if (obj instanceof ASN1Encodable) 1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Primitive primitive = ((ASN1Encodable)obj).toASN1Primitive(); 1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (primitive instanceof ASN1Sequence) 1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return (DERApplicationSpecific)primitive; 1134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 115c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("unknown object in getInstance: " + obj.getClass().getName()); 1174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom private int getLengthOfHeader(byte[] data) 1204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int length = data[1] & 0xff; // TODO: assumes 1 byte tag 1224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (length == 0x80) 1244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return 2; // indefinite-length encoding 1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (length > 127) 129c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int size = length & 0x7f; 1314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here 1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (size > 4) 1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalStateException("DER length more than 4 bytes: " + size); 1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return size + 2; 139c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 140c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return 2; 142c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 143c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public boolean isConstructed() 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 146c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return isConstructed; 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public byte[] getContents() 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return octets; 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int getApplicationTag() 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 156c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return tag; 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 158c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 159c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom /** 160c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * Return the enclosed object assuming explicit tagging. 161c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * 162c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @return the resulting object 163c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @throws IOException if reconstruction fails. 164c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom */ 1654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public ASN1Primitive getObject() 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IOException 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return new ASN1InputStream(getContents()).readObject(); 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 170c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 171c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom /** 172c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * Return the enclosed object assuming implicit tagging. 173c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * 174c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @param derTagNo the type tag that should be applied to the object's contents. 175c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @return the resulting object 176c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * @throws IOException if reconstruction fails. 177c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom */ 1784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom public ASN1Primitive getObject(int derTagNo) 179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws IOException 180c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (derTagNo >= 0x1f) 182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IOException("unsupported tag number"); 184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] orig = this.getEncoded(); 187c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] tmp = replaceTagNumber(derTagNo, orig); 188c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 1894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if ((orig[0] & BERTags.CONSTRUCTED) != 0) 190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 1914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom tmp[0] |= BERTags.CONSTRUCTED; 192c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 193c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 194c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return new ASN1InputStream(tmp).readObject(); 195c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 1964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 1974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int encodedLength() 1984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throws IOException 1994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 2004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom return StreamUtil.calculateTagLength(tag) + StreamUtil.calculateBodyLength(octets.length) + octets.length; 2014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 2024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* (non-Javadoc) 2044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream) 205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 2064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom void encode(ASN1OutputStream out) throws IOException 207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 2084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom int classBits = BERTags.APPLICATION; 209c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (isConstructed) 210c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 2114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom classBits |= BERTags.CONSTRUCTED; 212c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 213c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 214c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom out.writeEncoded(classBits, tag, octets); 215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 217c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean asn1Equals( 2184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ASN1Primitive o) 219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 220c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (!(o instanceof DERApplicationSpecific)) 221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return false; 223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 224c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam DERApplicationSpecific other = (DERApplicationSpecific)o; 226c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 227c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return isConstructed == other.isConstructed 228c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom && tag == other.tag 229c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom && Arrays.areEqual(octets, other.octets); 230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 231c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int hashCode() 233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 234c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return (isConstructed ? 1 : 0) ^ tag ^ Arrays.hashCode(octets); 235c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 237c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] replaceTagNumber(int newTag, byte[] input) 238c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws IOException 239c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 240c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int tagNo = input[0] & 0x1f; 241c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int index = 1; 242c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // 243c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // with tagged object tag number is bottom 5 bits, or stored at the start of the content 244c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // 245c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (tagNo == 0x1f) 246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 247c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom tagNo = 0; 248c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 249c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int b = input[index++] & 0xff; 250c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 251c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // X.690-0207 8.1.2.4.2 252c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // "c) bits 7 to 1 of the first subsequent octet shall not all be zero." 253c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if ((b & 0x7f) == 0) // Note: -1 will pass 254c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 255c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new ASN1ParsingException("corrupted stream - invalid high tag number found"); 256c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 257c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 258c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom while ((b >= 0) && ((b & 0x80) != 0)) 259c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 260c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom tagNo |= (b & 0x7f); 261c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom tagNo <<= 7; 262c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom b = input[index++] & 0xff; 263c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 264c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 265c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom tagNo |= (b & 0x7f); 266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 268c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] tmp = new byte[input.length - index + 1]; 269c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 270c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom System.arraycopy(input, index, tmp, 1, tmp.length - 1); 271c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 272c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom tmp[0] = (byte)newTag; 273c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 274c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return tmp; 275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 277