Methods Summary |
---|
public void | compactBuffer()Reallocates the buffer in order to make it
exactly the size of data it contains
if (offset != buffer.length) {
byte[] newBuffer = new byte[offset];
// restore buffer content
System.arraycopy(buffer, 0, newBuffer, 0, offset);
// set new buffer
buffer = newBuffer;
}
|
private final void | decodeValueCollection(ASN1ValueCollection collection)
int begOffset = offset;
int endOffset = begOffset + length;
ASN1Type type = collection.type;
if (isVerify) {
while (endOffset > offset) {
next();
type.decode(this);
}
} else {
int seqTagOffset = tagOffset; //store tag offset
ArrayList values = new ArrayList();
while (endOffset > offset) {
next();
values.add(type.decode(this));
}
content = values;
tagOffset = seqTagOffset; //retrieve tag offset
}
if (offset != endOffset) {
throw new ASN1Exception(Messages.getString("security.134", begOffset)); //$NON-NLS-1$
}
|
public java.lang.Object | get(java.lang.Object key)
if (pool == null) {
return null;
}
for (int i = 0; i < pool[0].length; i++) {
if (pool[0][i] == key) {
return pool[1][i];
}
}
return null;
|
public final byte[] | getBuffer()Returns internal buffer used for decoding
return buffer;
|
public final int | getContentOffset()
return contentOffset;
|
public byte[] | getEncoded()Returns encoded array.
MUST be invoked after decoding corresponding ASN.1 notation
byte[] encoded = new byte[offset - tagOffset];
System.arraycopy(buffer, tagOffset, encoded, 0, encoded.length);
return encoded;
|
public final int | getEndOffset()Returns end offset for the current encoded type
return offset + length;
|
public final int | getLength()Returns length of the current content for decoding
return length;
|
public static int | getLength(byte[] encoding)Returns the length of the encoding
int length = encoding[1] & 0xFF;
int numOctets = 0;
if ((length & 0x80) != 0) { // long form
numOctets = length & 0x7F;
// collect this value length
length = encoding[2] & 0xFF;
for (int i = 3; i < numOctets + 2; i++) {
length = (length << 8) + (encoding[i] & 0xFF);
}
}
// tag length long_form content
return 1 + 1 + numOctets + length;
|
public final int | getOffset()Returns the current offset
return offset;
|
public final int | getTagOffset()Returns start offset for the current encoded type
return tagOffset;
|
public int | next()Decodes next encoded type.
Initializes tag, length, tagOffset and contentOffset variables
tagOffset = offset;
// read tag
tag = read();
// read length
length = read();
if (length != 0x80) { // definite form
// long or short length form
if ((length & 0x80) != 0) { // long form
int numOctets = length & 0x7F;
if (numOctets > 5) {
throw new ASN1Exception(Messages.getString("security.113", //$NON-NLS-1$
tagOffset)); //FIXME message
}
// collect this value length
length = read();
for (int i = 1; i < numOctets; i++) {
int ch = read();
length = (length << 8) + ch;//read();
}
if (length > 0xFFFFFF) {
throw new ASN1Exception(Messages.getString("security.113", //$NON-NLS-1$
tagOffset)); //FIXME message
}
}
} else { //indefinite form
length = INDEFINIT_LENGTH;
}
contentOffset = offset;
return tag;
|
public void | put(java.lang.Object key, java.lang.Object entry)
if (pool == null) {
pool = new Object[2][10];
}
int i = 0;
for (; i < pool[0].length && pool[0][i] != null; i++) {
if (pool[0][i] == key) {
pool[1][i] = entry;
return;
}
}
if (i == pool[0].length) {
Object[][] newPool = new Object[pool[0].length * 2][2];
System.arraycopy(pool[0], 0, newPool[0], 0, pool[0].length);
System.arraycopy(pool[1], 0, newPool[1], 0, pool[0].length);
pool = newPool;
} else {
pool[0][i] = key;
pool[1][i] = entry;
}
|
protected int | read()Reads the next encoded byte from the encoded input stream.
if (offset == buffer.length) {
throw new ASN1Exception(Messages.getString("security.13B")); //$NON-NLS-1$
}
if (in == null) {
return buffer[offset++] & 0xFF;
} else {
int octet = in.read();
if (octet == -1) {
throw new ASN1Exception(Messages.getString("security.13B")); //$NON-NLS-1$
}
buffer[offset++] = (byte) octet;
return octet;
}
|
public void | readBitString()Decodes ASN.1 bitstring type
if (tag == ASN1Constants.TAG_BITSTRING) {
if (length == 0) {
throw new ASN1Exception(
Messages.getString("security.114", tagOffset)); //$NON-NLS-1$
}
readContent();
// content: check unused bits
if (buffer[contentOffset] > 7) {
throw new ASN1Exception(Messages.getString("security.115", //$NON-NLS-1$
contentOffset));
}
if (length == 1 && buffer[contentOffset] != 0) {
throw new ASN1Exception(Messages.getString("security.116", //$NON-NLS-1$
contentOffset));
}
} else if (tag == ASN1Constants.TAG_C_BITSTRING) {
throw new ASN1Exception(Messages.getString("security.117")); //$NON-NLS-1$
} else {
throw new ASN1Exception(
Messages.getString("security.118", tagOffset, //$NON-NLS-1$
Integer.toHexString(tag)));
}
|
public void | readBoolean()Decodes ASN.1 boolean type
if (tag != ASN1Constants.TAG_BOOLEAN) {
throw new ASN1Exception(Messages.getString("security.11C", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
// check encoded length
if (length != 1) {
throw new ASN1Exception(Messages.getString("security.11D", tagOffset));//$NON-NLS-1$
}
readContent();
|
public void | readContent()Reads the next encoded content from the encoded input stream.
The method MUST be used for reading a primitive encoded content.
if (offset + length > buffer.length) {
throw new ASN1Exception(Messages.getString("security.13B")); //$NON-NLS-1$
}
if (in == null) {
offset += length;
} else {
if (in.read(buffer, offset, length) != length) {
throw new ASN1Exception(Messages.getString("security.13C")); //$NON-NLS-1$
}
offset += length;
}
|
public void | readEnumerated()Decodes ASN.1 Enumerated type
if (tag != ASN1Constants.TAG_ENUM) {
throw new ASN1Exception(
Messages.getString("security.119", tagOffset, //$NON-NLS-1$
Integer.toHexString(tag)));
}
//
// all checks are the same as for ASN.1 integer type
//
// check encoded length
if (length == 0) {
throw new ASN1Exception(Messages.getString("security.11A", tagOffset));//$NON-NLS-1$
}
readContent();
// check encoded content
if (length > 1) {
int bits = buffer[contentOffset] & 0xFF;
if (buffer[contentOffset + 1] < 0) {
bits += 0x100;
}
if (bits == 0 || bits == 0x1FF) {
throw new ASN1Exception(Messages.getString("security.11B", contentOffset)); //$NON-NLS-1$
}
}
|
public void | readGeneralizedTime()Decodes ASN.1 GeneralizedTime type
if (tag == ASN1Constants.TAG_GENERALIZEDTIME) {
// FIXME: any other optimizations?
readContent();
// FIXME store string somewhere to allow a custom time type perform
// additional checks
// check syntax: the last char MUST be Z
if (buffer[offset - 1] != 'Z") {
// FIXME support only format that is acceptable for DER
throw new ASN1Exception(Messages.getString("security.11E")); //$NON-NLS-1$
}
// check syntax: MUST be YYYYMMDDHHMMSS[(./,)DDD]'Z'
if (length != 15 && (length < 17 || length > 19)) // invalid
// length
{
throw new ASN1Exception(Messages.getString("security.11F", //$NON-NLS-1$
contentOffset));
}
// check content: milliseconds
if (length > 16) {
byte char14 = buffer[contentOffset + 14];
if (char14 != '." && char14 != ',") {
throw new ASN1Exception(
Messages.getString("security.11F", //$NON-NLS-1$
contentOffset));
}
}
if (times == null) {
times = new int[7];
}
times[0] = strToInt(contentOffset, 4); // year
times[1] = strToInt(contentOffset + 4, 2); // month
times[2] = strToInt(contentOffset + 6, 2); // day
times[3] = strToInt(contentOffset + 8, 2); // hour
times[4] = strToInt(contentOffset + 10, 2); // minute
times[5] = strToInt(contentOffset + 12, 2); // second
if (length > 16) {
// FIXME optimize me
times[6] = strToInt(contentOffset + 15, length - 16);
if (length == 17) {
times[6] = times[6] * 100;
} else if (length == 18) {
times[6] = times[6] * 10;
}
}
// FIXME check all values for valid numbers!!!
} else if (tag == ASN1Constants.TAG_C_GENERALIZEDTIME) {
throw new ASN1Exception(Messages.getString("security.120")); //$NON-NLS-1$
} else {
throw new ASN1Exception(Messages.getString("security.121", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
|
public void | readInteger()Decodes ASN.1 Integer type
if (tag != ASN1Constants.TAG_INTEGER) {
throw new ASN1Exception(Messages.getString("security.127", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
// check encoded length
if (length < 1) {
throw new ASN1Exception(Messages.getString("security.128", //$NON-NLS-1$
tagOffset)); //$NON-NLS-1$
}
readContent();
// check encoded content
if (length > 1) {
byte firstByte = buffer[offset - length];
byte secondByte = (byte) (buffer[offset - length + 1] & 0x80);
if (firstByte == 0 && secondByte == 0 || firstByte == (byte) 0xFF
&& secondByte == (byte) 0x80) {
throw new ASN1Exception(Messages.getString("security.129", //$NON-NLS-1$
(offset - length)));
}
}
|
public void | readOID()Decodes ASN.1 ObjectIdentifier type
if (tag != ASN1Constants.TAG_OID) {
throw new ASN1Exception(Messages.getString("security.12C", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
// check encoded length
if (length < 1) {
throw new ASN1Exception(Messages.getString("security.12D", tagOffset)); //$NON-NLS-1$
}
readContent();
// check content: last encoded byte (8th bit MUST be zero)
if ((buffer[offset - 1] & 0x80) != 0) {
throw new ASN1Exception(Messages.getString("security.12E", (offset - 1))); //$NON-NLS-1$
}
oidElement = 1;
for (int i = 0; i < length; i++, ++oidElement) {
// According to ASN.1 BER spec:
// leading octet of subidentifier MUST not be 0x80
// This assertion is not verified
//
//if (buffer[contentOffset + i] == (byte)0x80) {
// throw new ASN1Exception(
// "Wrong content for ASN.1 object identifier at ["
// + contentOffset
// + "]. Subidentifier MUST be encoded in minimum number of octets");
//}
while ((buffer[contentOffset + i] & 0x80) == 0x80) {
i++;
}
}
|
public void | readOctetString()Decodes ASN.1 Octetstring type
if (tag == ASN1Constants.TAG_OCTETSTRING) {
readContent();
} else if (tag == ASN1Constants.TAG_C_OCTETSTRING) {
throw new ASN1Exception(Messages.getString("security.12A")); //$NON-NLS-1$
} else {
throw new ASN1Exception(
Messages.getString("security.12B", tagOffset, //$NON-NLS-1$
Integer.toHexString(tag)));
}
|
public void | readSequence(ASN1Sequence sequence)Decodes ASN.1 Sequence type
if (tag != ASN1Constants.TAG_C_SEQUENCE) {
throw new ASN1Exception(
Messages.getString("security.12F", tagOffset, //$NON-NLS-1$
Integer.toHexString(tag)));
}
int begOffset = offset;
int endOffset = begOffset + length;
ASN1Type[] type = sequence.type;
int i = 0;
if (isVerify) {
for (; (offset < endOffset) && (i < type.length); i++) {
next();
while (!type[i].checkTag(tag)) {
// check whether it is optional component or not
if (!sequence.OPTIONAL[i] || (i == type.length - 1)) {
throw new ASN1Exception(Messages.getString("security.130", //$NON-NLS-1$
tagOffset));
}
i++;
}
type[i].decode(this);
}
// check the rest of components
for (; i < type.length; i++) {
if (!sequence.OPTIONAL[i]) {
throw new ASN1Exception(Messages.getString("security.131", //$NON-NLS-1$
tagOffset));
}
}
} else {
int seqTagOffset = tagOffset; //store tag offset
Object[] values = new Object[type.length];
for (; (offset < endOffset) && (i < type.length); i++) {
next();
while (!type[i].checkTag(tag)) {
// check whether it is optional component or not
if (!sequence.OPTIONAL[i] || (i == type.length - 1)) {
throw new ASN1Exception(Messages.getString("security.132", //$NON-NLS-1$
tagOffset));
}
// sets default value
if (sequence.DEFAULT[i] != null) {
values[i] = sequence.DEFAULT[i];
}
i++;
}
values[i] = type[i].decode(this);
}
// check the rest of components
for (; i < type.length; i++) {
if (!sequence.OPTIONAL[i]) {
throw new ASN1Exception(Messages.getString("security.133", //$NON-NLS-1$
tagOffset));
}
if (sequence.DEFAULT[i] != null) {
values[i] = sequence.DEFAULT[i];
}
}
content = values;
tagOffset = seqTagOffset; //retrieve tag offset
}
if (offset != endOffset) {
throw new ASN1Exception(Messages.getString("security.134", begOffset)); //$NON-NLS-1$
}
|
public void | readSequenceOf(ASN1SequenceOf sequenceOf)Decodes ASN.1 SequenceOf type
if (tag != ASN1Constants.TAG_C_SEQUENCEOF) {
throw new ASN1Exception(Messages.getString("security.135", tagOffset, //$NON-NLS-1$
Integer.toHexString(tag)));
}
decodeValueCollection(sequenceOf);
|
public void | readSet(ASN1Set set)Decodes ASN.1 Set type
if (tag != ASN1Constants.TAG_C_SET) {
throw new ASN1Exception(Messages.getString("security.136", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
throw new ASN1Exception(Messages.getString("security.137")); //$NON-NLS-1$
|
public void | readSetOf(ASN1SetOf setOf)Decodes ASN.1 SetOf type
if (tag != ASN1Constants.TAG_C_SETOF) {
throw new ASN1Exception(Messages.getString("security.138", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
decodeValueCollection(setOf);
|
public void | readString(ASN1StringType type)Decodes ASN.1 String type
//FIXME check string content
if (tag == type.id) {
readContent();
} else if (tag == type.constrId) {
throw new ASN1Exception(Messages.getString("security.139")); //$NON-NLS-1$
} else {
throw new ASN1Exception(
Messages.getString("security.13A", tagOffset, //$NON-NLS-1$
Integer.toHexString(tag)));
}
|
public void | readUTCTime()Decodes ASN.1 UTCTime type
if (tag == ASN1Constants.TAG_UTCTIME) {
switch (length) {
case ASN1UTCTime.UTC_HM:
case ASN1UTCTime.UTC_HMS:
break;
case ASN1UTCTime.UTC_LOCAL_HM:
case ASN1UTCTime.UTC_LOCAL_HMS:
// FIXME only coordinated universal time formats are supported
throw new ASN1Exception(Messages.getString("security.122")); //$NON-NLS-1$
default:
throw new ASN1Exception(Messages.getString("security.123", //$NON-NLS-1$
tagOffset));
}
// FIXME: any other optimizations?
readContent();
// FIXME store string somewhere to allow a custom time type perform
// additional checks
// check syntax: the last char MUST be Z
if (buffer[offset - 1] != 'Z") {
throw new ASN1Exception("ASN.1 UTCTime wrongly encoded at [" //$NON-NLS-1$
+ contentOffset + ']");
}
if (times == null) {
times = new int[7];
}
times[0] = strToInt(contentOffset, 2); // year
if (times[0] > 49) {
times[0] += 1900;
} else {
times[0] += 2000;
}
times[1] = strToInt(contentOffset + 2, 2); // month
times[2] = strToInt(contentOffset + 4, 2); // day
times[3] = strToInt(contentOffset + 6, 2); // hour
times[4] = strToInt(contentOffset + 8, 2); // minute
if (length == ASN1UTCTime.UTC_HMS) {
times[5] = strToInt(contentOffset + 10, 2); // second
}
// FIXME check all time values for valid numbers!!!
} else if (tag == ASN1Constants.TAG_C_UTCTIME) {
throw new ASN1Exception(Messages.getString("security.124")); //$NON-NLS-1$
} else {
throw new ASN1Exception(Messages.getString("security.125", //$NON-NLS-1$
tagOffset, Integer.toHexString(tag)));
}
|
public final void | reset(byte[] encoded)Resets this stream to initial state.
buffer = encoded;
next();
|
public final void | setVerify()Sets verify mode.
isVerify = true;
|
private int | strToInt(int off, int count)
//FIXME works only with buffer
int c;
int result = 0;
for (int i = off, end = off + count; i < end; i++) {
c = buffer[i] - 48;
if (c < 0 || c > 9) {
throw new ASN1Exception(Messages.getString("security.126")); //$NON-NLS-1$
}
result = result * 10 + c;
}
return result;
|