FileDocCategorySizeDatePackage
TLV.javaAPI DocphoneME MR2 API (J2ME)24638Wed May 02 18:00:38 BST 2007com.sun.satsa.util

TLV

public class TLV extends Object
Used to represent each Type, Length, Value structure in a DER buffer.

Fields Summary
public static final int
CONTEXT
ASN context specific flag used in types (0x80).
public static final int
CONSTRUCTED
ASN constructed flag used in types (0x20).
public static final int
EXPLICIT
ASN constructed flag used in types (0x20).
public static final int
ANY_STRING_TYPE
ANY_STRING type used as a place holder. [UNIVERSAL 0]
public static final int
BOOLEAN_TYPE
ASN BOOLEAN type used in certificate parsing. [UNIVERSAL 1]
public static final int
INTEGER_TYPE
ASN INTEGER type used in certificate parsing. [UNIVERSAL 2]
public static final int
BITSTRING_TYPE
ASN BIT STRING type used in certificate parsing. [UNIVERSAL 3]
public static final int
OCTETSTR_TYPE
ASN OCTET STRING type used in certificate parsing. [UNIVERSAL 4]
public static final int
NULL_TYPE
ASN NULL type used in certificate parsing. [UNIVERSAL 5]
public static final int
OID_TYPE
ASN OBJECT ID type used in certificate parsing. [UNIVERSAL 6]
public static final int
ENUMERATED_TYPE
ASN ENUMERATED type. [UNIVERSAL 10]
public static final int
UTF8STR_TYPE
ASN UTF8String type used in certificate parsing. [UNIVERSAL 12]
public static final int
SEQUENCE_TYPE
ASN SEQUENCE type used in certificate parsing. [UNIVERSAL CONSTRUCTED 16]
public static final int
SET_TYPE
ASN SET type used in certificate parsing. [UNIVERSAL CONSTRUCTED 17]
public static final int
PRINTSTR_TYPE
ASN PrintableString type used in certificate parsing. [UNIVERSAL 19]
public static final int
TELETEXSTR_TYPE
ASN TELETEX STRING type used in certificate parsing. [UNIVERSAL 20]
public static final int
IA5STR_TYPE
ASN IA5 STRING type used in certificate parsing. [UNIVERSAL 22]
public static final int
UCT_TIME_TYPE
ASN UCT time type used in certificate parsing. [UNIVERSAL 23]
public static final int
GEN_TIME_TYPE
ASN Generalized time type used in certificate parsing. [UNIVERSAL 24]
public static final int
UNIVSTR_TYPE
ASN UniversalString type used in certificate parsing. [UNIVERSAL 28].
public static final int
BMPSTR_TYPE
ASN BIT STRING type used in certificate parsing. [UNIVERSAL 30]
public static final int
VERSION_TYPE
Context specific explicit type for certificate version. [CONTEXT EXPLICIT 0]
public static final int
EXTENSIONS_TYPE
Context specific explicit type for certificate extensions. [CONTEXT EXPLICIT 3]
public int
type
Raw DER type.
public int
length
Number of bytes that make up the value.
public int
valueOffset
Offset of the value.
public TLV
child
Non-null for constructed types, the first child TLV.
public TLV
next
The next TLV in the parent sequence.
public byte[]
data
Buffer that contains the DER encoded TLV.
Constructors Summary
public TLV(byte[] buffer, int offset)
Constructs a TLV structure, recursing down for constructed types.

