1c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrompackage org.bouncycastle.asn1;
2c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giroimport java.io.ByteArrayOutputStream;
479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giroimport java.io.IOException;
579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro/**
779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro * An indefinite-length encoding version of an application specific object.
879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro */
9c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrompublic class BERApplicationSpecific
1079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    extends ASN1ApplicationSpecific
11c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom{
1279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    BERApplicationSpecific(
1379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        boolean isConstructed,
1479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int tag,
1579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        byte[] octets)
1679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
1779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        super(isConstructed, tag, octets);
1879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
1979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
2079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    /**
2179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * Create an application specific object with a tagging of explicit/constructed.
2279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     *
2379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param tag the tag number for this object.
2479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param object the object to be contained.
2579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     */
2679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    public BERApplicationSpecific(
2779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int tag,
2879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        ASN1Encodable object)
2979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        throws IOException
3079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
3179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        this(true, tag, object);
3279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
3379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
3479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    /**
3579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * Create an application specific object with the tagging style given by the value of constructed.
3679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     *
3779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param constructed true if the object is constructed.
3879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param tag the tag number for this object.
3979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param object the object to be contained.
4079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     */
4179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    public BERApplicationSpecific(
4279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        boolean constructed,
4379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int tag,
4479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        ASN1Encodable object)
4579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        throws IOException
4679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
4779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        super(constructed || object.toASN1Primitive().isConstructed(), tag, getEncoding(constructed, object));
4879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
4979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
5079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private static byte[] getEncoding(boolean explicit, ASN1Encodable object)
5179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        throws IOException
5279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
5379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        byte[] data = object.toASN1Primitive().getEncoded(ASN1Encoding.BER);
5479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
5579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        if (explicit)
5679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
5779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            return data;
5879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
5979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        else
6079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
6179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            int lenBytes = getLengthOfHeader(data);
6279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            byte[] tmp = new byte[data.length - lenBytes];
6379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            System.arraycopy(data, lenBytes, tmp, 0, tmp.length);
6479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            return tmp;
6579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
6679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
6779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
6879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    /**
6979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * Create an application specific object which is marked as constructed
7079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     *
7179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param tagNo the tag number for this object.
7279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @param vec the objects making up the application specific object.
7379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     */
74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public BERApplicationSpecific(int tagNo, ASN1EncodableVector vec)
75c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
7679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        super(true, tagNo, getEncodedVector(vec));
7779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
7879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
7979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    private static byte[] getEncodedVector(ASN1EncodableVector vec)
8079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
8179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
8279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
8379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        for (int i = 0; i != vec.size(); i++)
8479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
8579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            try
8679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
8779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                bOut.write(((ASN1Object)vec.get(i)).getEncoded(ASN1Encoding.BER));
8879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
8979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            catch (IOException e)
9079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            {
9179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro                throw new ASN1ParsingException("malformed object: " + e, e);
9279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            }
9379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
9479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        return bOut.toByteArray();
9579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    }
9679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
9779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    /* (non-Javadoc)
9879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     * @see org.bouncycastle.asn1.ASN1Primitive#encode(org.bouncycastle.asn1.DEROutputStream)
9979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro     */
10079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    void encode(ASN1OutputStream out) throws IOException
10179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro    {
10279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        int classBits = BERTags.APPLICATION;
10379d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        if (isConstructed)
10479d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        {
10579d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro            classBits |= BERTags.CONSTRUCTED;
10679d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        }
10779d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro
10879d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        out.writeTag(classBits, tag);
10979d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        out.write(0x80);
11079d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        out.write(octets);
11179d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        out.write(0x00);
11279d3bf2425a53baab7feb744dad710b6c15533c9Sergio Giro        out.write(0x00);
113c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
114c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom}
115