DerInputStream.java revision 7a5b72d23c5b24e627ae09a7ab04f58cb1090d2b
151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.util; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InputStream; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException; 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.EOFException; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Vector; 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.math.BigInteger; 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.DataInputStream; 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A DER input stream, used for parsing ASN.1 DER-encoded data such as 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that found in X.509 certificates. DER is a subset of BER/1, which has 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the advantage that it allows only a single encoding of primitive data. 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (High level data such as dates still support many encodings.) That is, 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER). 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>Note that, like BER/1, DER streams are streams of explicitly 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * tagged data values. Accordingly, this programming interface does 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not expose any variant of the java.io.InputStream interface, since 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * that kind of input stream holds untagged data values and using that 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * I/O model could prevent correct parsing of the DER data. 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <P>At this time, this class supports only a subset of the types of DER 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * data encodings which are defined. That subset is sufficient for parsing 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * most X.509 certificates. 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author David Brownell 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Amit Kapoor 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Hemma Prafullchandra 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class DerInputStream { 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This version only supports fully buffered DER. This is easy to 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * work with, though if large objects are manipulated DER becomes 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * awkward to deal with. That's where BER is useful, since BER 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * handles streaming data relatively well. 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer buffer; 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** The DER tag of the value; one of the tag_ constants. */ 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte tag; 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a DER input stream from a data buffer. The buffer is not 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * copied, it is shared. Accordingly, the buffer should be treated 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as read-only. 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param data the buffer from which to create the string (CONSUMED) 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerInputStream(byte[] data) throws IOException { 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski init(data, 0, data.length); 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a DER input stream from part of a data buffer. 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The buffer is not copied, it is shared. Accordingly, the 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffer should be treated as read-only. 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param data the buffer from which to create the string (CONSUMED) 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param offset the first index of <em>data</em> which will 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be read as DER input in the new stream 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len how long a chunk of the buffer to use, 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * starting at "offset" 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerInputStream(byte[] data, int offset, int len) throws IOException { 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski init(data, offset, len); 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * private helper routine 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void init(byte[] data, int offset, int len) throws IOException { 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((offset+2 > data.length) || (offset+len > data.length)) { 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Encoding bytes too short"); 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // check for indefinite length encoding 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (DerIndefLenConverter.isIndefinite(data[offset+1])) { 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] inData = new byte[len]; 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.arraycopy(data, offset, inData, 0, len); 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerIndefLenConverter derIn = new DerIndefLenConverter(); 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new DerInputBuffer(derIn.convert(inData)); 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new DerInputBuffer(data, offset, len); 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.mark(Integer.MAX_VALUE); 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputStream(DerInputBuffer buf) { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = buf; 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.mark(Integer.MAX_VALUE); 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Creates a new DER input stream from part of this input stream. 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param len how long a chunk of the current input stream to use, 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * starting at the current position. 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param do_skip true if the existing data in the input stream should 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be skipped. If this value is false, the next data read 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * on this stream and the newly created stream will be the 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same. 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerInputStream subStream(int len, boolean do_skip) 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputBuffer newbuf = buffer.dup(); 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newbuf.truncate(len); 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (do_skip) { 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer.skip(len); 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerInputStream(newbuf); 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return what has been written to this DerInputStream 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as a byte array. Useful for debugging. 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] toByteArray() { 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.toByteArray(); 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * PRIMITIVES -- these are "universal" ASN.1 simple types. 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * INTEGER, ENUMERATED, BIT STRING, OCTET STRING, NULL 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF) 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * UTF8String, PrintableString, T61String, IA5String, UTCTime, 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * GeneralizedTime, BMPString. 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note: UniversalString not supported till encoder is available. 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get an integer from the input stream as an integer. 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER input stream. 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getInteger() throws IOException { 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Integer) { 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Integer tag error"); 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getInteger(getLength(buffer)); 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a integer from the input stream as a BigInteger object. 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER input stream. 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BigInteger getBigInteger() throws IOException { 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Integer) { 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Integer tag error"); 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getBigInteger(getLength(buffer), false); 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns an ASN.1 INTEGER value as a positive BigInteger. 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is just to deal with implementations that incorrectly encode 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * some values as negative. 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER value as a BigInteger. 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BigInteger getPositiveBigInteger() throws IOException { 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Integer) { 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Integer tag error"); 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getBigInteger(getLength(buffer), true); 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get an enumerated from the input stream. 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the integer held in this DER input stream. 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getEnumerated() throws IOException { 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Enumerated) { 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, Enumerated tag error"); 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getInteger(getLength(buffer)); 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a bit string from the input stream. Padded bits (if any) 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * will be stripped off before the bit string is returned. 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getBitString() throws IOException { 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_BitString) 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not an bit string"); 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getBitString(getLength(buffer)); 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a bit string from the input stream. The bit string need 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * not be byte-aligned. 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public BitArray getUnalignedBitString() throws IOException { 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_BitString) 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not a bit string"); 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer) - 1; 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * First byte = number of excess bits in the last octet of the 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * representation. 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int validBits = length*8 - buffer.read(); 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] repn = new byte[length]; 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((length != 0) && (buffer.read(repn) != length)) 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER bit string"); 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new BitArray(validBits, repn); 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns an ASN.1 OCTET STRING from the input stream. 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public byte[] getOctetString() throws IOException { 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_OctetString) 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not an octet string"); 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer); 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[length]; 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((length != 0) && (buffer.read(retval) != length)) 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER octet string"); 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the asked number of bytes from the input stream. 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void getBytes(byte[] val) throws IOException { 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((val.length != 0) && (buffer.read(val) != val.length)) { 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER octet string"); 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reads an encoded null value from the input stream. 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void getNull() throws IOException { 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_Null || buffer.read() != 0) 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("getNull, bad data"); 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Reads an X.200 style Object Identifier from the stream. 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public ObjectIdentifier getOID() throws IOException { 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ObjectIdentifier(this); 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a sequence of encoded entities. ASN.1 sequences are 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ordered, and they are often used, like a "struct" in C or C++, 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to group data values. They may have optional or context 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specific values. 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how long the sequence will be 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2947a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin public DerValue[] getSequence(int startLen, 2957a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin boolean originalEncodedFormRetained) throws IOException { 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Sequence) 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Sequence tag error"); 2997a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin return readVector(startLen, originalEncodedFormRetained); 3007a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin } 3017a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin 3027a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin /** 3037a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * Return a sequence of encoded entities. ASN.1 sequences are 3047a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * ordered, and they are often used, like a "struct" in C or C++, 3057a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * to group data values. They may have optional or context 3067a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * specific values. 3077a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * 3087a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * @param startLen guess about how long the sequence will be 3097a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * (used to initialize an auto-growing data structure) 3107a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin * @return array of the values in the sequence 3117a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin */ 3127a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin public DerValue[] getSequence(int startLen) throws IOException { 3137a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin return getSequence( 3147a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin startLen, 3157a5b72d23c5b24e627ae09a7ab04f58cb1090d2bAlex Klyubin false); // no need to retain original encoded form 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a set of encoded entities. ASN.1 sets are unordered, 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * though DER may specify an order for some kinds of sets (such 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as the attributes in an X.500 relative distinguished name) 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to facilitate binary comparisons of encoded values. 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how large the set will be 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSet(int startLen) throws IOException { 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Set) 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Set tag error"); 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readVector(startLen); 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a set of encoded entities. ASN.1 sets are unordered, 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * though DER may specify an order for some kinds of sets (such 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as the attributes in an X.500 relative distinguished name) 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to facilitate binary comparisons of encoded values. 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how large the set will be 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param implicit if true tag is assumed implicit. 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSet(int startLen, boolean implicit) 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 348ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return getSet( 349ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin startLen, 350ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin implicit, 351ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin false); // no need to retain original encoded form 352ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin } 353ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin 354ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin public DerValue[] getSet(int startLen, boolean implicit, 355ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin boolean originalEncodedFormRetained) 356ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin throws IOException { 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!implicit) { 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Set) { 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Set tag error"); 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 363ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return (readVector(startLen, originalEncodedFormRetained)); 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a "vector" of values ... set or sequence have the 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same encoding, except for the initial tag, so both use 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this same helper routine. 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected DerValue[] readVector(int startLen) throws IOException { 372ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin return readVector( 373ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin startLen, 374ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin false); // no need to retain original encoded form 375ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin } 376ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin 377ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin /* 378ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin * Read a "vector" of values ... set or sequence have the 379ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin * same encoding, except for the initial tag, so both use 380ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin * this same helper routine. 381ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin */ 382ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin protected DerValue[] readVector(int startLen, 383ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin boolean originalEncodedFormRetained) throws IOException { 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputStream newstr; 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte lenByte = (byte)buffer.read(); 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = getLength((lenByte & 0xff), buffer); 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == -1) { 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // indefinite length encoding found 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int readLen = buffer.available(); 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int offset = 2; // for tag and length bytes 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] indefData = new byte[readLen + offset]; 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski indefData[0] = tag; 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski indefData[1] = lenByte; 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DataInputStream dis = new DataInputStream(buffer); 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dis.readFully(indefData, offset, readLen); 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dis.close(); 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerIndefLenConverter derIn = new DerIndefLenConverter(); 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new DerInputBuffer(derIn.convert(indefData)); 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != buffer.read()) 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Indefinite length encoding" + 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " not supported"); 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len = DerInputStream.getLength(buffer); 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // return empty array instead of null, which should be 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // used only for missing optionals 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerValue[0]; 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a temporary stream from which to read the data, 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unless it's not really needed. 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.available() == len) 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newstr = this; 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newstr = subStream(len, true); 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pull values out of the stream. 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Vector<DerValue> vec = new Vector<DerValue>(startLen); 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue value; 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski do { 428ddde3e18b22acdaecb883794f5c8e21f0b87bf2fAlex Klyubin value = new DerValue(newstr.buffer, originalEncodedFormRetained); 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski vec.addElement(value); 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } while (newstr.available() > 0); 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (newstr.available() != 0) 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("extra data at end of vector"); 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Now stick them into the array we're returning. 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i, max = vec.size(); 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue[] retval = new DerValue[max]; 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (i = 0; i < max; i++) 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval[i] = vec.elementAt(i); 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a single DER-encoded value from the input stream. 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It can often be useful to pull a value from the stream 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and defer parsing it. For example, you can pull a nested 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sequence out with one call, and only examine its elements 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * later when you really need to. 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue getDerValue() throws IOException { 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerValue(buffer); 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a UTF8String DER value. 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getUTF8String() throws IOException { 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_UTF8String, "UTF-8", "UTF8"); 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a PrintableString DER value. 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getPrintableString() throws IOException { 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_PrintableString, "Printable", 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "ASCII"); 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a T61String DER value. 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getT61String() throws IOException { 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Works for common characters between T61 and ASCII. 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_T61String, "T61", "ISO-8859-1"); 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a IA5tring DER value. 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getIA5String() throws IOException { 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_IA5String, "IA5", "ASCII"); 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a BMPString DER value. 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getBMPString() throws IOException { 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_BMPString, "BMP", 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "UnicodeBigUnmarked"); 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a GeneralString DER value. 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getGeneralString() throws IOException { 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_GeneralString, "General", 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "ASCII"); 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine to read an encoded string from the input 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringTag the tag for the type of string to read 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringName a name to display in error messages 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param enc the encoder to use to interpret the data. Should 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * correspond to the stringTag above. 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String readString(byte stringTag, String stringName, 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String enc) throws IOException { 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != stringTag) 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not a " + 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stringName + " string"); 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer); 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[length]; 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((length != 0) && (buffer.read(retval) != length)) 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER " + 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stringName + " string"); 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(retval, enc); 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a UTC encoded time value from the input stream. 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getUTCTime() throws IOException { 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_UtcTime) 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, UTCtime tag invalid "); 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getUTCTime(getLength(buffer)); 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a Generalized encoded time value from the input stream. 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getGeneralizedTime() throws IOException { 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_GeneralizedTime) 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, GeneralizedTime tag invalid "); 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getGeneralizedTime(getLength(buffer)); 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a byte from the input stream. 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // package private 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getByte() throws IOException { 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (0x00ff & buffer.read()); 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int peekByte() throws IOException { 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.peek(); 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // package private 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getLength() throws IOException { 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getLength(buffer); 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a length from the input stream, allowing for at most 32 bits of 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding to be used. (Not the same as getting a tagged integer!) 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length or -1 if indefinite length found. 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on parsing error or unsupported lengths. 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static int getLength(InputStream in) throws IOException { 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getLength(in.read(), in); 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a length from the input stream, allowing for at most 32 bits of 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding to be used. (Not the same as getting a tagged integer!) 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length or -1 if indefinite length found. 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on parsing error or unsupported lengths. 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static int getLength(int lenByte, InputStream in) throws IOException { 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int value, tmp; 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp = lenByte; 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = tmp; 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { // long form or indefinite 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp &= 0x07f; 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NOTE: tmp == 0 indicates indefinite length encoded data. 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * tmp > 4 indicates more than 4Gb of data. 59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmp == 0) 59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmp < 0 || tmp > 4) 59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DerInputStream.getLength(): lengthTag=" 60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + tmp + ", " 60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + ((tmp < 0) ? "incorrect DER encoding." : "too big.")); 60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (value = 0; tmp > 0; tmp --) { 60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value <<= 8; 60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value += 0x0ff & in.read(); 60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return value; 60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Mark the current position in the buffer, so that 61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a later call to <code>reset</code> will return here. 61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void mark(int value) { buffer.mark(value); } 61651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 61851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 61951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return to the position of the last <code>mark</code> 62051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * call. A mark is implicitly set at the beginning of 62151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream when it is created. 62251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void reset() { buffer.reset(); } 62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 62551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the number of bytes available for reading. 62851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is most useful for testing whether the stream is 62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * empty. 63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int available() { return buffer.available(); } 63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 633