/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* https://opensso.dev.java.net/public/CDDLv1.0.html or
* opensso/legal/CDDLv1.0.txt
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: DerInputBuffer.java,v 1.2 2008/06/25 05:52:44 qcheng Exp $
*
*/
package com.iplanet.security.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import sun.security.util.BitArray;
/**
* 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.
*/
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);
}
}