jdk/src/share/classes/sun/security/util/DerInputStream.java
author weijun
Wed, 21 Oct 2009 08:17:35 +0800
changeset 4152 bc36a9f01ac6
parent 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
6870812: enhance security tools to use ECC algorithms Reviewed-by: vinnie, mullan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.security.util;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.InputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.io.IOException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.io.EOFException;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.util.Date;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.util.Vector;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
import java.math.BigInteger;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
import java.io.DataInputStream;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * A DER input stream, used for parsing ASN.1 DER-encoded data such as
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * that found in X.509 certificates.  DER is a subset of BER/1, which has
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * the advantage that it allows only a single encoding of primitive data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * (High level data such as dates still support many encodings.)  That is,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * <P>Note that, like BER/1, DER streams are streams of explicitly
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * tagged data values.  Accordingly, this programming interface does
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * not expose any variant of the java.io.InputStream interface, since
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * that kind of input stream holds untagged data values and using that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * I/O model could prevent correct parsing of the DER data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * <P>At this time, this class supports only a subset of the types of DER
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * data encodings which are defined.  That subset is sufficient for parsing
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * most X.509 certificates.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * @author David Brownell
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * @author Amit Kapoor
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * @author Hemma Prafullchandra
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
public class DerInputStream {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
     * This version only supports fully buffered DER.  This is easy to
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
     * work with, though if large objects are manipulated DER becomes
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
     * awkward to deal with.  That's where BER is useful, since BER
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
     * handles streaming data relatively well.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    DerInputBuffer      buffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    /** The DER tag of the value; one of the tag_ constants. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    public byte         tag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
     * Create a DER input stream from a data buffer.  The buffer is not
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
     * copied, it is shared.  Accordingly, the buffer should be treated
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
     * as read-only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
     * @param data the buffer from which to create the string (CONSUMED)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    public DerInputStream(byte[] data) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
        init(data, 0, data.length);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
     * Create a DER input stream from part of a data buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
     * The buffer is not copied, it is shared.  Accordingly, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
     * buffer should be treated as read-only.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
     * @param data the buffer from which to create the string (CONSUMED)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
     * @param offset the first index of <em>data</em> which will
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
     *          be read as DER input in the new stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
     * @param len how long a chunk of the buffer to use,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
     *          starting at "offset"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    public DerInputStream(byte[] data, int offset, int len) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
        init(data, offset, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * private helper routine
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    private void init(byte[] data, int offset, int len) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
        if ((offset+2 > data.length) || (offset+len > data.length)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
            throw new IOException("Encoding bytes too short");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        // check for indefinite length encoding
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
        if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
            byte[] inData = new byte[len];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
            System.arraycopy(data, offset, inData, 0, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
            DerIndefLenConverter derIn = new DerIndefLenConverter();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            buffer = new DerInputBuffer(derIn.convert(inData));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        } else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            buffer = new DerInputBuffer(data, offset, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
        buffer.mark(Integer.MAX_VALUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    DerInputStream(DerInputBuffer buf) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
        buffer = buf;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
        buffer.mark(Integer.MAX_VALUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * Creates a new DER input stream from part of this input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     * @param len how long a chunk of the current input stream to use,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     *          starting at the current position.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
     * @param do_skip true if the existing data in the input stream should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     *          be skipped.  If this value is false, the next data read
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     *          on this stream and the newly created stream will be the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     *          same.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    public DerInputStream subStream(int len, boolean do_skip)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
        DerInputBuffer  newbuf = buffer.dup();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        newbuf.truncate(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        if (do_skip) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            buffer.skip(len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        return new DerInputStream(newbuf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
     * Return what has been written to this DerInputStream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
     * as a byte array. Useful for debugging.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    public byte[] toByteArray() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
        return buffer.toByteArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
     * PRIMITIVES -- these are "universal" ASN.1 simple types.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
     *  INTEGER, ENUMERATED, BIT STRING, OCTET STRING, NULL
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
     *  OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
     *  UTF8String, PrintableString, T61String, IA5String, UTCTime,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
     *  GeneralizedTime, BMPString.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
     * Note: UniversalString not supported till encoder is available.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
     * Get an integer from the input stream as an integer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
     * @return the integer held in this DER input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    public int getInteger() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        if (buffer.read() != DerValue.tag_Integer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
            throw new IOException("DER input, Integer tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        return buffer.getInteger(getLength(buffer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     * Get a integer from the input stream as a BigInteger object.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
     * @return the integer held in this DER input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    public BigInteger getBigInteger() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
        if (buffer.read() != DerValue.tag_Integer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
            throw new IOException("DER input, Integer tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        return buffer.getBigInteger(getLength(buffer), false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
     * Returns an ASN.1 INTEGER value as a positive BigInteger.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
     * This is just to deal with implementations that incorrectly encode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
     * some values as negative.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
     * @return the integer held in this DER value as a BigInteger.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
    public BigInteger getPositiveBigInteger() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        if (buffer.read() != DerValue.tag_Integer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            throw new IOException("DER input, Integer tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        return buffer.getBigInteger(getLength(buffer), true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
     * Get an enumerated from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
     * @return the integer held in this DER input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    public int getEnumerated() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        if (buffer.read() != DerValue.tag_Enumerated) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
            throw new IOException("DER input, Enumerated tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        return buffer.getInteger(getLength(buffer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * Get a bit string from the input stream. Padded bits (if any)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     * will be stripped off before the bit string is returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
    public byte[] getBitString() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        if (buffer.read() != DerValue.tag_BitString)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            throw new IOException("DER input not an bit string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        return buffer.getBitString(getLength(buffer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
     * Get a bit string from the input stream.  The bit string need
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
     * not be byte-aligned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    public BitArray getUnalignedBitString() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        if (buffer.read() != DerValue.tag_BitString)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
            throw new IOException("DER input not a bit string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        int length = getLength(buffer) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
         * First byte = number of excess bits in the last octet of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
         * representation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        int validBits = length*8 - buffer.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
        byte[] repn = new byte[length];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        if ((length != 0) && (buffer.read(repn) != length))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            throw new IOException("short read of DER bit string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        return new BitArray(validBits, repn);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * Returns an ASN.1 OCTET STRING from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
    public byte[] getOctetString() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
        if (buffer.read() != DerValue.tag_OctetString)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
            throw new IOException("DER input not an octet string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        int length = getLength(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        byte[] retval = new byte[length];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        if ((length != 0) && (buffer.read(retval) != length))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            throw new IOException("short read of DER octet string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
        return retval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     * Returns the asked number of bytes from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
    public void getBytes(byte[] val) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        if ((val.length != 0) && (buffer.read(val) != val.length)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
            throw new IOException("short read of DER octet string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * Reads an encoded null value from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    public void getNull() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        if (buffer.read() != DerValue.tag_Null || buffer.read() != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
            throw new IOException("getNull, bad data");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
     * Reads an X.200 style Object Identifier from the stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    public ObjectIdentifier getOID() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        return new ObjectIdentifier(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     * Return a sequence of encoded entities.  ASN.1 sequences are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     * ordered, and they are often used, like a "struct" in C or C++,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
     * to group data values.  They may have optional or context
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
     * specific values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
     * @param startLen guess about how long the sequence will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
     *          (used to initialize an auto-growing data structure)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
     * @return array of the values in the sequence
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    public DerValue[] getSequence(int startLen) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        tag = (byte)buffer.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        if (tag != DerValue.tag_Sequence)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            throw new IOException("Sequence tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        return readVector(startLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
     * Return a set of encoded entities.  ASN.1 sets are unordered,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
     * though DER may specify an order for some kinds of sets (such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
     * as the attributes in an X.500 relative distinguished name)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
     * to facilitate binary comparisons of encoded values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
     * @param startLen guess about how large the set will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
     *          (used to initialize an auto-growing data structure)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
     * @return array of the values in the sequence
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    public DerValue[] getSet(int startLen) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
        tag = (byte)buffer.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
        if (tag != DerValue.tag_Set)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
            throw new IOException("Set tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        return readVector(startLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
     * Return a set of encoded entities.  ASN.1 sets are unordered,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
     * though DER may specify an order for some kinds of sets (such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
     * as the attributes in an X.500 relative distinguished name)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     * to facilitate binary comparisons of encoded values.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     * @param startLen guess about how large the set will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     *          (used to initialize an auto-growing data structure)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     * @param implicit if true tag is assumed implicit.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     * @return array of the values in the sequence
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    public DerValue[] getSet(int startLen, boolean implicit)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        tag = (byte)buffer.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        if (!implicit) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            if (tag != DerValue.tag_Set) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                throw new IOException("Set tag error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        return (readVector(startLen));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
     * Read a "vector" of values ... set or sequence have the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
     * same encoding, except for the initial tag, so both use
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     * this same helper routine.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    protected DerValue[] readVector(int startLen) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        DerInputStream  newstr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
        byte lenByte = (byte)buffer.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        int len = getLength((lenByte & 0xff), buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        if (len == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
           // indefinite length encoding found
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
           int readLen = buffer.available();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
           int offset = 2;     // for tag and length bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
           byte[] indefData = new byte[readLen + offset];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
           indefData[0] = tag;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
           indefData[1] = lenByte;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
           DataInputStream dis = new DataInputStream(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
           dis.readFully(indefData, offset, readLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
           dis.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
           DerIndefLenConverter derIn = new DerIndefLenConverter();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
           buffer = new DerInputBuffer(derIn.convert(indefData));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
           if (tag != buffer.read())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
                throw new IOException("Indefinite length encoding" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                        " not supported");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
           len = DerInputStream.getLength(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        if (len == 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
            // return empty array instead of null, which should be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            // used only for missing optionals
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            return new DerValue[0];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
         * Create a temporary stream from which to read the data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
         * unless it's not really needed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        if (buffer.available() == len)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            newstr = this;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            newstr = subStream(len, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
         * Pull values out of the stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        Vector<DerValue> vec = new Vector<DerValue>(startLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
        DerValue value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
            value = new DerValue(newstr.buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
            vec.addElement(value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        } while (newstr.available() > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        if (newstr.available() != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
            throw new IOException("extra data at end of vector");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
         * Now stick them into the array we're returning.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        int             i, max = vec.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        DerValue[]      retval = new DerValue[max];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        for (i = 0; i < max; i++)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            retval[i] = vec.elementAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
        return retval;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
     * Get a single DER-encoded value from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
     * It can often be useful to pull a value from the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
     * and defer parsing it.  For example, you can pull a nested
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
     * sequence out with one call, and only examine its elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
     * later when you really need to.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    public DerValue getDerValue() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        return new DerValue(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
     * Read a string that was encoded as a UTF8String DER value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    public String getUTF8String() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        return readString(DerValue.tag_UTF8String, "UTF-8", "UTF8");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     * Read a string that was encoded as a PrintableString DER value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    public String getPrintableString() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
        return readString(DerValue.tag_PrintableString, "Printable",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
                          "ASCII");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
     * Read a string that was encoded as a T61String DER value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
    public String getT61String() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
         * Works for common characters between T61 and ASCII.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        return readString(DerValue.tag_T61String, "T61", "ISO-8859-1");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
     * Read a string that was encoded as a IA5tring DER value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
    public String getIA5String() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
        return readString(DerValue.tag_IA5String, "IA5", "ASCII");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
     * Read a string that was encoded as a BMPString DER value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
    public String getBMPString() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        return readString(DerValue.tag_BMPString, "BMP",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                          "UnicodeBigUnmarked");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
     * Read a string that was encoded as a GeneralString DER value.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
    public String getGeneralString() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
        return readString(DerValue.tag_GeneralString, "General",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                          "ASCII");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     * Private helper routine to read an encoded string from the input
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     * @param stringTag the tag for the type of string to read
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     * @param stringName a name to display in error messages
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     * @param enc the encoder to use to interpret the data. Should
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
     * correspond to the stringTag above.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
    private String readString(byte stringTag, String stringName,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                              String enc) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        if (buffer.read() != stringTag)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
            throw new IOException("DER input not a " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
                                  stringName + " string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
        int length = getLength(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        byte[] retval = new byte[length];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        if ((length != 0) && (buffer.read(retval) != length))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
            throw new IOException("short read of DER " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                                  stringName + " string");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        return new String(retval, enc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
     * Get a UTC encoded time value from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
    public Date getUTCTime() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        if (buffer.read() != DerValue.tag_UtcTime)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
            throw new IOException("DER input, UTCtime tag invalid ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
        return buffer.getUTCTime(getLength(buffer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
     * Get a Generalized encoded time value from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
    public Date getGeneralizedTime() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        if (buffer.read() != DerValue.tag_GeneralizedTime)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
            throw new IOException("DER input, GeneralizedTime tag invalid ");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        return buffer.getGeneralizedTime(getLength(buffer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
     * Get a byte from the input stream.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
    // package private
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
    int getByte() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
        return (0x00ff & buffer.read());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
    public int peekByte() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
        return buffer.peek();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    // package private
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
    int getLength() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        return getLength(buffer);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
     * Get a length from the input stream, allowing for at most 32 bits of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
     * encoding to be used.  (Not the same as getting a tagged integer!)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
     * @return the length or -1 if indefinite length found.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     * @exception IOException on parsing error or unsupported lengths.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    static int getLength(InputStream in) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        return getLength(in.read(), in);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
     * Get a length from the input stream, allowing for at most 32 bits of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
     * encoding to be used.  (Not the same as getting a tagged integer!)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
     * @return the length or -1 if indefinite length found.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
     * @exception IOException on parsing error or unsupported lengths.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
    static int getLength(int lenByte, InputStream in) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        int value, tmp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        tmp = lenByte;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
            value = tmp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        } else {                     // long form or indefinite
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            tmp &= 0x07f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
             * NOTE:  tmp == 0 indicates indefinite length encoded data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
             * tmp > 4 indicates more than 4Gb of data.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
            if (tmp == 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
                return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
            if (tmp < 0 || tmp > 4)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
                throw new IOException("DerInputStream.getLength(): lengthTag="
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
                    + tmp + ", "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
                    + ((tmp < 0) ? "incorrect DER encoding." : "too big."));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            for (value = 0; tmp > 0; tmp --) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                value <<= 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                value += 0x0ff & in.read();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
     * Mark the current position in the buffer, so that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     * a later call to <code>reset</code> will return here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    public void mark(int value) { buffer.mark(value); }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
     * Return to the position of the last <code>mark</code>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
     * call.  A mark is implicitly set at the beginning of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
     * the stream when it is created.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    public void reset() { buffer.reset(); }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
     * Returns the number of bytes available for reading.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
     * This is most useful for testing whether the stream is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
     * empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    public int available() { return buffer.available(); }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
}