FileDocCategorySizeDatePackage
TLV.javaAPI DocphoneME MR2 API (J2ME)17429Wed May 02 18:00:40 BST 2007dummyCA

TLV

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

Fields Summary
static final int
CONTEXT
ASN context specific flag used in types (0x80).
static final int
CONSTRUCTED
ASN constructed flag used in types (0x20).
static final int
EXPLICIT
ASN constructed flag used in types (0x20).
static final int
ANY_STRING_TYPE
ANY_STRING type used as a place holder. [UNIVERSAL 0]
static final int
BOOLEAN_TYPE
ASN BOOLEAN type used in certificate parsing. [UNIVERSAL 1]
static final int
INTEGER_TYPE
ASN INTEGER type used in certificate parsing. [UNIVERSAL 2]
static final int
BITSTRING_TYPE
ASN BIT STRING type used in certificate parsing. [UNIVERSAL 3]
static final int
OCTETSTR_TYPE
ASN OCTET STRING type used in certificate parsing. [UNIVERSAL 4]
static final int
NULL_TYPE
ASN NULL type used in certificate parsing. [UNIVERSAL 5]
static final int
OID_TYPE
ASN OBJECT ID type used in certificate parsing. [UNIVERSAL 6]
static final int
UTF8STR_TYPE
ASN UTF8String type used in certificate parsing. [UNIVERSAL 12]
static final int
SEQUENCE_TYPE
ASN SEQUENCE type used in certificate parsing. [UNIVERSAL CONSTRUCTED 16]
static final int
SET_TYPE
ASN SET type used in certificate parsing. [UNIVERSAL CONSTRUCTED 17]
static final int
PRINTSTR_TYPE
ASN PrintableString type used in certificate parsing. [UNIVERSAL 19]
static final int
TELETEXSTR_TYPE
ASN TELETEX STRING type used in certificate parsing. [UNIVERSAL 20]
static final int
IA5STR_TYPE
ASN IA5 STRING type used in certificate parsing. [UNIVERSAL 22]
static final int
UCT_TIME_TYPE
ASN UCT time type used in certificate parsing [UNIVERSAL 23]
static final int
GEN_TIME_TYPE
ASN Generalized time type used in certificate parsing. [UNIVERSAL 24]
static final int
UNIVSTR_TYPE
ASN UniversalString type used in certificate parsing. [UNIVERSAL 28].
static final int
BMPSTR_TYPE
ASN BIT STRING type used in certificate parsing. [UNIVERSAL 30]
static final int
VERSION_TYPE
Context specific explicit type for certificate version. [CONTEXT EXPLICIT 0]
static final int
EXTENSIONS_TYPE
Context specific explicit type for certificate extensions. [CONTEXT EXPLICIT 3]
private static final int
MAX_OID_SIZE
OID must fit into byte array of this size.
static char[]
hc
Hexadecimal digits.
int
type
Raw DER type.
int
length
Number of bytes that make up the value.
int
valueOffset
Offset of the value.
TLV
child
Non-null for constructed types, the first child TLV.
TLV
next
The next TLV in the parent sequence.
int
TLSize
Size of tag and length in DER encoding.
byte[]
data
Buffer that contains the DER encoded TLV.
Constructors Summary
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
IndexOutOfBoundException if the DER is corrupt


        boolean constructed;
        int size;

        int start = offset;
        data = buffer;

        type = buffer[offset++] & 0xff;

        // recurse for constructed types, bit 6 = 1
        constructed = (type & 0x20) == 0x20;

        if ((type & 0x1f) == 0x1f) {
            // multi byte type, 7 bits per byte, only last byte bit 8 as zero

            type = 0;
            for (; ; ) {
                int temp = buffer[offset++];
                type = type << 7;
                if (temp >= 0) {
                    type += temp;
                    break;
                }

                // stip off bit 8
                temp = temp & 0x7f;
                type += temp;
            }
        }

        size = buffer[offset++] & 0xff;
        if (size >= 128) {
            int sizeLen = size - 128;

            // NOTE: for now, all sizes must fit int two bytes
            if (sizeLen > 2) {
                throw new RuntimeException("TLV size to large");
            }

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

        TLSize = offset - start;
        length = size;
        valueOffset = offset;

        if (constructed) {
            int end;
            TLV temp;

            end = offset + length;

            child = new TLV(buffer, offset);
            temp = child;
            for (; ; ) {
                offset = temp.valueOffset + temp.length;
                if (offset >= end) {
                    break;
                }

                temp.next = new TLV(buffer, offset);
                temp = temp.next;
            }
        }
    
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 new TLV
param
bytes value of new TLV


        type = tag;
        length = bytes.length;

        data = new byte[length + 4];
        int i = putHeader(data, 0);

        TLSize = i;
        valueOffset = i;
        System.arraycopy(bytes, 0, data, i, bytes.length);
    
Methods Summary
static java.lang.StringOIDtoString(byte[] buffer, int offset, int length)
Converts a subsequence of bytes into a printable OID, a string of decimal digits, each separated by a ".".

param
buffer byte array containing the bytes to be converted
param
offset starting offset of the byte subsequence inside b
param
length number of bytes to be converted
return
printable OID


                                                           
            
        StringBuffer result;
        int end;
        int t;
        int x;
        int y;

        if (length == 0) {
            return "";
        }

        result = new StringBuffer(40);

        end = offset + length;

        /*
         * first byte (t) always represents the first 2 values (x, y).
         * t = (x * 40) + y;
         */
        t = buffer[offset++] & 0xff;
        x = t / 40;
        y = t - (x * 40);

        result.append(x);
        result.append('.");
        result.append(y);

        x = 0;
        while (offset < end) {
            // 7 bit per byte, bit 8 = 0 means the end of a value
            x = x << 7;

            t = buffer[offset++];
            if (t >= 0) {
                x += t;
                result.append('.");
                result.append(x);
                x = 0;
            } else {
                x += t & 0x7f;
            }
        }

        return result.toString();
    
static byte[]StringToOID(java.lang.String oid)
Converts a printable OID into a subsequence of bytes.

param
oid printable OID
return
byte array containing the OID


                             
        

        StringTokenizer t = new StringTokenizer(oid, ".");

        int[] values = new int[t.countTokens()];
        for (int i = 0; i < values.length; i++) {
            values[i] = Integer.parseInt(t.nextToken(), 10);
        }

        byte[] x = new byte[MAX_OID_SIZE];

        int i = 0;
        x[i++] = (byte) (values[0] * 40 + values[1]);

        for (int j = 2; j < values.length; j++) {

            int k = values[j];

            int p = 0;

            while (true) {
                p += 1;
                k = k >> 7;
                if (k == 0) {
                    break;
                }
            }

            k = values[j];
            while (p > 0) {

                x[i] = (byte) (k >> ((p - 1) * 7));

                if (p == 1) {
                    x[i] &= 0x7f;
                } else {
                    x[i] |= 0x80;
                }
                p--;
                i++;
            }
        }

        byte[] data = new byte[i];
        System.arraycopy(x, 0, data, 0, i);
        return data;
    
dummyCA.TLVcopy()
Creates a copy of this TLV. The value of field next of the new TLV is null.

return
a copy of this TLV

        return new TLV(getDERData(), 0);
    
public static dummyCA.TLVcreateUTCTime(java.util.Calendar time)
Creates UTCTime TLV structure for given date.

param
time 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);
    
byte[]getDERData()
Returns DER encoded TLV.

return
DER encoded TLV


        if (data == null) {

            byte[] x = new byte[getDERSize()];

            int i = putHeader(x, 0);

            TLV c = child;

            while (c != null) {
                byte[] cdata = c.getDERData();
                System.arraycopy(cdata, 0, x, i, cdata.length);
                i += cdata.length;
                c = c.next;
            }
             if (i != x.length) {
                 throw new RuntimeException("debug");
             }

            return x;
        }

        byte[] x = new byte[length + TLSize];
        System.arraycopy(data, valueOffset - TLSize, x, 0, length + TLSize);
        return x;
    
private intgetDERSize()
Returns the size of DER encoded TLV.

return
the size of DER encoded TLV


        if (data == null) {

            int size = 0;

            TLV c = child;

            while (c != null) {
                size += c.getDERSize();
                c = c.next;
            }

            length = size;

            // length size
            if (size < 128) {
                size += 1;
            } else {
                size += 1;
                int i = size;
                while (i != 0) {
                    size += 1;
                    i = i >> 8;
                }
            }

            // tag size - only one byte tags are used
            size += 1;

            TLSize =  size - length;
        }
        return length + TLSize;
    
java.lang.StringgetOID()
Returns string representation of OID represented by this TLV.

return
string representation of OID represented by this TLV
throws
IOException if TLV doesn't contain OID


        if (type != OID_TYPE) {
            throw new IOException("OID expected");
        }
        return OIDtoString(data, valueOffset, length);
    
byte[]getValue()
Returns the value field of this TLV.

return
the value field of this TLV


        if (data == null) {
            return copy().getValue();
        }

        byte[] x = new byte[length];
        System.arraycopy(data, valueOffset, x, 0, length);
        return x;
    
static java.lang.StringhexEncode(byte[] b, int off, int len, int max)
Converts a subsequence of bytes in a byte array into a corresponding string of hexadecimal digits, each separated by a ":".

param
b byte array containing the bytes to be converted
param
off starting offset of the byte subsequence inside b
param
len number of bytes to be converted
param
max print a single "+" instead of the bytes after max, -1 for no max.
return
a string of corresponding hexadecimal digits or an error string


                                                                                            
              
        char[] r;
        int v;
        int i;
        int j;

        if ((b == null) || (len == 0)) {
            return "";
        }

        if ((off < 0) || (len < 0)) {
            throw new ArrayIndexOutOfBoundsException();
        }

        r = new char[len * 3];

        for (i = 0, j = 0; ; ) {
            v = b[off + i] & 0xff;
            r[j++] = hc[v >>> 4];
            r[j++] = hc[v & 0x0f];

            i++;
            if (i >= len) {
                break;
            }

            if (i == max) {
                r[j++] = ' ";
                r[j++] = '+";
                break;
            }

            r[j++] = ':";
        }

        return (new String(r, 0, j));
    
voidprint(java.io.PrintStream out)
Print the a TLV structure, recursing down for constructed types.

param
out output stream

        print(out, 0);
    
private voidprint(java.io.PrintStream out, int level)
Prints the a TLV structure, recursing down for constructed types.

param
out output stream
param
level what level this TLV is at


        for (int i = 0; i < level; i++) {
            out.print("    ");
        }

        byte[] buffer;

        if (data != null) {
            buffer = data;
        } else {
            buffer = getDERData();
        }

        if (child == null) {
            out.print("Type: 0x" + Integer.toHexString(type) +
                             " length: " + length + " value: ");
            if (type == PRINTSTR_TYPE ||
                type == TELETEXSTR_TYPE ||
                type == UTF8STR_TYPE ||
                type == IA5STR_TYPE ||
                type == UNIVSTR_TYPE) {
                try {
                    out.print(new String(buffer, valueOffset, length,
                                                "UTF-8"));
                } catch (UnsupportedEncodingException e) {
                    // ignore
                }
            } else if (type == OID_TYPE) {
                out.print(OIDtoString(buffer, valueOffset, length));
            } else {
                out.print(hexEncode(buffer, valueOffset, length, 999999));
            }

            out.println("");
        } else {
            if (type == SET_TYPE) {
                out.print("Set:");
            } else {
                out.print("Sequence:");
            }

            out.println("  (0x" + Integer.toHexString(type) +
                             " " + length + ")");

            child.print(out, level + 1);
        }

        if (next != null) {
            next.print(out, level);
        }
    
voidprint()
Print the a TLV structure, recursing down for constructed types.

        print(System.out, 0);
    
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;