History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/util/DerInputBuffer.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/util/DerInputBuffer.java+433−0
@@ -0,0 +1,433 @@
1+/*
2+ * Copyright (c) 1996, 2006, 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.ByteArrayInputStream;
29+import java.io.IOException;
30+import java.io.OutputStream;
31+import java.math.BigInteger;
32+import java.util.Date;
33+import sun.util.calendar.CalendarDate;
34+import sun.util.calendar.CalendarSystem;
35+
36+/**
37+ * DER input buffer ... this is the main abstraction in the DER library
38+ * which actively works with the "untyped byte stream" abstraction. It
39+ * does so with impunity, since it's not intended to be exposed to
40+ * anyone who could violate the "typed value stream" DER model and hence
41+ * corrupt the input stream of DER values.
42+ *
43+ * @author David Brownell
44+ */
45+class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
46+
47+ DerInputBuffer(byte[] buf) { super(buf); }
48+
49+ DerInputBuffer(byte[] buf, int offset, int len) {
50+ super(buf, offset, len);
51+ }
52+
53+ DerInputBuffer dup() {
54+ try {
55+ DerInputBuffer retval = (DerInputBuffer)clone();
56+
57+ retval.mark(Integer.MAX_VALUE);
58+ return retval;
59+ } catch (CloneNotSupportedException e) {
60+ throw new IllegalArgumentException(e.toString());
61+ }
62+ }
63+
64+ byte[] toByteArray() {
65+ int len = available();
66+ if (len <= 0)
67+ return null;
68+ byte[] retval = new byte[len];
69+
70+ System.arraycopy(buf, pos, retval, 0, len);
71+ return retval;
72+ }
73+
74+ int peek() throws IOException {
75+ if (pos >= count)
76+ throw new IOException("out of data");
77+ else
78+ return buf[pos];
79+ }
80+
81+ /**
82+ * Compares this DerInputBuffer for equality with the specified
83+ * object.
84+ */
85+ public boolean equals(Object other) {
86+ if (other instanceof DerInputBuffer)
87+ return equals((DerInputBuffer)other);
88+ else
89+ return false;
90+ }
91+
92+ boolean equals(DerInputBuffer other) {
93+ if (this == other)
94+ return true;
95+
96+ int max = this.available();
97+ if (other.available() != max)
98+ return false;
99+ for (int i = 0; i < max; i++) {
100+ if (this.buf[this.pos + i] != other.buf[other.pos + i]) {
101+ return false;
102+ }
103+ }
104+ return true;
105+ }
106+
107+ /**
108+ * Returns a hashcode for this DerInputBuffer.
109+ *
110+ * @return a hashcode for this DerInputBuffer.
111+ */
112+ public int hashCode() {
113+ int retval = 0;
114+
115+ int len = available();
116+ int p = pos;
117+
118+ for (int i = 0; i < len; i++)
119+ retval += buf[p + i] * i;
120+ return retval;
121+ }
122+
123+ void truncate(int len) throws IOException {
124+ if (len > available())
125+ throw new IOException("insufficient data");
126+ count = pos + len;
127+ }
128+
129+ /**
130+ * Returns the integer which takes up the specified number
131+ * of bytes in this buffer as a BigInteger.
132+ * @param len the number of bytes to use.
133+ * @param makePositive whether to always return a positive value,
134+ * irrespective of actual encoding
135+ * @return the integer as a BigInteger.
136+ */
137+ BigInteger getBigInteger(int len, boolean makePositive) throws IOException {
138+ if (len > available())
139+ throw new IOException("short read of integer");
140+
141+ if (len == 0) {
142+ throw new IOException("Invalid encoding: zero length Int value");
143+ }
144+
145+ byte[] bytes = new byte[len];
146+
147+ System.arraycopy(buf, pos, bytes, 0, len);
148+ skip(len);
149+
150+ if (makePositive) {
151+ return new BigInteger(1, bytes);
152+ } else {
153+ return new BigInteger(bytes);
154+ }
155+ }
156+
157+ /**
158+ * Returns the integer which takes up the specified number
159+ * of bytes in this buffer.
160+ * @throws IOException if the result is not within the valid
161+ * range for integer, i.e. between Integer.MIN_VALUE and
162+ * Integer.MAX_VALUE.
163+ * @param len the number of bytes to use.
164+ * @return the integer.
165+ */
166+ public int getInteger(int len) throws IOException {
167+
168+ BigInteger result = getBigInteger(len, false);
169+ if (result.compareTo(BigInteger.valueOf(Integer.MIN_VALUE)) < 0) {
170+ throw new IOException("Integer below minimum valid value");
171+ }
172+ if (result.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) > 0) {
173+ throw new IOException("Integer exceeds maximum valid value");
174+ }
175+ return result.intValue();
176+ }
177+
178+ /**
179+ * Returns the bit string which takes up the specified
180+ * number of bytes in this buffer.
181+ */
182+ public byte[] getBitString(int len) throws IOException {
183+ if (len > available())
184+ throw new IOException("short read of bit string");
185+
186+ if (len == 0) {
187+ throw new IOException("Invalid encoding: zero length bit string");
188+ }
189+
190+ int numOfPadBits = buf[pos];
191+ if ((numOfPadBits < 0) || (numOfPadBits > 7)) {
192+ throw new IOException("Invalid number of padding bits");
193+ }
194+ // minus the first byte which indicates the number of padding bits
195+ byte[] retval = new byte[len - 1];
196+ System.arraycopy(buf, pos + 1, retval, 0, len - 1);
197+ if (numOfPadBits != 0) {
198+ // get rid of the padding bits
199+ retval[len - 2] &= (0xff << numOfPadBits);
200+ }
201+ skip(len);
202+ return retval;
203+ }
204+
205+ /**
206+ * Returns the bit string which takes up the rest of this buffer.
207+ */
208+ byte[] getBitString() throws IOException {
209+ return getBitString(available());
210+ }
211+
212+ /**
213+ * Returns the bit string which takes up the rest of this buffer.
214+ * The bit string need not be byte-aligned.
215+ */
216+ BitArray getUnalignedBitString() throws IOException {
217+ if (pos >= count)
218+ return null;
219+ /*
220+ * Just copy the data into an aligned, padded octet buffer,
221+ * and consume the rest of the buffer.
222+ */
223+ int len = available();
224+ int unusedBits = buf[pos] & 0xff;
225+ if (unusedBits > 7 ) {
226+ throw new IOException("Invalid value for unused bits: " + unusedBits);
227+ }
228+ byte[] bits = new byte[len - 1];
229+ // number of valid bits
230+ int length = (bits.length == 0) ? 0 : bits.length * 8 - unusedBits;
231+
232+ System.arraycopy(buf, pos + 1, bits, 0, len - 1);
233+
234+ BitArray bitArray = new BitArray(length, bits);
235+ pos = count;
236+ return bitArray;
237+ }
238+
239+ /**
240+ * Returns the UTC Time value that takes up the specified number
241+ * of bytes in this buffer.
242+ * @param len the number of bytes to use
243+ */
244+ public Date getUTCTime(int len) throws IOException {
245+ if (len > available())
246+ throw new IOException("short read of DER UTC Time");
247+
248+ if (len < 11 || len > 17)
249+ throw new IOException("DER UTC Time length error");
250+
251+ return getTime(len, false);
252+ }
253+
254+ /**
255+ * Returns the Generalized Time value that takes up the specified
256+ * number of bytes in this buffer.
257+ * @param len the number of bytes to use
258+ */
259+ public Date getGeneralizedTime(int len) throws IOException {
260+ if (len > available())
261+ throw new IOException("short read of DER Generalized Time");
262+
263+ if (len < 13 || len > 23)
264+ throw new IOException("DER Generalized Time length error");
265+
266+ return getTime(len, true);
267+
268+ }
269+
270+ /**
271+ * Private helper routine to extract time from the der value.
272+ * @param len the number of bytes to use
273+ * @param generalized true if Generalized Time is to be read, false
274+ * if UTC Time is to be read.
275+ */
276+ private Date getTime(int len, boolean generalized) throws IOException {
277+
278+ /*
279+ * UTC time encoded as ASCII chars:
280+ * YYMMDDhhmmZ
281+ * YYMMDDhhmmssZ
282+ * YYMMDDhhmm+hhmm
283+ * YYMMDDhhmm-hhmm
284+ * YYMMDDhhmmss+hhmm
285+ * YYMMDDhhmmss-hhmm
286+ * UTC Time is broken in storing only two digits of year.
287+ * If YY < 50, we assume 20YY;
288+ * if YY >= 50, we assume 19YY, as per RFC 3280.
289+ *
290+ * Generalized time has a four-digit year and allows any
291+ * precision specified in ISO 8601. However, for our purposes,
292+ * we will only allow the same format as UTC time, except that
293+ * fractional seconds (millisecond precision) are supported.
294+ */
295+
296+ int year, month, day, hour, minute, second, millis;
297+ String type = null;
298+
299+ if (generalized) {
300+ type = "Generalized";
301+ year = 1000 * Character.digit((char)buf[pos++], 10);
302+ year += 100 * Character.digit((char)buf[pos++], 10);
303+ year += 10 * Character.digit((char)buf[pos++], 10);
304+ year += Character.digit((char)buf[pos++], 10);
305+ len -= 2; // For the two extra YY
306+ } else {
307+ type = "UTC";
308+ year = 10 * Character.digit((char)buf[pos++], 10);
309+ year += Character.digit((char)buf[pos++], 10);
310+
311+ if (year < 50) // origin 2000
312+ year += 2000;
313+ else
314+ year += 1900; // origin 1900
315+ }
316+
317+ month = 10 * Character.digit((char)buf[pos++], 10);
318+ month += Character.digit((char)buf[pos++], 10);
319+
320+ day = 10 * Character.digit((char)buf[pos++], 10);
321+ day += Character.digit((char)buf[pos++], 10);
322+
323+ hour = 10 * Character.digit((char)buf[pos++], 10);
324+ hour += Character.digit((char)buf[pos++], 10);
325+
326+ minute = 10 * Character.digit((char)buf[pos++], 10);
327+ minute += Character.digit((char)buf[pos++], 10);
328+
329+ len -= 10; // YYMMDDhhmm
330+
331+ /*
332+ * We allow for non-encoded seconds, even though the
333+ * IETF-PKIX specification says that the seconds should
334+ * always be encoded even if it is zero.
335+ */
336+
337+ millis = 0;
338+ if (len > 2 && len < 12) {
339+ second = 10 * Character.digit((char)buf[pos++], 10);
340+ second += Character.digit((char)buf[pos++], 10);
341+ len -= 2;
342+ // handle fractional seconds (if present)
343+ if (buf[pos] == '.' || buf[pos] == ',') {
344+ len --;
345+ pos++;
346+ // handle upto milisecond precision only
347+ int precision = 0;
348+ int peek = pos;
349+ while (buf[peek] != 'Z' &&
350+ buf[peek] != '+' &&
351+ buf[peek] != '-') {
352+ peek++;
353+ precision++;
354+ }
355+ switch (precision) {
356+ case 3:
357+ millis += 100 * Character.digit((char)buf[pos++], 10);
358+ millis += 10 * Character.digit((char)buf[pos++], 10);
359+ millis += Character.digit((char)buf[pos++], 10);
360+ break;
361+ case 2:
362+ millis += 100 * Character.digit((char)buf[pos++], 10);
363+ millis += 10 * Character.digit((char)buf[pos++], 10);
364+ break;
365+ case 1:
366+ millis += 100 * Character.digit((char)buf[pos++], 10);
367+ break;
368+ default:
369+ throw new IOException("Parse " + type +
370+ " time, unsupported precision for seconds value");
371+ }
372+ len -= precision;
373+ }
374+ } else
375+ second = 0;
376+
377+ if (month == 0 || day == 0
378+ || month > 12 || day > 31
379+ || hour >= 24 || minute >= 60 || second >= 60)
380+ throw new IOException("Parse " + type + " time, invalid format");
381+
382+ /*
383+ * Generalized time can theoretically allow any precision,
384+ * but we're not supporting that.
385+ */
386+ CalendarSystem gcal = CalendarSystem.getGregorianCalendar();
387+ CalendarDate date = gcal.newCalendarDate(null); // no time zone
388+ date.setDate(year, month, day);
389+ date.setTimeOfDay(hour, minute, second, millis);
390+ long time = gcal.getTime(date);
391+
392+ /*
393+ * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm
394+ */
395+ if (! (len == 1 || len == 5))
396+ throw new IOException("Parse " + type + " time, invalid offset");
397+
398+ int hr, min;
399+
400+ switch (buf[pos++]) {
401+ case '+':
402+ hr = 10 * Character.digit((char)buf[pos++], 10);
403+ hr += Character.digit((char)buf[pos++], 10);
404+ min = 10 * Character.digit((char)buf[pos++], 10);
405+ min += Character.digit((char)buf[pos++], 10);
406+
407+ if (hr >= 24 || min >= 60)
408+ throw new IOException("Parse " + type + " time, +hhmm");
409+
410+ time -= ((hr * 60) + min) * 60 * 1000;
411+ break;
412+
413+ case '-':
414+ hr = 10 * Character.digit((char)buf[pos++], 10);
415+ hr += Character.digit((char)buf[pos++], 10);
416+ min = 10 * Character.digit((char)buf[pos++], 10);
417+ min += Character.digit((char)buf[pos++], 10);
418+
419+ if (hr >= 24 || min >= 60)
420+ throw new IOException("Parse " + type + " time, -hhmm");
421+
422+ time += ((hr * 60) + min) * 60 * 1000;
423+ break;
424+
425+ case 'Z':
426+ break;
427+
428+ default:
429+ throw new IOException("Parse " + type + " time, garbage offset");
430+ }
431+ return new Date(time);
432+ }
433+}