1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.util.Enumeration;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/**
7c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * BER TaggedObject - in ASN.1 notation this is any object preceded by
8c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * a [n] where n is some number - these are assumed to follow the construction
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * rules (as with sequences).
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class BERTaggedObject
124c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    extends ASN1TaggedObject
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param tagNo the tag number for this object.
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param obj the tagged object.
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public BERTaggedObject(
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int             tagNo,
204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1Encodable    obj)
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        super(true, tagNo, obj);
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param explicit true if an explicitly tagged object.
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param tagNo the tag number for this object.
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * @param obj the tagged object.
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public BERTaggedObject(
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        boolean         explicit,
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int             tagNo,
334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1Encodable    obj)
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super(explicit, tagNo, obj);
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    /**
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * create an implicitly tagged object that contains a zero
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     * length sequence.
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam     */
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public BERTaggedObject(
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int             tagNo)
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super(false, tagNo, new BERSequence());
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
484c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    boolean isConstructed()
494c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
504c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!empty)
514c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
524c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (explicit)
534c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
544c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return true;
554c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
564c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
574c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
584c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                ASN1Primitive primitive = obj.toASN1Primitive().toDERObject();
594c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
604c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return primitive.isConstructed();
614c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
624c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
634c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return true;
664c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
684c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
694c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    int encodedLength()
70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
724c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!empty)
73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            ASN1Primitive primitive = obj.toASN1Primitive();
754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            int length = primitive.encodedLength();
76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (explicit)
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return StreamUtil.calculateTagLength(tagNo) + StreamUtil.calculateBodyLength(length) + length;
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                // header length already in calculation
844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                length = length - 1;
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                return StreamUtil.calculateTagLength(tagNo) + length;
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        else
904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            return StreamUtil.calculateTagLength(tagNo) + 1;
924c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
934c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
954c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    void encode(
964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        ASN1OutputStream out)
974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        throws IOException
984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
994c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.writeTag(BERTags.CONSTRUCTED | BERTags.TAGGED, tagNo);
1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.write(0x80);
1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        if (!empty)
1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (!explicit)
1054c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1064c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                Enumeration e;
1074c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                if (obj instanceof ASN1OctetString)
108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1094c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    if (obj instanceof BEROctetString)
110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1114c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        e = ((BEROctetString)obj).getObjects();
112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    }
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    else
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                    {
1154c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        ASN1OctetString             octs = (ASN1OctetString)obj;
1164c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        BEROctetString berO = new BEROctetString(octs.getOctets());
1174c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                        e = berO.getObjects();
118c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    }
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
1204c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else if (obj instanceof ASN1Sequence)
1214c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1224c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    e = ((ASN1Sequence)obj).getObjects();
1234c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                else if (obj instanceof ASN1Set)
1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    e = ((ASN1Set)obj).getObjects();
1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                else
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                {
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    throw new RuntimeException("not implemented: " + obj.getClass().getName());
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                }
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                while (e.hasMoreElements())
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                {
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                    out.writeObject((ASN1Encodable)e.nextElement());
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                }
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            else
1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1404c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                out.writeObject(obj);
1414c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
1434c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
1444c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.write(0x00);
1454c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        out.write(0x00);
146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
148