param
buffer DER buffer
param
offset where to start parsing
exception
IndexOutOfBoundsException if the DER is corrupt
throws
TLVException in case of parsing error


                                          
           

        try {
            data = buffer;
            type = buffer[offset++] & 0xff;

            if ((type & 0x1f) == 0x1f) {
                // multi byte type, 7 bits per byte,
                // only last byte bit 8 as zero
                throw new TLVException("Invalid tag");
            }

            int size = buffer[offset++] & 0xff;
            boolean indefinite = (size == 128);
            if (indefinite) {
                if ((type & 0x20) == 0) {
                    throw new TLVException("Invalid length");
                }
            } else
                if (size >= 128) {
                    int sizeLen = size - 128;

                    // NOTE: for now, all sizes must fit int 3 bytes
                    if (sizeLen > 3) {
                        throw new TLVException("TLV is too large");
                    }

                    size = 0;
                    while (sizeLen > 0) {
                        size = (size << 8) + (buffer[offset++] & 0xff);
                        sizeLen--;
                    }
                }

            length = size;
            valueOffset = offset;

            if ((type & 0x20) == 0 || length == 0) {
                return;
            }

            // constructed and not empty

            TLV prev = null;
            while (true) {
                if (indefinite && data[offset] == 0 &&
                        data[offset + 1] == 0) {
                    length = offset - valueOffset;
                    return;
                }

                TLV temp = new TLV(buffer, offset);
                offset = (data[offset + 1] == (byte) 0x80 ? 2 : 0) +
                        temp.valueOffset + temp.length;

                if (prev == null) {
                    child = temp;
                } else {
                    prev.next = temp;
                }
                prev = temp;

                if (indefinite) {
                    continue;
                }
                if (offset == valueOffset + length) {
                    break;
                }
                if (offset > valueOffset + length) {
                    throw new TLVException("incorrect structure");
                }
            }
        } catch (NullPointerException npe) {
            throw new TLVException("parser error");
        } catch (IndexOutOfBoundsException iobe) {
            throw new TLVException("parser error");
        } catch (NumberFormatException nfe) {
            throw new TLVException("parser error");
        }
    
public TLV(int tag)
Constructs a TLV structure.

param
tag tag of new TLV

        type = tag;
    
public TLV(int tag, byte[] bytes)
Constructs a TLV structure.

param
tag tag of the new TLV
param
bytes value of the new TLV

        type = tag;
        valueOffset = 0;
        length = bytes.length;
        data = bytes;
    
public TLV(int tag, byte[] bytes, int offset)
Constructs a TLV structure.

param
tag tag of the new TLV
param
bytes data for new TLV
param
offset of data

        type = tag;
        valueOffset = offset;
        length = bytes.length - offset;
        data = bytes;
    
Methods Summary
public booleancheckFlag(int index)
Returns the value of flag stored in bitsring value.

param
index flag index
return
true if the flag is set
throws
TLVException if TLV type is invalid


        if (type != BITSTRING_TYPE) {
            throw new TLVException("invalid type - checkFlag");
        }

        int i = (length - 1) * 8  - data[valueOffset];
        if (index >= i) {
            return false;
        }

        return ((data[valueOffset + 1 + (index/8)] << index % 8) & 0x80)
                != 0;
    
public com.sun.satsa.util.TLVcopy()
Creates a copy of this TLV. The value of field next of the new TLV is null.

return
a copy of this TLV

        try {
            return new TLV(getDERData(), 0);
        } catch (TLVException e) {}
        return null;
    
public static com.sun.satsa.util.TLVcreateIA5String(java.lang.String s)
Creates TLV object of type IA5 string.

param
s string value
throws
TLVException if illegal string has been provided
return
new object

        int len = (s == null ? 0 : s.length());
        
        if (len == 0) {
            return new TLV(TLV.IA5STR_TYPE, new byte[] {});
        }
        byte[] b = new byte[len];
        
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (c >= 0 && c <= 127) {
                b[i] = (byte)c;
            } else {
                throw new TLVException("Illegal string for IA5:" + s);
            }
        }
        return new TLV(TLV.IA5STR_TYPE, b);
    
public static com.sun.satsa.util.TLVcreateInteger(long value)
Creates TLV object of type integer.

param
value value
return
new object


        int check = (value < 0) ? -1 : 0;

        int i = 1;
        while (i < 8) {
            if (value >> (i * 8) == check) {
                byte v = (byte) (value >> ((i - 1) * 8));
                if (value < 0 ? v > 0 : v < 0) {
                    i++;
                }
                break;
            }
            i++;
        }

        byte[] data = new byte[i];
        while (i > 0) {
            i--;
            data[i] = (byte) value;
            value = value >> 8;
        }
        return new TLV(TLV.INTEGER_TYPE, data);
    
public static com.sun.satsa.util.TLVcreateInteger(byte[] data)
Creates TLV object of type integer.

param
data value
return
new object

        return new TLV(INTEGER_TYPE, data);
    
public static com.sun.satsa.util.TLVcreateOID(java.lang.String oid)
Creates TLV object of type OID.

param
oid OID in text form
return
new object

        return new TLV(TLV.OID_TYPE, Utils.StringToOID(oid));
    
public static com.sun.satsa.util.TLVcreateOctetString(byte[] data)
Creates TLV object of type octet string.

param
data value
return
new object

        return new TLV(OCTETSTR_TYPE, data);
    
public static com.sun.satsa.util.TLVcreateSequence()
Creates TLV object of type sequence.

