1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.asn1;
2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.FilterOutputStream;
4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.IOException;
5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport java.io.OutputStream;
6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class DEROutputStream
8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    extends FilterOutputStream implements DERTags
9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{
10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public DEROutputStream(
11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        OutputStream    os)
12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        super(os);
14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    private void writeLength(
17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int length)
18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (length > 127)
21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            int size = 1;
23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            int val = length;
24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            while ((val >>>= 8) != 0)
26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                size++;
28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            write((byte)(size | 0x80));
31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            for (int i = (size - 1) * 8; i >= 0; i -= 8)
33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            {
34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam                write((byte)(length >> i));
35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            }
36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            write((byte)length);
40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    void writeEncoded(
44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        int     tag,
45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        byte[]  bytes)
46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        write(tag);
49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        writeLength(bytes.length);
50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        write(bytes);
51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
53c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    void writeTag(int flags, int tagNo)
54c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throws IOException
55c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
56c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (tagNo < 31)
57c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
58c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            write(flags | tagNo);
59c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
60c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        else
61c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
62c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            write(flags | 0x1f);
63c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (tagNo < 128)
64c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
65c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                write(tagNo);
66c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
67c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            else
68c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
69c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                byte[] stack = new byte[5];
70c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                int pos = stack.length;
71c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
72c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                stack[--pos] = (byte)(tagNo & 0x7F);
73c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                do
75c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                {
76c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    tagNo >>= 7;
77c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                    stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
78c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                }
79c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                while (tagNo > 127);
80c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
81c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                write(stack, pos, stack.length - pos);
82c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
83c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
85c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
86c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    void writeEncoded(int flags, int tagNo, byte[] bytes)
87c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throws IOException
88c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
89c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        writeTag(flags, tagNo);
90c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        writeLength(bytes.length);
91c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        write(bytes);
92c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
93c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    protected void writeNull()
95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        write(NULL);
98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        write(0x00);
99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam
101c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public void write(byte[] buf)
102c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throws IOException
103c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
104c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        out.write(buf, 0, buf.length);
105c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
106c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
107c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    public void write(byte[] buf, int offSet, int len)
108c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        throws IOException
109c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
110c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        out.write(buf, offSet, len);
111c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
112c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    public void writeObject(
114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        Object    obj)
115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        throws IOException
116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    {
117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        if (obj == null)
118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            writeNull();
120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DERObject)
122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ((DERObject)obj).encode(this);
124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else if (obj instanceof DEREncodable)
126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            ((DEREncodable)obj).getDERObject().encode(this);
128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        else
130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        {
131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam            throw new IOException("object not DEREncodable");
132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam        }
133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam    }
134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam}
135