package sos.passportapplet; /** * A very rough, zero extra memory use, TLV array scanner. * * @author Cees-Bart Breunesse <ceesb@cs.ru.nl> * @author Wojciech Mostowski <woj@cs.ru.nl> * */ public class BERTLVScanner { /** Universal tag class. */ public static final short UNIVERSAL_CLASS = 0; /** Application tag class. */ public static final short APPLICATION_CLASS = 1; /** Context specific tag class. */ public static final short CONTEXT_SPECIFIC_CLASS = 2; /** Private tag class. */ public static final short PRIVATE_CLASS = 3; // Tag data static short tag; static short tagClass; static boolean isPrimitive; // Offset and length for the value static short valueOffset; static short valueLength; private BERTLVScanner() { } public static short readTag(byte[] in, short offset) { short in_p = offset; short b = (short) (in[in_p] & 0xff); while (b == 0 || b == 0xff) { in_p++; b = in[in_p]; /* skip 00 and FF */ } switch (b & 0xC0) { case 0: tagClass = UNIVERSAL_CLASS; break; case 0x40: tagClass = APPLICATION_CLASS; break; case 0x80: tagClass = CONTEXT_SPECIFIC_CLASS; break; case 0xC0: tagClass = PRIVATE_CLASS; break; } switch (b & 0x20) { case 0: isPrimitive = true; break; case 0x20: isPrimitive = false; break; } switch (b & 0x1F) { case 0x1F: tag = b; in_p++; b = in[in_p]; while ((b & 0x80) == 0x80) { tag <<= 8; tag |= (b & 0x7F); in_p++; b = in[in_p]; } tag <<= 8; tag |= (b & 0x7F); break; default: tag = b; break; } in_p++; return in_p; } public static short readLength(byte[] in, short offset) { short in_p = offset; short b = (short) (in[offset] & 0xff); if ((b & 0x80) == 0) { /* short form */ valueLength = b; } else { /* long form */ short count = (short) (b & 0x7F); valueLength = 0; for (short i = 0; i < count; i++) { in_p++; b = (short) (in[in_p] & 0xff); valueLength <<= 8; valueLength += b; } } valueOffset = (short) (in_p + 1); return valueOffset; } public static short skipValue() { return (short) (valueOffset + valueLength); } }