summaryrefslogtreecommitdiffstats
path: root/pki/base/util/src/netscape/security/util/DerInputBuffer.java
blob: 74ab9f705aead1b5c5d8ddf42bc221391f1d7f00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package netscape.security.util ;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;


/**
 * DER input buffer ... this is the main abstraction in the DER library
 * which actively works with the "untyped byte stream" abstraction.  It
 * does so with impunity, since it's not intended to be exposed to the
 * anyone who could violate the "typed value stream" DER model and hence
 * corrupt the input stream of DER values.
 *
 * @version 1.11
 * @author David Brownell
 */
class DerInputBuffer extends ByteArrayInputStream implements Cloneable {

    DerInputBuffer(byte[] buf) { super(buf); }

    DerInputBuffer(byte[] buf, int offset, int len) {
        super(buf, offset, len);
    }

    DerInputBuffer dup() {
	try {
	    DerInputBuffer retval = (DerInputBuffer) clone ();

	    retval.mark (Integer.MAX_VALUE);
	    return retval;
	} catch (CloneNotSupportedException e) {
	    throw new IllegalArgumentException (e.toString ());
	}
    }

    byte[] toByteArray() {
	int	len = available();
        if (len <= 0)
            return null;
	byte[]	retval = new byte[len];

	System.arraycopy(buf, pos, retval, 0, len);
	return retval;
    }

    int peek() throws IOException {
	if (pos >= count)
	    throw new IOException ("out of data");
	else
	    return buf [pos]; 
    }

    /**
     * Compares this DerInputBuffer for equality with the specified
     * object.
     */
    public boolean equals(Object other) {
	if (other instanceof DerInputBuffer)
	    return equals ((DerInputBuffer) other);
	else
	    return false;
    }

    boolean equals(DerInputBuffer other) {
	if (this == other)
	    return true;

	int max = this.available();
	if (other.available() != max)
	    return false;
	for (int i = 0; i < max; i++) {
	    if (this.buf [this.pos + i] != other.buf [other.pos + i]) {
		return false;
	    }
	}
	return true;
    }

    void truncate(int len) throws IOException {
	if (len > available ())
	    throw new IOException ("insufficient data");
	count = pos + len;
    }

    /**
     * Returns the unsigned integer which takes up the specified number
     * of bytes in this buffer.
     */
    BigInt getUnsigned(int len) throws IOException {
	if (len > available ())
	    throw new IOException ("short read, getInteger");

	/*
	 * A prepended zero is used to ensure that the integer is
	 * interpreted as unsigned even when the high order bit is
	 * zero.  We don't support signed BigInts.
	 *
	 * Fix this here ... BigInts aren't expected to have these,
	 * and stuff like signing (sigsize = f(modulus)) misbehaves.
	 */
	if (len > 1 && buf [pos] == 0) {
	    len--;
	    skip (1);
	}

	/*
	 * Consume the rest of the buffer, returning its value as
	 * an unsigned integer.
	 */
	byte[] bytes = new byte[len];

	System.arraycopy (buf, pos, bytes, 0, len);
	skip (len);
        return new BigInt (bytes);
    }

    /**
     * Returns the bit string which takes up the rest of this buffer.
     * This bit string must be byte-aligned.
	 */
    byte[] getBitString() {
	if (pos >= count || buf [pos] != 0)
	    return null;
	/*
	 * Just copy the data into an aligned, padded octet buffer,
	 * and consume the rest of the buffer.
	 */
	int	len = available ();
	byte[]	retval = new byte[len - 1];

	System.arraycopy (buf, pos + 1, retval, 0, len - 1);
	pos = count;
	return retval;
    }

	/**
	 * Returns the bit string which takes up the rest of this buffer.
	 * The bit string need not be byte-aligned.
	 */
     BitArray getUnalignedBitString() {
       if (pos >= count)
           return null;
       /*
        * Just copy the data into an aligned, padded octet buffer,
        * and consume the rest of the buffer.
        */
      int len = available();
       byte[] bits = new byte[len - 1];
       int length = bits.length*8 - buf[pos]; // number of valid bits

       System.arraycopy(buf, pos + 1, bits, 0, len - 1);
      
       BitArray bitArray = new BitArray(length, bits);
       pos = count;
      return bitArray;
     }

	/**
	 * Package-access method to optimize output operations
	 */
	void dump(OutputStream out, int length) throws IOException {
		if (count < mark + length)
		  throw new IOException ("short DER value (encode)");
		out.write(buf,mark,length);
	}
	
}