1 package org.bouncycastle.asn1; 2 3 import java.io.IOException; 4 5 /** 6 * DER TaggedObject - in ASN.1 notation this is any object preceded by 7 * a [n] where n is some number - these are assumed to follow the construction 8 * rules (as with sequences). 9 */ 10 public class DERTaggedObject 11 extends ASN1TaggedObject 12 { 13 private static final byte[] ZERO_BYTES = new byte[0]; 14 15 /** 16 * @param explicit true if an explicitly tagged object. 17 * @param tagNo the tag number for this object. 18 * @param obj the tagged object. 19 */ 20 public DERTaggedObject( 21 boolean explicit, 22 int tagNo, 23 ASN1Encodable obj) 24 { 25 super(explicit, tagNo, obj); 26 } 27 28 public DERTaggedObject(int tagNo, ASN1Encodable encodable) 29 { 30 super(true, tagNo, encodable); 31 } 32 33 boolean isConstructed() 34 { 35 if (!empty) 36 { 37 if (explicit) 38 { 39 return true; 40 } 41 else 42 { 43 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); 44 45 return primitive.isConstructed(); 46 } 47 } 48 else 49 { 50 return true; 51 } 52 } 53 54 int encodedLength() 55 throws IOException 56 { 57 if (!empty) 58 { 59 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); 60 int length = primitive.encodedLength(); 61 62 if (explicit) 63 { 64 return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length; 65 } 66 else 67 { 68 // header length already in calculation 69 length = length - 1; 70 71 return StreamUtil.calculateTagLength(tagNo) + length; 72 } 73 } 74 else 75 { 76 return StreamUtil.calculateTagLength(tagNo) + 1; 77 } 78 } 79 80 void encode( 81 ASN1OutputStream out) 82 throws IOException 83 { 84 if (!empty) 85 { 86 ASN1Primitive primitive = obj.toASN1Primitive().toDERObject(); 87 88 if (explicit) 89 { 90 out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo); 91 out.writeLength(primitive.encodedLength()); 92 out.writeObject(primitive); 93 } 94 else 95 { 96 // 97 // need to mark constructed types... 98 // 99 int flags; 100 if (primitive.isConstructed()) 101 { 102 flags = BERTags.CONSTRUCTED | BERTags.TAGGED; 103 } 104 else 105 { 106 flags = BERTags.TAGGED; 107 } 108 109 out.writeTag(flags, tagNo); 110 out.writeImplicitObject(primitive); 111 } 112 } 113 else 114 { 115 out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES); 116 } 117 } 118 } 119