return
new object

        return new TLV(SEQUENCE_TYPE);
    
public static com.sun.satsa.util.TLVcreateUTCTime(java.util.Calendar time)
Creates UTCTime TLV structure for given date.

param
time date
return
TLV value representing this date

        byte[] data = new byte[13];
        putDigits(data, 0, time.get(Calendar.YEAR));
        putDigits(data, 2, time.get(Calendar.MONTH) + 1);
        putDigits(data, 4, time.get(Calendar.DAY_OF_MONTH));
        putDigits(data, 6, time.get(Calendar.HOUR_OF_DAY));
        putDigits(data, 8, time.get(Calendar.MINUTE));
        putDigits(data, 10, time.get(Calendar.SECOND));
        data[12] = 0x5a;
        return new TLV(UCT_TIME_TYPE, data);
    
public static com.sun.satsa.util.TLVcreateUTF8String(java.lang.String s)
Creates TLV object of type UTF8 string.

param
s string value
return
new object

        return new TLV(TLV.UTF8STR_TYPE, Utils.stringToBytes(s));
    
public byte[]getDERData()
Returns DER encoded TLV.

return
DER encoded TLV


        byte[] x = new byte[getDERSize()];
        getDERData_(x, 0);
        return x;
    
public intgetDERData(byte[] buffer, int offset)
Returns DER encoded TLV.

param
buffer target buffer
param
offset offset in the buffer
return
value length


        getDERSize();
        return getDERData_(buffer, offset);
    
private intgetDERData_(byte[] buffer, int offset)
Returns DER encoded TLV.

param
buffer target buffer
param
offset offset in the buffer
return
value length


        int initialOffset = offset;
        offset = putHeader(buffer, offset);

        if (data == null) {
            TLV c = child;
            while (c != null) {
                offset += c.getDERData_(buffer, offset);
                c = c.next;
            }
        } else {
            System.arraycopy(data, valueOffset, buffer, offset, length);
            offset += length;
        }
        return (offset - initialOffset);
    
public intgetDERSize()
Returns the size of DER encoded TLV.

return
the size of DER encoded TLV


        if (data == null) {
            length = 0;
            TLV c = child;
            while (c != null) {
                length += c.getDERSize();
                c = c.next;
            }
        }
        return length + getTLSize();
    
public intgetEnumerated()
Returns the value of enumerated type.

return
the value
throws
TLVException if TLV type is invalid


        if (type != ENUMERATED_TYPE) {
            throw new TLVException("invalid type - getEnumerated");
        }
        return getIntegerValue();
    
public intgetId()
Returns octet string value as integer.

return
integer value
throws
TLVException if this TLV is not octet string


        if (type != OCTETSTR_TYPE) {
            throw new TLVException("invalid type - getId");
        }
        return getIntegerValue();
    
public intgetInteger()
Returns integer value.

return
integer value
throws
TLVException if this TLV doesn't represent integer value


        if (type != INTEGER_TYPE && ((type & 0xf0) != 0x80)) {
            throw new TLVException("invalid type - getInteger");
        }
        return getIntegerValue();
    
private intgetIntegerValue()
Returns the value of TLV as integer.

return
the integer value
throws
TLVException if the value is too long


        int l = data[valueOffset] < 0 ? -1 : 0;
        int check = l << 24;

        for (int i = 0; i < length; i++) {
            if ((l & 0xff000000) != check) {
                throw new TLVException("Integer value is too big");
            }
            l = (l << 8) | (data[valueOffset + i] & 0xff);
        }
        return l;
    
private intgetTLSize()
Returns the size of tag and length encoding.

return
the size of tag and length encoding


        int TLSize = 2;
        if (length >= 128) {
            int i = length;
            while (i != 0) {
                TLSize++;
                i = i >> 8;
            }
        }
        return TLSize;
    
public java.util.CalendargetTime()
Returns time represented by this TLV.

return
time value
throws
TLVException if TLV type is invalid


        if (type != GEN_TIME_TYPE &&
            type != UCT_TIME_TYPE) {
            throw new TLVException("invalid type - getType");
        }

        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

        int offset;
        int year;
        if (type == GEN_TIME_TYPE) {
            year = getTimeComponent(0, 4);
            offset = 4;
        } else {
            year = getTimeComponent(0, 2);
            year += (year >= 50) ? 1900 : 2000;
            offset = 2;
        }
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, getTimeComponent(offset, 2) - 1);
        offset += 2;
        c.set(Calendar.DAY_OF_MONTH, getTimeComponent(offset, 2));
        offset += 2;
        c.set(Calendar.HOUR_OF_DAY, getTimeComponent(offset, 2));
        offset += 2;
        c.set(Calendar.MINUTE, getTimeComponent(offset, 2));
        offset += 2;
        c.set(Calendar.SECOND, getTimeComponent(offset, 2));

        return c;
    
