/*
* DrivingLicenseApplet - A reference implementation of the ISO18013 standards.
* Based on the passport applet code developed by the JMRTD team, see
* http://jmrtd.org
*
* Copyright (C) 2006 SoS group, Radboud University
* Copyright (C) 2009 Wojciech Mostowski, Radboud University
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
package org.isodl.applet;
/**
* 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. */
static final short UNIVERSAL_CLASS = 0;
/** Application tag class. */
static final short APPLICATION_CLASS = 1;
/** Context specific tag class. */
static final short CONTEXT_SPECIFIC_CLASS = 2;
/** Private tag class. */
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() { }
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;
}
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;
}
static short skipValue() {
return (short) (valueOffset + valueLength);
}
}