diff options
Diffstat (limited to 'pki/base/util/src/netscape/security/util/DerInputStream.java')
-rw-r--r-- | pki/base/util/src/netscape/security/util/DerInputStream.java | 754 |
1 files changed, 383 insertions, 371 deletions
diff --git a/pki/base/util/src/netscape/security/util/DerInputStream.java b/pki/base/util/src/netscape/security/util/DerInputStream.java index 6e5e25ff1..fb73b761e 100644 --- a/pki/base/util/src/netscape/security/util/DerInputStream.java +++ b/pki/base/util/src/netscape/security/util/DerInputStream.java @@ -26,92 +26,93 @@ import java.util.TimeZone; import java.util.Vector; /** - * A DER input stream, used for parsing ASN.1 DER-encoded data such as that - * found in X.509 certificates. DER is a subset of BER/1, which has the - * advantage that it allows only a single encoding of primitive data. (High - * level data such as dates still support many encodings.) That is, it uses the - * "Definite" Encoding Rules (DER) not the "Basic" ones (BER). - * - * <P> - * Note that, like BER/1, DER streams are streams of explicitly tagged data - * values. Accordingly, this programming interface does not expose any variant - * of the java.io.InputStream interface, since that kind of input stream holds - * untagged data values and using that I/O model could prevent correct parsing - * of the DER data. - * - * <P> - * At this time, this class supports only a subset of the types of DER data - * encodings which are defined. That subset is sufficient for parsing most X.509 - * certificates. - * + * A DER input stream, used for parsing ASN.1 DER-encoded data such as + * that found in X.509 certificates. DER is a subset of BER/1, which has + * the advantage that it allows only a single encoding of primitive data. + * (High level data such as dates still support many encodings.) That is, + * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER). + * + * <P>Note that, like BER/1, DER streams are streams of explicitly + * tagged data values. Accordingly, this programming interface does + * not expose any variant of the java.io.InputStream interface, since + * that kind of input stream holds untagged data values and using that + * I/O model could prevent correct parsing of the DER data. + * + * <P>At this time, this class supports only a subset of the types of DER + * data encodings which are defined. That subset is sufficient for parsing + * most X.509 certificates. + * * @version 1.35 - * + * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class DerInputStream { /* - * This version only supports fully buffered DER. This is easy to work with, - * though if large objects are manipulated DER becomes awkward to deal with. - * That's where BER is useful, since BER handles streaming data relatively - * well. + * This version only supports fully buffered DER. This is easy to + * work with, though if large objects are manipulated DER becomes + * awkward to deal with. That's where BER is useful, since BER + * handles streaming data relatively well. */ - DerInputBuffer buffer; + DerInputBuffer buffer; /** - * Create a DER input stream from a data buffer. The buffer is not copied, - * it is shared. Accordingly, the buffer should be treated as read-only. - * + * Create a DER input stream from a data buffer. The buffer is not + * copied, it is shared. Accordingly, the buffer should be treated + * as read-only. + * * @param data the buffer from which to create the string (CONSUMED) */ public DerInputStream(byte[] data) { - buffer = new DerInputBuffer(data); - buffer.mark(Integer.MAX_VALUE); + buffer = new DerInputBuffer(data); + buffer.mark(Integer.MAX_VALUE); } /** - * Create a DER input stream from part of a data buffer. The buffer is not - * copied, it is shared. Accordingly, the buffer should be treated as - * read-only. - * + * Create a DER input stream from part of a data buffer. + * The buffer is not copied, it is shared. Accordingly, the + * buffer should be treated as read-only. + * * @param data the buffer from which to create the string (CONSUMED) - * @param offset the first index of <em>data</em> which will be read as DER - * input in the new stream - * @param len how long a chunk of the buffer to use, starting at "offset" + * @param offset the first index of <em>data</em> which will + * be read as DER input in the new stream + * @param len how long a chunk of the buffer to use, + * starting at "offset" */ public DerInputStream(byte[] data, int offset, int len) { - buffer = new DerInputBuffer(data, offset, len); - buffer.mark(Integer.MAX_VALUE); + buffer = new DerInputBuffer(data, offset, len); + buffer.mark(Integer.MAX_VALUE); } DerInputStream(DerInputBuffer buf) { - buffer = buf; - buffer.mark(Integer.MAX_VALUE); + buffer = buf; + buffer.mark(Integer.MAX_VALUE); } /** * Creates a new DER input stream from part of this input stream. * - * @param len how long a chunk of the current input stream to use, starting - * at the current position. - * @param do_skip true if the existing data in the input stream should be - * skipped. If this value is false, the next data read on this - * stream and the newly created stream will be the same. + * @param len how long a chunk of the current input stream to use, + * starting at the current position. + * @param do_skip true if the existing data in the input stream should + * be skipped. If this value is false, the next data read + * on this stream and the newly created stream will be the + * same. */ - public DerInputStream subStream(int len, boolean do_skip) - throws IOException { - DerInputBuffer newbuf = buffer.dup(); - - newbuf.truncate(len); - if (do_skip) - buffer.skip(len); - return new DerInputStream(newbuf); + public DerInputStream subStream(int len, boolean do_skip) + throws IOException { + DerInputBuffer newbuf = buffer.dup(); + + newbuf.truncate(len); + if (do_skip) + buffer.skip(len); + return new DerInputStream(newbuf); } /** - * Return what has been written to this DerInputStream as a byte array. - * Useful for debugging. + * Return what has been written to this DerInputStream + * as a byte array. Useful for debugging. */ public byte[] toByteArray() { return buffer.toByteArray(); @@ -119,9 +120,10 @@ public class DerInputStream { /* * PRIMITIVES -- these are "universal" ASN.1 simple types. - * - * INTEGER, BIT STRING, OCTET STRING, NULL OBJECT IDENTIFIER, SEQUENCE (OF), - * SET (OF) PrintableString, T61String, IA5String, UTCTime + * + * INTEGER, BIT STRING, OCTET STRING, NULL + * OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF) + * PrintableString, T61String, IA5String, UTCTime */ /** @@ -131,236 +133,245 @@ public class DerInputStream { if (buffer.read() != DerValue.tag_Integer) throw new IOException("DER input, Integer tag error"); - return buffer.getUnsigned(getLength(buffer)); + return buffer.getUnsigned(getLength(buffer)); } /** - * Get a bit string from the input stream. Only octet-aligned bitstrings - * (multiples of eight bits in length) are handled by this method. + * Get a bit string from the input stream. Only octet-aligned + * bitstrings (multiples of eight bits in length) are handled + * by this method. */ public byte[] getBitString() throws IOException { - if (buffer.read() != DerValue.tag_BitString) - throw new IOException("DER input not an bit string"); - int length = getLength(buffer); - - /* - * This byte affects alignment and padding (for the last byte). Use - * getUnalignedBitString() for none 8-bit aligned bit strings. - */ - if (buffer.read() != 0) - return null; - length--; - - /* - * Just read the data into an aligned, padded octet buffer. - */ - byte[] retval = new byte[length]; - if (buffer.read(retval) != length) - throw new IOException("short read of DER bit string"); - return retval; + if (buffer.read() != DerValue.tag_BitString) + throw new IOException("DER input not an bit string"); + int length = getLength(buffer); + + /* + * This byte affects alignment and padding (for the last byte). + * Use getUnalignedBitString() for none 8-bit aligned bit strings. + */ + if (buffer.read() != 0) + return null; + length--; + + /* + * Just read the data into an aligned, padded octet buffer. + */ + byte[] retval = new byte[length]; + if (buffer.read(retval) != length) + throw new IOException("short read of DER bit string"); + return retval; } /** - * Get a bit string from the input stream. The bit string need not be - * byte-aligned. + * Get a bit string from the input stream. The bit string need + * not be byte-aligned. */ public BitArray getUnalignedBitString() throws IOException { - if (buffer.read() != DerValue.tag_BitString) - throw new IOException("DER input not a bit string"); + if (buffer.read() != DerValue.tag_BitString) + throw new IOException("DER input not a bit string"); - int length = getLength(buffer) - 1; + int length = getLength(buffer) - 1; - /* - * First byte = number of excess bits in the last octet of the - * representation. - */ - int validBits = length * 8 - buffer.read(); + /* + * First byte = number of excess bits in the last octet of the + * representation. + */ + int validBits = length*8 - buffer.read(); - byte[] repn = new byte[length]; + byte[] repn = new byte[length]; - if (buffer.read(repn) != length) - throw new IOException("short read of DER bit string"); - return new BitArray(validBits, repn); + if (buffer.read(repn) != length) + throw new IOException("short read of DER bit string"); + return new BitArray(validBits, repn); } /** * Returns an ASN.1 OCTET STRING from the input stream. */ public byte[] getOctetString() throws IOException { - if (buffer.read() != DerValue.tag_OctetString) - throw new IOException("DER input not an octet string"); + if (buffer.read() != DerValue.tag_OctetString) + throw new IOException("DER input not an octet string"); - int length = getLength(buffer); - byte[] retval = new byte[length]; - if (buffer.read(retval) != length) - throw new IOException("short read of DER octet string"); + int length = getLength(buffer); + byte[] retval = new byte[length]; + if (buffer.read(retval) != length) + throw new IOException("short read of DER octet string"); - return retval; + return retval; } /** * Returns the asked number of bytes from the input stream. */ public void getBytes(byte[] val) throws IOException { - if (val.length != 0) { + if (val.length != 0) { if (buffer.read(val) != val.length) { - throw new IOException("short read of DER octet string"); - } - } + throw new IOException("short read of DER octet string"); + } + } } /** * Reads an encoded null value from the input stream. */ public void getNull() throws IOException { - if (buffer.read() != DerValue.tag_Null || buffer.read() != 0) - throw new IOException("getNull, bad data"); + if (buffer.read() != DerValue.tag_Null || buffer.read() != 0) + throw new IOException("getNull, bad data"); } /** * Reads an X.200 style Object Identifier from the stream. */ public ObjectIdentifier getOID() throws IOException { - return new ObjectIdentifier(this); + return new ObjectIdentifier(this); } /** - * Return a sequence of encoded entities. ASN.1 sequences are ordered, and - * they are often used, like a "struct" in C or C++, to group data values. - * They may have optional or context specific values. - * - * @param startLen guess about how long the sequence will be (used to - * initialize an auto-growing data structure) + * Return a sequence of encoded entities. ASN.1 sequences are + * ordered, and they are often used, like a "struct" in C or C++, + * to group data values. They may have optional or context + * specific values. + * + * @param startLen guess about how long the sequence will be + * (used to initialize an auto-growing data structure) * @return array of the values in the sequence */ public DerValue[] getSequence(int startLen) throws IOException { - int b = buffer.read(); - if (b != DerValue.tag_Sequence) - throw new IOException("Sequence tag error " + b); - return readVector(startLen); + int b = buffer.read(); + if (b != DerValue.tag_Sequence) + throw new IOException("Sequence tag error " + b); + return readVector(startLen); } public void skipSequence(int startLen) throws IOException { - int b = buffer.read(); - if (b != DerValue.tag_Sequence) - throw new IOException("Sequence tag error " + b); - int len = getLength(buffer); - buffer.skip(len); + int b = buffer.read(); + if (b != DerValue.tag_Sequence) + throw new IOException("Sequence tag error " + b); + int len = getLength(buffer); + buffer.skip(len); } /** - * Return a set of encoded entities. ASN.1 sets are unordered, though DER - * may specify an order for some kinds of sets (such as the attributes in an - * X.500 relative distinguished name) to facilitate binary comparisons of - * encoded values. - * - * @param startLen guess about how large the set will be (used to initialize - * an auto-growing data structure) + * Return a set of encoded entities. ASN.1 sets are unordered, + * though DER may specify an order for some kinds of sets (such + * as the attributes in an X.500 relative distinguished name) + * to facilitate binary comparisons of encoded values. + * + * @param startLen guess about how large the set will be + * (used to initialize an auto-growing data structure) * @return array of the values in the sequence */ public DerValue[] getSet(int startLen) throws IOException { - if (buffer.read() != DerValue.tag_Set) - throw new IOException("Set tag error"); - return readVector(startLen); + if (buffer.read() != DerValue.tag_Set) + throw new IOException("Set tag error"); + return readVector(startLen); } /** - * Return a set of encoded entities. ASN.1 sets are unordered, though DER - * may specify an order for some kinds of sets (such as the attributes in an - * X.500 relative distinguished name) to facilitate binary comparisons of - * encoded values. - * - * @param startLen guess about how large the set will be (used to initialize - * an auto-growing data structure) + * Return a set of encoded entities. ASN.1 sets are unordered, + * though DER may specify an order for some kinds of sets (such + * as the attributes in an X.500 relative distinguished name) + * to facilitate binary comparisons of encoded values. + * + * @param startLen guess about how large the set will be + * (used to initialize an auto-growing data structure) * @param implicit if true tag is assumed implicit. * @return array of the values in the sequence */ public DerValue[] getSet(int startLen, boolean implicit) throws IOException { int tag = buffer.read(); - if (!implicit) { - if (tag != DerValue.tag_Set) { - throw new IOException("Set tag error"); - } - } - return (readVector(startLen)); + if (!implicit) { + if (tag != DerValue.tag_Set) { + throw new IOException("Set tag error"); + } + } + return (readVector(startLen)); } /* - * Read a "vector" of values ... set or sequence have the same encoding, - * except for the initial tag, so both use this same helper routine. + * Read a "vector" of values ... set or sequence have the + * same encoding, except for the initial tag, so both use + * this same helper routine. */ protected DerValue[] readVector(int startLen) throws IOException { - int len = getLength(buffer); - DerInputStream newstr; + int len = getLength(buffer); + DerInputStream newstr; - if (len == 0) - // return empty array instead of null, which should be - // used only for missing optionals - return new DerValue[0]; + if (len == 0) + // return empty array instead of null, which should be + // used only for missing optionals + return new DerValue[0]; - /* - * Create a temporary stream from which to read the data, unless it's - * not really needed. - */ - if (buffer.available() == len) - newstr = this; - else - newstr = subStream(len, true); + /* + * Create a temporary stream from which to read the data, + * unless it's not really needed. + */ + if (buffer.available() == len) + newstr = this; + else + newstr = subStream(len, true); - /* - * Pull values out of the stream. - */ - Vector vec = new Vector(startLen); - DerValue value; + /* + * Pull values out of the stream. + */ + Vector vec = new Vector(startLen); + DerValue value; - do { - value = new DerValue(newstr.buffer); - vec.addElement(value); - } while (newstr.available() > 0); + do { + value = new DerValue(newstr.buffer); + vec.addElement(value); + } while (newstr.available() > 0); - if (newstr.available() != 0) - throw new IOException("extra data at end of vector"); + if (newstr.available() != 0) + throw new IOException("extra data at end of vector"); - /* - * Now stick them into the array we're returning. - */ - int i, max = vec.size(); - DerValue[] retval = new DerValue[max]; + /* + * Now stick them into the array we're returning. + */ + int i, max = vec.size(); + DerValue[] retval = new DerValue[max]; - for (i = 0; i < max; i++) - retval[i] = (DerValue) vec.elementAt(i); + for (i = 0; i < max; i++) + retval[i] = (DerValue) vec.elementAt(i); - return retval; + return retval; } /** - * Get a single DER-encoded value from the input stream. It can often be - * useful to pull a value from the stream and defer parsing it. For example, - * you can pull a nested sequence out with one call, and only examine its - * elements later when you really need to. + * Get a single DER-encoded value from the input stream. + * It can often be useful to pull a value from the stream + * and defer parsing it. For example, you can pull a nested + * sequence out with one call, and only examine its elements + * later when you really need to. */ public DerValue getDerValue() throws IOException { - return new DerValue(buffer); + return new DerValue(buffer); } - public String getPrintableString() throws IOException { - return (new DerValue(buffer)).getPrintableString(); + public String getPrintableString() throws IOException + { + return (new DerValue(buffer)).getPrintableString(); } - public String getT61String() throws IOException { - return (new DerValue(buffer)).getT61String(); + public String getT61String() throws IOException + { + return (new DerValue(buffer)).getT61String(); } - public String getIA5String() throws IOException { - return (new DerValue(buffer)).getIA5String(); + public String getIA5String() throws IOException + { + return (new DerValue(buffer)).getIA5String(); } - public String getBMPString() throws IOException { - return (new DerValue(buffer)).getBMPString(); + public String getBMPString () throws IOException + { + return (new DerValue(buffer)).getBMPString(); } - public String getUniversalString() throws IOException { - return (new DerValue(buffer)).getUniversalString(); + public String getUniversalString () throws IOException + { + return (new DerValue(buffer)).getUniversalString(); } /** @@ -369,7 +380,7 @@ public class DerInputStream { public Date getUTCTime() throws IOException { if (buffer.read() != DerValue.tag_UtcTime) throw new IOException("DER input, UTCtime tag invalid "); - if (buffer.available() < 11) + if (buffer.available() < 11) throw new IOException("DER input, UTCtime short input"); int len = getLength(buffer); @@ -378,53 +389,55 @@ public class DerInputStream { throw new IOException("DER getUTCTime length error"); /* - * UTC time encoded as ASCII chars, YYMMDDhhmmss. If YY <= 50, we assume - * 20YY; if YY > 50, we assume 19YY, as per IETF-PKIX part I. + * UTC time encoded as ASCII chars, YYMMDDhhmmss. + * If YY <= 50, we assume 20YY; + * if YY > 50, we assume 19YY, as per IETF-PKIX part I. */ int year, month, day, hour, minute, second; - year = 10 * Character.digit((char) buffer.read(), 10); - year += Character.digit((char) buffer.read(), 10); - if (year <= 50) // origin 2000 + year = 10 * Character.digit((char)buffer.read(), 10); + year += Character.digit((char)buffer.read(), 10); + if (year <= 50) // origin 2000 year += 2000; else - year += 1900; // origin 1900 + year += 1900; // origin 1900 - month = 10 * Character.digit((char) buffer.read(), 10); - month += Character.digit((char) buffer.read(), 10); - month -= 1; // months are 0-11 + month = 10 * Character.digit((char)buffer.read(), 10); + month += Character.digit((char)buffer.read(), 10); + month -= 1; // months are 0-11 - day = 10 * Character.digit((char) buffer.read(), 10); - day += Character.digit((char) buffer.read(), 10); + day = 10 * Character.digit((char)buffer.read(), 10); + day += Character.digit((char)buffer.read(), 10); - hour = 10 * Character.digit((char) buffer.read(), 10); - hour += Character.digit((char) buffer.read(), 10); + hour = 10 * Character.digit((char)buffer.read(), 10); + hour += Character.digit((char)buffer.read(), 10); - minute = 10 * Character.digit((char) buffer.read(), 10); - minute += Character.digit((char) buffer.read(), 10); + minute = 10 * Character.digit((char)buffer.read(), 10); + minute += Character.digit((char)buffer.read(), 10); - len -= 10; + len -= 10; /** - * We allow for non-encoded seconds, even though the IETF-PKIX - * specification says that the seconds should always be encoded even if - * it is zero. + * We allow for non-encoded seconds, even though the + * IETF-PKIX specification says that the seconds should + * always be encoded even if it is zero. */ if (len == 3 || len == 7) { - second = 10 * Character.digit((char) buffer.read(), 10); - second += Character.digit((char) buffer.read(), 10); - len -= 2; + second = 10 * Character.digit((char)buffer.read(), 10); + second += Character.digit((char)buffer.read(), 10); + len -= 2; } else second = 0; - if (month < 0 || day <= 0 || month > 11 || day > 31 || hour >= 24 + if (month < 0 || day <= 0 + || month > 11 || day > 31 || hour >= 24 || minute >= 60 || second >= 60) throw new IOException("Parse UTC time, invalid format"); - - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal.set(year, month, day, hour, minute, second); - cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */ + + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal.set(year, month, day, hour, minute, second); + cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */ cal.set(Calendar.ERA, GregorianCalendar.AD); Date readDate = cal.getTime(); long utcTime = readDate.getTime(); @@ -432,41 +445,43 @@ public class DerInputStream { /* * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm */ - if (!(len == 1 || len == 5)) + if (! (len == 1 || len == 5)) throw new IOException("Parse UTC time, invalid offset"); switch (buffer.read()) { - case '+': { - int Htmp = 10 * Character.digit((char) buffer.read(), 10); - Htmp += Character.digit((char) buffer.read(), 10); - int Mtmp = 10 * Character.digit((char) buffer.read(), 10); - Mtmp += Character.digit((char) buffer.read(), 10); - - if (Htmp >= 24 || Mtmp >= 60) - throw new IOException("Parse UTCtime, +hhmm"); - - utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000; - } - break; - - case '-': { - int Htmp = 10 * Character.digit((char) buffer.read(), 10); - Htmp += Character.digit((char) buffer.read(), 10); - int Mtmp = 10 * Character.digit((char) buffer.read(), 10); - Mtmp += Character.digit((char) buffer.read(), 10); - - if (Htmp >= 24 || Mtmp >= 60) - throw new IOException("Parse UTCtime, -hhmm"); - - utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000; - } - break; - - case 'Z': - break; - - default: - throw new IOException("Parse UTCtime, garbage offset"); + case '+': + { + int Htmp = 10 * Character.digit((char)buffer.read(), 10); + Htmp += Character.digit((char)buffer.read(), 10); + int Mtmp = 10 * Character.digit((char)buffer.read(), 10); + Mtmp += Character.digit((char)buffer.read(), 10); + + if (Htmp >=24 || Mtmp >= 60) + throw new IOException("Parse UTCtime, +hhmm"); + + utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000; + } + break; + + case '-': + { + int Htmp = 10 * Character.digit((char)buffer.read(), 10); + Htmp += Character.digit((char)buffer.read(), 10); + int Mtmp = 10 * Character.digit((char)buffer.read(), 10); + Mtmp += Character.digit((char)buffer.read(), 10); + + if (Htmp >=24 || Mtmp >= 60) + throw new IOException("Parse UTCtime, -hhmm"); + + utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000; + } + break; + + case 'Z': + break; + + default: + throw new IOException("Parse UTCtime, garbage offset"); } readDate.setTime(utcTime); return readDate; @@ -476,63 +491,62 @@ public class DerInputStream { * Get a Generalized encoded time value from the input stream. */ public Date getGeneralizedTime() throws IOException { - if (buffer.read() != DerValue.tag_GeneralizedTime) - throw new IOException("DER input, GeneralizedTime tag invalid "); + if (buffer.read () != DerValue.tag_GeneralizedTime) + throw new IOException ("DER input, GeneralizedTime tag invalid "); + + if (buffer.available() < 13) + throw new IOException ("DER input, GeneralizedTime short input"); - if (buffer.available() < 13) - throw new IOException("DER input, GeneralizedTime short input"); - - int len = getLength(buffer); + int len = getLength (buffer); /* * Generalized time encoded as ASCII chars, YYYYMMDDhhmm[ss] */ int year, month, day, hour, minute, second; - year = 1000 * Character.digit((char) buffer.read(), 10); - year += 100 * Character.digit((char) buffer.read(), 10); - year += 10 * Character.digit((char) buffer.read(), 10); - year += Character.digit((char) buffer.read(), 10); + year = 1000 * Character.digit ((char)buffer.read (), 10); + year += 100 * Character.digit ((char)buffer.read (), 10); + year += 10 * Character.digit ((char)buffer.read (), 10); + year += Character.digit ((char)buffer.read (), 10); - month = 10 * Character.digit((char) buffer.read(), 10); - month += Character.digit((char) buffer.read(), 10); - month -= 1; // Calendar months are 0-11 + month = 10 * Character.digit ((char)buffer.read (), 10); + month += Character.digit ((char)buffer.read (), 10); + month -= 1; // Calendar months are 0-11 - day = 10 * Character.digit((char) buffer.read(), 10); - day += Character.digit((char) buffer.read(), 10); + day = 10 * Character.digit ((char)buffer.read (), 10); + day += Character.digit ((char)buffer.read (), 10); - hour = 10 * Character.digit((char) buffer.read(), 10); - hour += Character.digit((char) buffer.read(), 10); + hour = 10 * Character.digit ((char)buffer.read (), 10); + hour += Character.digit ((char)buffer.read (), 10); - minute = 10 * Character.digit((char) buffer.read(), 10); - minute += Character.digit((char) buffer.read(), 10); + minute = 10 * Character.digit ((char)buffer.read (), 10); + minute += Character.digit ((char)buffer.read (), 10); len -= 12; /** - * We allow for non-encoded seconds, even though the IETF-PKIX - * specification says that the seconds should always be encoded even if - * it is zero. + * We allow for non-encoded seconds, even though the + * IETF-PKIX specification says that the seconds should + * always be encoded even if it is zero. */ if (len == 3 || len == 7) { - second = 10 * Character.digit((char) buffer.read(), 10); - second += Character.digit((char) buffer.read(), 10); - len -= 2; + second = 10 * Character.digit ((char)buffer.read (), 10); + second += Character.digit ((char)buffer.read (), 10); + len -= 2; } else second = 0; - if (month < 0 || day <= 0 || month > 11 || day > 31 || hour >= 24 + if (month < 0 || day <= 0 + || month > 11 || day > 31 || hour >= 24 || minute >= 60 || second >= 60) throw new IOException("Parse Generalized time, invalid format"); - - /* - * Shouldn't this construct a Gregorian calendar directly??? We don't - * really want locale dependant processing here - */ - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - cal.set(year, month, day, hour, minute, second); - cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */ + +/* Shouldn't this construct a Gregorian calendar directly??? + * We don't really want locale dependant processing here */ + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + cal.set(year, month, day, hour, minute, second); + cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */ cal.set(Calendar.ERA, GregorianCalendar.AD); Date readDate = cal.getTime(); long utcTime = readDate.getTime(); @@ -540,41 +554,43 @@ public class DerInputStream { /* * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm */ - if (!(len == 1 || len == 5)) - throw new IOException("Parse Generalized time, invalid offset"); - - switch (buffer.read()) { - case '+': { - int Htmp = 10 * Character.digit((char) buffer.read(), 10); - Htmp += Character.digit((char) buffer.read(), 10); - int Mtmp = 10 * Character.digit((char) buffer.read(), 10); - Mtmp += Character.digit((char) buffer.read(), 10); - - if (Htmp >= 24 || Mtmp >= 60) - throw new IOException("Parse GeneralizedTime, +hhmm"); - - utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000; - } - break; - - case '-': { - int Htmp = 10 * Character.digit((char) buffer.read(), 10); - Htmp += Character.digit((char) buffer.read(), 10); - int Mtmp = 10 * Character.digit((char) buffer.read(), 10); - Mtmp += Character.digit((char) buffer.read(), 10); - - if (Htmp >= 24 || Mtmp >= 60) - throw new IOException("Parse GeneralizedTime, -hhmm"); - - utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000; - } - break; - - case 'Z': - break; - - default: - throw new IOException("Parse GeneralizedTime, garbage offset"); + if (! (len == 1 || len == 5)) + throw new IOException ("Parse Generalized time, invalid offset"); + + switch (buffer.read ()) { + case '+': + { + int Htmp = 10 * Character.digit((char)buffer.read(), 10); + Htmp += Character.digit((char)buffer.read(), 10); + int Mtmp = 10 * Character.digit((char)buffer.read(), 10); + Mtmp += Character.digit((char)buffer.read(), 10); + + if (Htmp >=24 || Mtmp >= 60) + throw new IOException("Parse GeneralizedTime, +hhmm"); + + utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000; + } + break; + + case '-': + { + int Htmp = 10 * Character.digit((char)buffer.read(), 10); + Htmp += Character.digit((char)buffer.read(), 10); + int Mtmp = 10 * Character.digit((char)buffer.read(), 10); + Mtmp += Character.digit((char)buffer.read(), 10); + + if (Htmp >=24 || Mtmp >= 60) + throw new IOException("Parse GeneralizedTime, -hhmm"); + + utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000; + } + break; + + case 'Z': + break; + + default: + throw new IOException ("Parse GeneralizedTime, garbage offset"); } readDate.setTime(utcTime); return readDate; @@ -585,73 +601,69 @@ public class DerInputStream { */ // package private int getByte() throws IOException { - return (0x00ff & buffer.read()); + return (0x00ff & buffer.read()); } public int peekByte() throws IOException { - return buffer.peek(); + return buffer.peek (); } // package private int getLength() throws IOException { - return getLength(buffer); + return getLength (buffer); } /* * Get a length from the input stream, allowing for at most 32 bits of - * encoding to be used. (Not the same as getting a tagged integer!) + * encoding to be used. (Not the same as getting a tagged integer!) */ static int getLength(InputStream in) throws IOException { - int value, tmp; - - tmp = in.read(); - if ((tmp & 0x080) == 0x00) { // 1 byte datum? - value = tmp; - } else { // no, more ... - tmp &= 0x07f; - - /* - * NOTE: tmp == 0 indicates BER encoded data. tmp > 4 indicates more - * than 4Gb of data. - */ - if (tmp <= 0 || tmp > 4) - throw new IOException( - "DerInput.getLength(): lengthTag=" - + tmp - + ", " - + ((tmp == 0) ? "Indefinite length encoding not supported" - + " or incorrect DER encoding." - : "too big.")); - - for (value = 0; tmp > 0; tmp--) { - value <<= 8; - value += 0x0ff & in.read(); - } - } - return value; + int value, tmp; + + tmp = in.read (); + if ((tmp & 0x080) == 0x00) { // 1 byte datum? + value = tmp; + } else { // no, more ... + tmp &= 0x07f; + + /* + * NOTE: tmp == 0 indicates BER encoded data. + * tmp > 4 indicates more than 4Gb of data. + */ + if (tmp <= 0 || tmp > 4) + throw new IOException("DerInput.getLength(): lengthTag=" + + tmp + ", " + + ((tmp == 0) ? "Indefinite length encoding not supported" + + " or incorrect DER encoding." + : "too big.")); + + for (value = 0; tmp > 0; tmp --) { + value <<= 8; + value += 0x0ff & in.read (); + } + } + return value; } /** - * Mark the current position in the buffer, so that a later call to - * <code>reset</code> will return here. + * Mark the current position in the buffer, so that + * a later call to <code>reset</code> will return here. */ - public void mark(int value) { - buffer.mark(value); - } + public void mark (int value) { buffer.mark (value); } + /** - * Return to the position of the last <code>mark</code> call. A mark is - * implicitly set at the beginning of the stream when it is created. + * Return to the position of the last <code>mark</code> + * call. A mark is implicitly set at the beginning of + * the stream when it is created. */ - public void reset() { - buffer.reset(); - } + public void reset () { buffer.reset (); } + /** - * Returns the number of bytes available for reading. This is most useful - * for testing whether the stream is empty. + * Returns the number of bytes available for reading. + * This is most useful for testing whether the stream is + * empty. */ - public int available() { - return buffer.available(); - } + public int available () { return buffer.available (); } } |