DerInputStream.java revision 51b1b6997fd3f980076b8081f7f1165ccc2a4008
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 */ 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSequence(int startLen) throws IOException { 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Sequence) 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Sequence tag error"); 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readVector(startLen); 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a set of encoded entities. ASN.1 sets are unordered, 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * though DER may specify an order for some kinds of sets (such 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * as the attributes in an X.500 relative distinguished name) 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to facilitate binary comparisons of encoded values. 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param startLen guess about how large the set will be 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (used to initialize an auto-growing data structure) 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSet(int startLen) throws IOException { 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Set) 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Set tag error"); 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readVector(startLen); 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 * @param implicit if true tag is assumed implicit. 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return array of the values in the sequence 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue[] getSet(int startLen, boolean implicit) 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throws IOException { 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tag = (byte)buffer.read(); 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!implicit) { 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != DerValue.tag_Set) { 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Set tag error"); 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (readVector(startLen)); 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a "vector" of values ... set or sequence have the 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * same encoding, except for the initial tag, so both use 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * this same helper routine. 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski protected DerValue[] readVector(int startLen) throws IOException { 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerInputStream newstr; 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte lenByte = (byte)buffer.read(); 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int len = getLength((lenByte & 0xff), buffer); 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == -1) { 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // indefinite length encoding found 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int readLen = buffer.available(); 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int offset = 2; // for tag and length bytes 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] indefData = new byte[readLen + offset]; 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski indefData[0] = tag; 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski indefData[1] = lenByte; 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DataInputStream dis = new DataInputStream(buffer); 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dis.readFully(indefData, offset, readLen); 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski dis.close(); 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerIndefLenConverter derIn = new DerIndefLenConverter(); 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new DerInputBuffer(derIn.convert(indefData)); 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tag != buffer.read()) 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("Indefinite length encoding" + 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski " not supported"); 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski len = DerInputStream.getLength(buffer); 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (len == 0) 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // return empty array instead of null, which should be 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // used only for missing optionals 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerValue[0]; 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a temporary stream from which to read the data, 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * unless it's not really needed. 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.available() == len) 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newstr = this; 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski else 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newstr = subStream(len, true); 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pull values out of the stream. 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Vector<DerValue> vec = new Vector<DerValue>(startLen); 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue value; 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski do { 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = new DerValue(newstr.buffer); 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski vec.addElement(value); 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } while (newstr.available() > 0); 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (newstr.available() != 0) 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("extra data at end of vector"); 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Now stick them into the array we're returning. 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int i, max = vec.size(); 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski DerValue[] retval = new DerValue[max]; 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (i = 0; i < max; i++) 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski retval[i] = vec.elementAt(i); 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return retval; 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a single DER-encoded value from the input stream. 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It can often be useful to pull a value from the stream 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and defer parsing it. For example, you can pull a nested 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * sequence out with one call, and only examine its elements 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * later when you really need to. 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public DerValue getDerValue() throws IOException { 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new DerValue(buffer); 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a UTF8String DER value. 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getUTF8String() throws IOException { 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_UTF8String, "UTF-8", "UTF8"); 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a PrintableString DER value. 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getPrintableString() throws IOException { 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_PrintableString, "Printable", 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "ASCII"); 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a T61String DER value. 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getT61String() throws IOException { 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Works for common characters between T61 and ASCII. 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_T61String, "T61", "ISO-8859-1"); 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a IA5tring DER value. 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getIA5String() throws IOException { 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_IA5String, "IA5", "ASCII"); 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a BMPString DER value. 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getBMPString() throws IOException { 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_BMPString, "BMP", 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "UnicodeBigUnmarked"); 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Read a string that was encoded as a GeneralString DER value. 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String getGeneralString() throws IOException { 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return readString(DerValue.tag_GeneralString, "General", 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "ASCII"); 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Private helper routine to read an encoded string from the input 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * stream. 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringTag the tag for the type of string to read 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param stringName a name to display in error messages 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param enc the encoder to use to interpret the data. Should 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * correspond to the stringTag above. 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private String readString(byte stringTag, String stringName, 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String enc) throws IOException { 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != stringTag) 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input not a " + 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stringName + " string"); 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int length = getLength(buffer); 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski byte[] retval = new byte[length]; 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((length != 0) && (buffer.read(retval) != length)) 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("short read of DER " + 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski stringName + " string"); 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new String(retval, enc); 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a UTC encoded time value from the input stream. 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getUTCTime() throws IOException { 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_UtcTime) 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, UTCtime tag invalid "); 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getUTCTime(getLength(buffer)); 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a Generalized encoded time value from the input stream. 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Date getGeneralizedTime() throws IOException { 50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (buffer.read() != DerValue.tag_GeneralizedTime) 50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DER input, GeneralizedTime tag invalid "); 50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.getGeneralizedTime(getLength(buffer)); 50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a byte from the input stream. 51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // package private 51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getByte() throws IOException { 51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (0x00ff & buffer.read()); 51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int peekByte() throws IOException { 51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return buffer.peek(); 52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // package private 52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int getLength() throws IOException { 52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getLength(buffer); 52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a length from the input stream, allowing for at most 32 bits of 52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding to be used. (Not the same as getting a tagged integer!) 53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length or -1 if indefinite length found. 53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on parsing error or unsupported lengths. 53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static int getLength(InputStream in) throws IOException { 53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getLength(in.read(), in); 53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get a length from the input stream, allowing for at most 32 bits of 54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * encoding to be used. (Not the same as getting a tagged integer!) 54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the length or -1 if indefinite length found. 54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception IOException on parsing error or unsupported lengths. 54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static int getLength(int lenByte, InputStream in) throws IOException { 54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int value, tmp; 54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp = lenByte; 54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum 55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value = tmp; 55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { // long form or indefinite 55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski tmp &= 0x07f; 55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /* 55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * NOTE: tmp == 0 indicates indefinite length encoded data. 55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * tmp > 4 indicates more than 4Gb of data. 55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmp == 0) 55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (tmp < 0 || tmp > 4) 56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IOException("DerInputStream.getLength(): lengthTag=" 56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + tmp + ", " 56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski + ((tmp < 0) ? "incorrect DER encoding." : "too big.")); 56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (value = 0; tmp > 0; tmp --) { 56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value <<= 8; 56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski value += 0x0ff & in.read(); 56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return value; 57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Mark the current position in the buffer, so that 57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * a later call to <code>reset</code> will return here. 57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void mark(int value) { buffer.mark(value); } 57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return to the position of the last <code>mark</code> 58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * call. A mark is implicitly set at the beginning of 58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the stream when it is created. 58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void reset() { buffer.reset(); } 58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Returns the number of bytes available for reading. 59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This is most useful for testing whether the stream is 59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * empty. 59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int available() { return buffer.available(); } 59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 595