~brian-thomason/+junk/bouncycastle

« back to all changes in this revision

Viewing changes to jdk1.0/org/bouncycastle/asn1/DERInputStream.java

  • Committer: Brian Thomason
  • Date: 2011-12-20 17:20:32 UTC
  • Revision ID: brian.thomason@canonical.com-20111220172032-rdtm13jgdxtksacr
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.bouncycastle.asn1;
 
2
 
 
3
import java.io.ByteArrayInputStream;
 
4
import java.io.EOFException;
 
5
import java.io.FilterInputStream;
 
6
import java.io.IOException;
 
7
import java.io.InputStream;
 
8
 
 
9
public class DERInputStream
 
10
    extends FilterInputStream implements DERTags
 
11
{
 
12
    public DERInputStream(
 
13
        InputStream is)
 
14
    {
 
15
        super(is);
 
16
    }
 
17
 
 
18
    protected int readLength()
 
19
        throws IOException
 
20
    {
 
21
        int length = read();
 
22
        if (length < 0)
 
23
        {
 
24
            throw new IOException("EOF found when length expected");
 
25
        }
 
26
 
 
27
        if (length == 0x80)
 
28
        {
 
29
            return -1;      // indefinite-length encoding
 
30
        }
 
31
 
 
32
        if (length > 127)
 
33
        {
 
34
            int size = length & 0x7f;
 
35
 
 
36
            length = 0;
 
37
            for (int i = 0; i < size; i++)
 
38
            {
 
39
                int next = read();
 
40
 
 
41
                if (next < 0)
 
42
                {
 
43
                    throw new IOException("EOF found reading length");
 
44
                }
 
45
 
 
46
                length = (length << 8) + next;
 
47
            }
 
48
        }
 
49
 
 
50
        return length;
 
51
    }
 
52
 
 
53
    protected void readFully(
 
54
        byte[]  bytes)
 
55
        throws IOException
 
56
    {
 
57
        int     left = bytes.length;
 
58
 
 
59
        if (left == 0)
 
60
        {
 
61
            return;
 
62
        }
 
63
 
 
64
        while ((left -= read(bytes, bytes.length - left, left)) != 0)
 
65
        {
 
66
            // do nothing
 
67
        }
 
68
    }
 
69
 
 
70
    /**
 
71
     * build an object given its tag and a byte stream to construct it
 
72
     * from.
 
73
     */
 
74
    protected DERObject buildObject(
 
75
        int    tag,
 
76
        byte[]    bytes)
 
77
        throws IOException
 
78
    {
 
79
        switch (tag)
 
80
        {
 
81
        case NULL:
 
82
            return null;   
 
83
        case SEQUENCE | CONSTRUCTED:
 
84
            ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
 
85
            BERInputStream          dIn = new BERInputStream(bIn);
 
86
            DERConstructedSequence  seq = new DERConstructedSequence();
 
87
 
 
88
            try
 
89
            {
 
90
                for (;;)
 
91
                {
 
92
                    DERObject   obj = dIn.readObject();
 
93
 
 
94
                    seq.addObject(obj);
 
95
                }
 
96
            }
 
97
            catch (EOFException ex)
 
98
            {
 
99
                return seq;
 
100
            }
 
101
        case SET | CONSTRUCTED:
 
102
            bIn = new ByteArrayInputStream(bytes);
 
103
            dIn = new BERInputStream(bIn);
 
104
 
 
105
            DERSet       set = new DERSet(dIn.readObject());
 
106
 
 
107
            try
 
108
            {
 
109
                for (;;)
 
110
                {
 
111
                    DERObject   obj = dIn.readObject();
 
112
 
 
113
                    set.addObject(obj);
 
114
                }
 
115
            }
 
116
            catch (EOFException ex)
 
117
            {
 
118
                return set;
 
119
            }
 
120
        case BOOLEAN:
 
121
            return new DERBoolean(bytes);
 
122
        case INTEGER:
 
123
            return new DERInteger(bytes);
 
124
        case OBJECT_IDENTIFIER:
 
125
            int             head = bytes[0] & 0xff;
 
126
            StringBuffer    objId = new StringBuffer();
 
127
    
 
128
            objId.append(head / 40);
 
129
            objId.append('.');
 
130
            objId.append(head % 40);
 
131
            
 
132
            int value = 0;
 
133
    
 
134
            for (int i = 1; i != bytes.length; i++)
 
135
            {
 
136
                int b = bytes[i] & 0xff;
 
137
    
 
138
                value = value * 128 + (b & 0x7f);
 
139
                if ((b & 128) == 0)             // end of number reached
 
140
                {
 
141
                    objId.append('.');
 
142
                    objId.append(value);
 
143
                    value = 0;
 
144
                }
 
145
            }
 
146
    
 
147
            return new DERObjectIdentifier(objId.toString());
 
148
        case BIT_STRING:
 
149
            int     padBits = bytes[0];
 
150
            byte[]  data = new byte[bytes.length - 1];
 
151
 
 
152
            System.arraycopy(bytes, 1, data, 0, bytes.length - 1);
 
153
 
 
154
            return new DERBitString(data, padBits);
 
155
        case PRINTABLE_STRING:
 
156
            return new DERPrintableString(bytes);
 
157
        case IA5_STRING:
 
158
            return new DERIA5String(bytes);
 
159
        case T61_STRING:
 
160
            return new DERT61String(bytes);
 
161
        case VISIBLE_STRING:
 
162
            return new DERVisibleString(bytes);
 
163
        case BMP_STRING:
 
164
            return new DERBMPString(bytes);
 
165
        case OCTET_STRING:
 
166
            return new DEROctetString(bytes);
 
167
        case GENERALIZED_TIME:
 
168
            return new DERGeneralizedTime(new String(bytes, 0));
 
169
        case UTC_TIME:
 
170
            return new DERUTCTime(new String(bytes, 0));
 
171
        default:
 
172
            //
 
173
            // with tagged object tag number is bottom 4 bits
 
174
            //
 
175
            if ((tag & (TAGGED | CONSTRUCTED)) != 0)  
 
176
            {
 
177
                if (bytes.length == 0)        // empty tag!
 
178
                {
 
179
                    return new DERTaggedObject(tag & 0x0f);
 
180
                }
 
181
 
 
182
                //
 
183
                // simple type - implicit... return an octet string
 
184
                //
 
185
                if ((tag & CONSTRUCTED) == 0)
 
186
                {
 
187
                    return new DERTaggedObject(false, tag & 0x0f, new DEROctetString(bytes));
 
188
                }
 
189
 
 
190
                bIn = new ByteArrayInputStream(bytes);
 
191
                dIn = new BERInputStream(bIn);
 
192
 
 
193
                DEREncodable dObj = dIn.readObject();
 
194
 
 
195
                //
 
196
                // explicitly tagged (probably!) - if it isn't we'd have to
 
197
                // tell from the context
 
198
                //
 
199
                if (dIn.available() == 0)
 
200
                {
 
201
                    return new DERTaggedObject(tag & 0x0f, dObj);
 
202
                }
 
203
 
 
204
                //
 
205
                // another implicit object, we'll create a sequence...
 
206
                //
 
207
                seq = new DERConstructedSequence();
 
208
 
 
209
                seq.addObject(dObj);
 
210
 
 
211
                try
 
212
                {
 
213
                    for (;;)
 
214
                    {
 
215
                        dObj = dIn.readObject();
 
216
 
 
217
                        seq.addObject(dObj);
 
218
                    }
 
219
                }
 
220
                catch (EOFException ex)
 
221
                {
 
222
                    // ignore --
 
223
                }
 
224
 
 
225
                return new DERTaggedObject(false, tag & 0x0f, seq);
 
226
            }
 
227
 
 
228
            return new DERUnknownTag(tag, bytes);
 
229
        }
 
230
    }
 
231
 
 
232
    public DERObject readObject()
 
233
        throws IOException
 
234
    {
 
235
        int tag = read();
 
236
        if (tag == -1)
 
237
        {
 
238
            throw new EOFException();
 
239
        }
 
240
 
 
241
        int     length = readLength();
 
242
        byte[]  bytes = new byte[length];
 
243
 
 
244
        readFully(bytes);
 
245
 
 
246
        return buildObject(tag, bytes);
 
247
    }
 
248
}