14c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompackage org.bouncycastle.asn1;
24c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
34c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstromimport java.io.IOException;
44c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
54c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom/**
64c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * Definite Length TaggedObject - in ASN.1 notation this is any object preceded by
74c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * a [n] where n is some number - these are assumed to follow the construction
84c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom * rules (as with sequences).
94c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom */
104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrompublic class DLTaggedObject
114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    extends ASN1TaggedObject
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom{
134c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    private static final byte[] ZERO_BYTES = new byte[0];
144c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    /**
164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @param explicit true if an explicitly tagged object.
174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @param tagNo the tag number for this object.
184c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     * @param obj the tagged object.
194c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom     */
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    public DLTaggedObject(
214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        boolean explicit,
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int tagNo,
234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1Encodable obj)
244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        super(explicit, tagNo, obj);
264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    boolean isConstructed()
294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!empty)
314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (explicit)
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return true;
354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return primitive.isConstructed();
414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
424c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return true;
464c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
474c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    int encodedLength()
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!empty)
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            int length = obj.toASN1Primitive().toDLObject().encodedLength();
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (explicit)
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return  StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                // header length already in calculation
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                length = length - 1;
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return StreamUtil.calculateTagLength(tagNo) + length;
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return StreamUtil.calculateTagLength(tagNo) + 1;
714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    void encode(
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1OutputStream out)
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!empty)
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ASN1Primitive primitive = obj.toASN1Primitive().toDLObject();
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (explicit)
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                out.writeLength(primitive.encodedLength());
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                out.writeObject(primitive);
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                //
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                // need to mark constructed types...
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                //
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                int flags;
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (primitive.isConstructed())
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    flags = BERTags.CONSTRUCTED | BERTags.TAGGED;
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    flags = BERTags.TAGGED;
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                out.writeTag(flags, tagNo);
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                out.writeImplicitObject(primitive);
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
1084c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            out.writeEncoded(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo, ZERO_BYTES);
1104c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom}
113