private intgetTimeComponent(int offset, int len)
Returns decoded BCD value.

param
offset value offset
param
len value length
return
decoded value


        int value = 0;
        while (len-- > 0) {
            value = value * 10 + (data[valueOffset + offset++] - 0x30);
        }
        return value;
    
public java.lang.StringgetUTF8()
Returns string represented by this UTF8 string.

return
string value
throws
TLVException if TLV type is invalid


        if (type != UTF8STR_TYPE && ((type & 0xf0) != 0x80)) {
            throw new TLVException("invalid type - getUTF8");
        }

        try {
            return new String(data, valueOffset, length, Utils.utf8);
        } catch (UnsupportedEncodingException e) {
            throw new TLVException("invalid encoding");
        }
    
public byte[]getValue()
Returns the value field of this TLV.

return
the value field of this TLV


        if (data == null) {
            getDERSize();
        }
        byte[] x = new byte[length];
        getValue_(x, 0);
        return x;
    
private intgetValue_(byte[] buffer, int offset)
Places the value field of this TLV into the buffer.

param
buffer target buffer
param
offset index of the first byte
return
value length


        if (data == null) {
            TLV c = child;
            while (c != null) {
                offset += c.getDERData(buffer, offset);
                c = c.next;
            }
        } else {
            System.arraycopy(data, valueOffset, buffer, offset, length);
        }
        return length;
    
public booleanisString()
Returns true if this value represents string.

return
true if this value represents string

        return (type == TELETEXSTR_TYPE ||
                type == PRINTSTR_TYPE ||
                type == UNIVSTR_TYPE ||
                type == UTF8STR_TYPE ||
                type == BMPSTR_TYPE);
    
public booleanmatch(com.sun.satsa.util.TLV t)
Compares this object with other TLV object.

param
t TLV object
return
true if both objects have the same type and contain the same data


        if (type != t.type) {
            return false;
        }
        if (t.data == null) {
            t = t.copy();
        }
        if (data == null) {
            t.match(this);
        }
        return Utils.byteMatch(data, valueOffset, length,
                               t.data, t.valueOffset, t.length);
    
private static voidputDigits(byte[] data, int offset, int value)
Places two ASCII encoded decimal digits into byte array.

param
data byte aray
param
offset the index of the first byte
param
value the value to be placed into the buffer


        value = value % 100;
        data[offset++] = (byte) (0x30 | (value / 10));
        data[offset++] = (byte) (0x30 | (value % 10));
    
private intputHeader(byte[] x, int i)
Places tag and length values into the buffer.

param
x byte buffer
param
i offset
return
value offset in the buffer


        x[i++] = (byte) type;

        if (length < 128) {
            x[i++] = (byte) length;
        } else
        if (length < 256) {
            x[i++] = (byte) 0x81;
            x[i++] = (byte) length;
        } else {
            x[i++] = (byte) 0x82;
            x[i++] = (byte) (length >> 8);
            x[i++] = (byte) length;
        }
        return i;
    
public com.sun.satsa.util.TLVsetChild(com.sun.satsa.util.TLV child)
Sets child element for this TLV object.

param
child the child object
return
the passed value to allow chaining

        this.child = child;
        return child;
    
public com.sun.satsa.util.TLVsetNext(com.sun.satsa.util.TLV next)
Sets next element for this TLV object.

param
next the next object
return
the passed value to allow chaining

        this.next = next;
        return next;
    
public com.sun.satsa.util.TLVsetTag(int tag)
Sets the (implicit) tag value for this object.

param
tag tag value
return
this value to allow call chaining

        this.type = tag;
        return this;
    
public com.sun.satsa.util.TLVskipOptional(int type)
Skips optional element of DER structure with given tag.

param
type tag of optional value
return
this object if type doesn't match or the next one if it does


        if (this.type == type) {
            return next;
        }
        return this;
    
public booleanvalueEquals(byte[] data)
Compares the value of this TLV with given value.

param
data the value to be compared
return
true if TLV object contains the same value

        return Utils.byteMatch(this.data, valueOffset, length,
                               data, 0, data.length);