Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/security/util/DerInputStream.java
41159 views
1
/*
2
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.util;
27
28
import java.io.InputStream;
29
import java.io.IOException;
30
import java.math.BigInteger;
31
import java.util.Arrays;
32
import java.util.Date;
33
34
/**
35
* A DER input stream, used for parsing ASN.1 DER-encoded data such as
36
* that found in X.509 certificates. DER is a subset of BER/1, which has
37
* the advantage that it allows only a single encoding of primitive data.
38
* (High level data such as dates still support many encodings.) That is,
39
* it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER).
40
*
41
* <P>Note that, like BER/1, DER streams are streams of explicitly
42
* tagged data values. Accordingly, this programming interface does
43
* not expose any variant of the java.io.InputStream interface, since
44
* that kind of input stream holds untagged data values and using that
45
* I/O model could prevent correct parsing of the DER data.
46
*
47
* <P>At this time, this class supports only a subset of the types of DER
48
* data encodings which are defined. That subset is sufficient for parsing
49
* most X.509 certificates.
50
*
51
*
52
* @author David Brownell
53
* @author Amit Kapoor
54
* @author Hemma Prafullchandra
55
*/
56
57
public class DerInputStream {
58
59
// The static part
60
final byte[] data;
61
final int start; // inclusive
62
final int end; // exclusive
63
final boolean allowBER;
64
65
// The moving part
66
int pos;
67
int mark;
68
69
/**
70
* Constructs a DerInputStream by assigning all its fields.
71
*
72
* No checking on arguments since all callers are internal.
73
* {@code data} should never be null even if length is 0.
74
*/
75
public DerInputStream(byte[] data, int start, int length, boolean allowBER) {
76
this.data = data;
77
this.start = start;
78
this.end = start + length;
79
this.allowBER = allowBER;
80
this.pos = start;
81
this.mark = start;
82
}
83
84
public DerInputStream(byte[] data) throws IOException {
85
this(data, 0, data.length, true);
86
}
87
88
public DerInputStream(byte[] data, int offset, int len) throws IOException {
89
this(data, offset, len, true);
90
}
91
92
/**
93
* Returns the remaining unread bytes, or, all bytes if none read yet.
94
*/
95
public byte[] toByteArray() {
96
return Arrays.copyOfRange(data, pos, end);
97
}
98
99
/**
100
* Reads a DerValue from this stream. After the call, the data pointer
101
* is right after this DerValue so that the next call will read the
102
* next DerValue.
103
*
104
* @return the read DerValue.
105
* @throws IOException if a DerValue cannot be constructed starting from
106
* this position because of byte shortage or encoding error.
107
*/
108
public DerValue getDerValue() throws IOException {
109
DerValue result = new DerValue(
110
this.data, this.pos, this.end - this.pos, this.allowBER, true);
111
if (result.buffer != this.data) {
112
// Indefinite length observed. Unused bytes in data are appended
113
// to the end of return value by DerIndefLenConverter::convertBytes
114
// and stay inside result.buffer.
115
int unused = result.buffer.length - result.end;
116
this.pos = this.data.length - unused;
117
} else {
118
this.pos = result.end;
119
}
120
return result;
121
}
122
123
// The following getXyz methods are mostly shorthands for getDerValue().getXyz().
124
125
public int getInteger() throws IOException {
126
return getDerValue().getInteger();
127
}
128
129
public BigInteger getBigInteger() throws IOException {
130
return getDerValue().getBigInteger();
131
}
132
133
public BigInteger getPositiveBigInteger() throws IOException {
134
return getDerValue().getPositiveBigInteger();
135
}
136
137
public int getEnumerated() throws IOException {
138
return getDerValue().getEnumerated();
139
}
140
141
public byte[] getBitString() throws IOException {
142
return getDerValue().getBitString();
143
}
144
145
public BitArray getUnalignedBitString() throws IOException {
146
return getDerValue().getUnalignedBitString();
147
}
148
149
public byte[] getOctetString() throws IOException {
150
// Not identical to DerValue::getOctetString. This method
151
// does not accept constructed OCTET STRING.
152
DerValue v = getDerValue();
153
if (v.tag != DerValue.tag_OctetString) {
154
throw new IOException("DER input not an octet string");
155
}
156
return v.getOctetString();
157
}
158
159
public void getNull() throws IOException {
160
getDerValue().getNull();
161
}
162
163
public ObjectIdentifier getOID() throws IOException {
164
return getDerValue().getOID();
165
}
166
167
public String getUTF8String() throws IOException {
168
return getDerValue().getUTF8String();
169
}
170
171
public String getPrintableString() throws IOException {
172
return getDerValue().getPrintableString();
173
}
174
175
public String getT61String() throws IOException {
176
return getDerValue().getT61String();
177
}
178
179
public String getBMPString() throws IOException {
180
return getDerValue().getBMPString();
181
}
182
183
public String getIA5String() throws IOException {
184
return getDerValue().getIA5String();
185
}
186
187
public String getGeneralString() throws IOException {
188
return getDerValue().getGeneralString();
189
}
190
191
public Date getUTCTime() throws IOException {
192
return getDerValue().getUTCTime();
193
}
194
195
public Date getGeneralizedTime() throws IOException {
196
return getDerValue().getGeneralizedTime();
197
}
198
199
// Read a series of DerValue objects which is the sub-elements
200
// of a SEQUENCE and SET.
201
202
public DerValue[] getSequence(int startLen) throws IOException {
203
return getDerValue().subs(DerValue.tag_Sequence, startLen);
204
}
205
206
public DerValue[] getSet(int startLen) throws IOException {
207
return getDerValue().subs(DerValue.tag_Set, startLen);
208
}
209
210
public DerValue[] getSet(int startLen, boolean implicit) throws IOException {
211
if (implicit) {
212
return getDerValue().subs((byte) 0, startLen);
213
} else {
214
return getSet(startLen);
215
}
216
}
217
218
public int peekByte() throws IOException {
219
if (pos == end) {
220
throw new IOException("At end");
221
}
222
return data[pos];
223
}
224
225
/**
226
* Get a length from the input stream, allowing for at most 32 bits of
227
* encoding to be used. (Not the same as getting a tagged integer!)
228
*
229
* @return the length or -1 if indefinite length found.
230
* @exception IOException on parsing error or unsupported lengths.
231
*/
232
static int getLength(InputStream in) throws IOException {
233
int lenByte = in.read();
234
if (lenByte == -1) {
235
throw new IOException("Short read of DER length");
236
}
237
if (lenByte == 0x80) {
238
return -1;
239
}
240
241
int value, tmp;
242
String mdName = "DerInputStream.getLength(): ";
243
tmp = lenByte;
244
if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
245
value = tmp;
246
} else { // long form
247
tmp &= 0x07f;
248
249
// tmp > 4 indicates more than 4Gb of data.
250
if (tmp > 4) {
251
throw new IOException(mdName + "lengthTag=" + tmp + ", too big.");
252
}
253
254
value = 0x0ff & in.read();
255
tmp--;
256
if (value == 0) {
257
// DER requires length value be encoded in minimum number of bytes
258
throw new IOException(mdName + "Redundant length bytes found");
259
}
260
while (tmp-- > 0) {
261
value <<= 8;
262
value += 0x0ff & in.read();
263
}
264
if (value < 0) {
265
throw new IOException(mdName + "Invalid length bytes");
266
} else if (value <= 127) {
267
throw new IOException(mdName + "Should use short form for length");
268
}
269
}
270
return value;
271
}
272
273
/*
274
* Get a definite length from the input stream.
275
*
276
* @return the length
277
* @exception IOException on parsing error or if indefinite length found.
278
*/
279
static int getDefiniteLength(InputStream in) throws IOException {
280
int len = getLength(in);
281
if (len < 0) {
282
throw new IOException("Indefinite length encoding not supported");
283
}
284
return len;
285
}
286
287
/**
288
* Mark the current position in the buffer, so that
289
* a later call to <code>reset</code> will return here.
290
* The {@code readAheadLimit} is useless here because
291
* all data is available and we can go to anywhere at will.
292
*/
293
public void mark(int readAheadLimit) { mark = pos; }
294
295
/**
296
* Return to the position of the last <code>mark</code>
297
* call. A mark is implicitly set at the beginning of
298
* the stream when it is created.
299
*/
300
public void reset() { pos = mark; }
301
302
/**
303
* Returns the number of bytes available for reading.
304
* This is most useful for testing whether the stream is
305
* empty.
306
*/
307
public int available() { return end - pos; }
308
}
309
310