/* * * * Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program 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 * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. */ //----------------------------------------------------------------------------- // PACKAGE DEFINITION //----------------------------------------------------------------------------- package sim.toolkit; //import sat.AccessBuffer; //----------------------------------------------------------------------------- // IMPORTS //----------------------------------------------------------------------------- import javacard.framework.Util; import javacard.framework.ISO7816; /** * * The ViewHandler class offers basic services and contains basic * methods to handle * a Simple TLV List, such as in a <b>Terminal Response</b> data field * or in a BER-TLV * element (<b>Envelope</b> data field or <b>Proactive</b> command). * The byte at offset 0 of a handler is the tag of the first Simple TLV. * * @version 8.3.0 * * @see ToolkitException */ public abstract class ViewHandler { /** Offset of BER_TLV_TAG. */ protected static final byte BER_TLV_TAG_OFFSET = (byte)5; /** Offset of Lc in the APDU buffer. */ protected static final byte OFFSET_LC = (byte)4; /** Offset of TPDUD. */ protected static final byte TPUD_OFFSET = (byte)12; /** Tag of DEVICE_ID field. */ private static final byte DEVICE_ID_TAG = (byte)0x82; /** Length of DEVICE_ID field. */ private static final byte DEVICE_ID_LENGTH = (byte)0x02; /** Tag of ADDRESS field. */ private static final byte ADDRESS_TAG = (byte)0x06; /** Tag of SMS_TPDU. */ private static final byte SMS_TPDU_TAG = (byte)0x8B; /** Offset of first occurrence of TLV. */ short currentTLVOffset; /** Offset of first occurrence of TLV. */ short firstTLVOffset; /** Reference to SAT Accessor. */ public static AccessSAT SATAccessor; /** Reference to TI which is now serviced. */ public static ToolkitInterface currentTI; /** * Constructor. */ ViewHandler() {} // ------------------------------- Constructor --------------------------- /** * Builds a new ViewHandler object. * * @param buffer a reference to the TLV buffer * @param offset the position in the TLV buffer * @param length the length of the TLV buffer * * @exception NullPointerException if <code>buffer</code> * is <code>null</code> * @exception ArrayIndexOutOfBoundsException if <code>offset</code> * or <code>length</code> or both would cause access outside array bounds */ ViewHandler(byte[] buffer, short offset, short length) throws NullPointerException, ArrayIndexOutOfBoundsException { } // ------------------------------- Public methods ------------------------- /** * Returns the length of the TLV list. * * @return length in bytes * * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is * busy</ul> */ public short getLength() throws ToolkitException { byte[] buffer = getAPDUBuffer(); short length = (short)(buffer[(short)(currentTLVOffset + 1)] & 0xFF); return length; } /** * Copies the simple TLV list contained in the handler to the * destination byte array. * * <p> * Notes:<ul> * <li><em>If </em><code>dstOffset</code><em> or * </em><code>dstLength</code><em> parameter is negative * an </em><code>ArrayIndexOutOfBoundsException</code> * <em> exception is thrown and no copy is performed.</em> * <li><em>If </em><code>dstOffset+dstLength</code><em> is greater * than </em><code>dstBuffer.length</code><em>, the length * of the </em><code>dstBuffer</code><em> array an * </em><code>ArrayIndexOutOfBoundsException</code><em> * exception is thrown and no copy is performed.</em> * </ul> * * @param dstBuffer a reference to the destination buffer * @param dstOffset the position in the destination buffer * @param dstLength the data length to be copied * * @return <code>dstOffset+dstLength</code> * * @exception NullPointerException if <code>dstBuffer</code> * is <code>null</code> * @exception ArrayIndexOutOfBoundsException if copy would * cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>OUT_OF_TLV_BOUNDARIES</code> if <code>dstLength</code> * is grater than the length of the simple TLV List.</ul> */ public short copy(byte[] dstBuffer, short dstOffset, short dstLength) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { byte[] buffer = getAPDUBuffer(); short TLVLength = (short)(buffer[(short)(currentTLVOffset + 1)] & 0xFF); if (TLVLength < dstLength) { // if length is greater than the TLV length itself, then // throw exception ToolkitException.throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES); } // copy the current TLV list Util.arrayCopy(buffer, (short)(currentTLVOffset+2), dstBuffer, dstOffset, dstLength); return (short)(dstOffset + dstLength); } /** * Looks for the indicated occurrence of a TLV element from the beginning of * the TLV list (handler buffer). If the method is successful then the * corresponding TLV becomes current, else no TLV is selected. * This search method is Comprehension Required flag independent. * * @param tag the tag of the TLV element to search * @param occurrence the occurrence number of the TLV element (1 for the * first, 2 for the second...) * * @return result of the method: <ul> * <li><code>TLV_NOT_FOUND</code> if the required occurrence of the * TLV element does not exist * <li><code>TLV_FOUND_CR_SET</code> if the required occurrence exists * and Comprehension Required flag is set * <li><code>TLV_FOUND_CR_NOT_SET</code> if the required occurrence * exists and Comprehension Required flag is not set</ul> * * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>BAD_INPUT_PARAMETER</code> if an input parameter is not * valid (e.g. occurrence = 0)</ul> */ public byte findTLV(byte tag, byte occurrence) throws ToolkitException { byte count = 0; // count of occurances byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getTLVOffset(buffer, tag, Lc, occurrence); if (TLVOffset >= Lc) return ToolkitConstants.TLV_NOT_FOUND; // not found currentTLVOffset = TLVOffset; if ((byte)(buffer[TLVOffset] & ToolkitConstants.TAG_SET_CR) == ToolkitConstants.TAG_SET_CR) return ToolkitConstants.TLV_FOUND_CR_SET; return ToolkitConstants.TLV_FOUND_CR_NOT_SET; } /** * Gets the binary length of the value field for the last TLV element * which has been found in the handler. * * @return length of the value field * * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element</ul> */ public short getValueLength() throws ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getLastTLVOffset(buffer, Lc); if (TLVOffset >= Lc) { ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } return (short)(buffer[(short) (TLVOffset + 1)] & 0xFF); // return the length } /** * Gets a byte from the last TLV element which has been found in the * handler. * * @param valueOffset the offset of the byte to return in the TLV element * * @return element value (1 byte) * * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable TLV * element * <li><code>OUT_OF_TLV_BOUNDARIES</code> if * <code>valueOffset</code> is out of the current TLV </ul> */ public byte getValueByte(short valueOffset) throws ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getLastTLVOffset(buffer, Lc); if (TLVOffset >= Lc) { ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } short TLVLength = (short)(buffer[(short)(TLVOffset + 1)] & 0xFF); if (valueOffset > TLVLength) { ToolkitException.throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES); } // return the byte at offset return buffer[(short)(TLVOffset + 2 + valueOffset)]; } /** * Copies a part of the last TLV element which has been found, into a * destination buffer. * * <p> * Notes:<ul> * <li><em>If </em><code>dstOffset</code><em> or * </em><code>dstLength</code><em> parameter is negative an * </em><code>ArrayIndexOutOfBoundsException</code> * <em> exception is thrown and no copy is performed.</em> * <li><em>If </em><code>dstOffset+dstLength</code><em> is * greater than </em><code>dstBuffer.length</code><em>, the length * of the </em><code>dstBuffer</code><em> array an * </em><code>ArrayIndexOutOfBoundsException</code><em> exception * is thrown and no copy is performed.</em> * </ul> * * @param valueOffset the offset of the first byte in the source * TLV element * @param dstBuffer a reference to the destination buffer * @param dstOffset the position in the destination buffer * @param dstLength the data length to be copied * * @return <code>dstOffset+dstLength</code> * * @exception NullPointerException if <code>dstBuffer</code> is * <code>null</code> * @exception ArrayIndexOutOfBoundsException if copyValue would * cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element * <li><code>OUT_OF_TLV_BOUNDARIES</code> if: * <ul> * <li><code>valueOffset</code> parameter is negative or * <li><code>valueOffset + dstLength</code> is greater than * the length of the current TLV * </ul> * </ul> */ public short copyValue(short valueOffset, byte[] dstBuffer, short dstOffset, short dstLength) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getLastTLVOffset(buffer, Lc); if (TLVOffset >= Lc) { ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } short TLVLength = (short)(buffer[(short)(TLVOffset + 1)] & 0xFF); if (valueOffset > TLVLength || valueOffset < 0) { ToolkitException.throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES); } Util.arrayCopy(buffer, (short)(currentTLVOffset + 2 + valueOffset), dstBuffer, dstOffset, dstLength); return buffer[(short)(TLVOffset + 2 + valueOffset)]; } /** * Compares the last found TLV element with a buffer. * * <p> * Notes:<ul> * <li><em>If </em><code>compareOffset</code><em> or * </em><code>compareLength</code><em> parameter is negative * an </em><code>ArrayIndexOutOfBoundsException</code> * <em> exception is thrown and no compare is performed.</em> * <li><em>If </em><code>compareOffset+compareLength</code><em>is * greater than </em><code>compareBuffer.length</code><em>, the length * of the </em><code>compareBuffer</code><em> array an * </em><code>ArrayIndexOutOfBoundsException</code><em> exception * is thrown and no compare is performed.</em> * </ul> * * @param valueOffset the offset of the first byte to compare in * the TLV element * @param compareBuffer a reference to the comparison buffer * @param compareOffset the position in the comparison buffer * @param compareLength the length to be compared * * @return the result of the comparison as follows: <ul> * <li><code>0</code> if identical * <li><code>-1</code> if the first miscomparing byte in simple * TLV List is less than that in <code>compareBuffer</code>, * <li><code>1</code> if the first miscomparing byte in simple * TLV List is greater than that in <code>compareBuffer</code>.</ul> * * @exception NullPointerException if <code>compareBuffer</code> is * <code>null</code> * @exception ArrayIndexOutOfBoundsException if compareValue would * cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element * <li><code>OUT_OF_TLV_BOUNDARIES</code> if: * <ul> * <li><code>valueOffset</code> parameter is negative or * <li><code>valueOffset + compareLength</code> is greater * than the length of the current TLV * </ul> * </ul> */ public byte compareValue(short valueOffset, byte[] compareBuffer, short compareOffset, short compareLength) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getLastTLVOffset(buffer, Lc); if (TLVOffset >= Lc) { ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } short TLVLength = (short)(buffer[(short)(TLVOffset + 1)] & 0xFF); if (valueOffset > TLVLength || valueOffset < 0) { ToolkitException.throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES); } return Util.arrayCompare(buffer, (short)(currentTLVOffset + 2 + valueOffset), compareBuffer, compareOffset, compareLength); } /** * Looks for the first occurrence of a TLV element from the beginning * of a TLV * list and copy its value into a destination buffer. * If no TLV element is found, the <code>UNAVAILABLE_ELEMENT</code> * exception is thrown. * If the method is successful then the corresponding TLV becomes current, * else no TLV is selected. * This search method is Comprehension Required flag independent. * * <p> * Notes:<ul> * <li><em>If </em><code>dstOffset</code><em> parameter is negative or * </em><code>dstOffset</code> * <em> is greater than </em><code>dstBuffer.length</code><em>, the * length of the </em><code>dstBuffer</code> * <em> array an </em><code>ArrayIndexOutOfBoundsException</code><em> * exception is thrown and no find is performed.</em> * </ul> * * @param tag the tag of the TLV element to search * @param dstBuffer a reference to the destination buffer * @param dstOffset the position in the destination buffer * * @return <code>dstOffset</code> + length of the copied value * * @exception NullPointerException if <code>dstBuffer</code> * is <code>null</code> * @exception ArrayIndexOutOfBoundsException if findAndCopyValue * would cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element</ul> */ public short findAndCopyValue(byte tag, byte[] dstBuffer, short dstOffset) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { // this method could potentialy use the other // findAndCopyValue() method. The only problem is the length // parameter required by that method byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getTLVOffset(buffer, tag, Lc, (short)1); if (TLVOffset >= Lc) { // TLV not found ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } currentTLVOffset = TLVOffset; short length = buffer[(short)(TLVOffset+1)]; Util.arrayCopy(buffer, (short)(TLVOffset+2), dstBuffer, dstOffset, length); return (short)(dstOffset + length); } /** * Looks for the indicated occurrence of a TLV element from the * beginning of a TLV * list and copy its value into a destination buffer. * If no TLV element is found, the <code>UNAVAILABLE_ELEMENT</code> * exception is thrown. * If the method is successful then the corresponding TLV becomes current, * else no TLV is selected. * This search method is Comprehension Required flag independent. * * <p> * Notes:<ul> * <li><em>If </em><code>dstOffset</code><em> or * </em><code>dstLength</code><em> parameter is negative * an </em><code>ArrayIndexOutOfBoundsException</code> * <em> exception is thrown and no copy is performed.</em> * <li><em>If </em><code>dstOffset+dstLength</code><em>is greater * than </em><code>dstBuffer.length</code><em>, the length * of the </em><code>dstBuffer</code><em> array an * </em><code>ArrayIndexOutOfBoundsException</code><em> exception * is thrown and no copy is performed.</em> * </ul> * * @param tag the tag of the TLV element to search * @param occurrence the occurrence number of the TLV element * (1 for the first, 2 for the second...) * @param valueOffset the offset of the first byte in the source * TLV element * @param dstBuffer a reference to the destination buffer * @param dstOffset the position in the destination buffer * @param dstLength the data length to be copied * * @return <code>dstOffset + dstLength</code> * * @exception NullPointerException if <code>dstBuffer</code> is * <code>null</code> * @exception ArrayIndexOutOfBoundsException if findAndCopyValue * would cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element * <li><code>OUT_OF_TLV_BOUNDARIES</code> if: * <ul> * <li><code>valueOffset</code> parameter is negative or * <li><code>valueOffset + dstLength</code> is greater * than the length of the current TLV * </ul> * <li><code>BAD_INPUT_PARAMETER</code> if an input parameter * is not valid (e.g. occurrence = 0)</ul> */ public short findAndCopyValue(byte tag, byte occurrence, short valueOffset, byte[] dstBuffer, short dstOffset, short dstLength) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getTLVOffset(buffer, tag, Lc, occurrence); if (TLVOffset >= Lc) { // TLV not found ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } // this is the current TLV currentTLVOffset = TLVOffset; short length = buffer[(short)(TLVOffset+1)]; if ((valueOffset < 0) || (short)(valueOffset + dstLength) > length) { ToolkitException.throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES); } Util.arrayCopy(buffer, (short)(TLVOffset+2+valueOffset), dstBuffer, dstOffset, dstLength); return (short)(dstOffset + length); } /** * Looks for the first occurrence of a TLV element * from beginning of a TLV * list and compare its value with a buffer. * If no TLV element is found, the * <code>UNAVAILABLE_ELEMENT</code> exception is thrown. * If the method is successful then the corresponding TLV * becomes current, else no TLV is selected. * This search method is Comprehension Required flag independent. * * <p> * Notes:<ul> * <li><em>If </em><code>compareOffset</code><em> parameter is * negative or </em><code>compareOffset</code> * <em> is greater than </em><code>compareBuffer.length</code><em>, * the length of the </em><code>compareBuffer</code> * <em> array an </em><code>ArrayIndexOutOfBoundsException</code><em> * exception is thrown and no find is performed.</em> * </ul> * * @param tag the tag of the TLV element to search * @param compareBuffer a reference to the comparison buffer * @param compareOffset the position in the comparison buffer * * @return the result of the comparison as follows: <ul> * <li><code>0</code> if identical * <li><code>-1</code> if the first miscomparing byte in simple * TLV is less than that in <code>compareBuffer</code>, * <li><code>1</code> if the first miscomparing byte in simple * TLV is greater than that in <code>compareBuffer</code>.</ul> * * @exception NullPointerException if <code>compareBuffer</code> is * <code>null</code> * @exception ArrayIndexOutOfBoundsException if findAndCompareValue * would cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element</ul> */ public byte findAndCompareValue(byte tag, byte[] compareBuffer, short compareOffset) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getTLVOffset(buffer, tag, Lc, (byte)1); if (TLVOffset >= Lc) { // TLV not found ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } // this is the current TLV currentTLVOffset = TLVOffset; short length = buffer[(short)(TLVOffset+1)]; return Util.arrayCompare(buffer, (short)(TLVOffset+2), compareBuffer, compareOffset, length); } /** * Looks for the indicated occurrence of a TLV element from the * beginning of a TLV list and compare its value with a buffer. * If no TLV element is found, the <code>UNAVAILABLE_ELEMENT</code> * exception is thrown. * If the method is successful then the corresponding TLV becomes * current, else no TLV is selected. * This search method is Comprehension Required flag independent. * * <p> * Notes:<ul> * <li><em>If </em><code>compareOffset</code><em> or * </em><code>compareLength</code><em> parameter is * negative an </em><code>ArrayIndexOutOfBoundsException</code> * <em> exception is thrown and no find and compare is performed.</em> * <li><em>If </em><code>compareOffset+compareLength</code><em> is * greater than </em><code>compareBuffer.length</code><em>, the length * of the </em><code>compareBuffer</code><em> array an * </em><code>ArrayIndexOutOfBoundsException</code><em> exception * is thrown and no find and compare is performed.</em> * </ul> * * @param tag the tag of the TLV element to search * @param occurrence the occurrence number of the TLV element * (1 for the first, 2 for the second...) * @param valueOffset the offset of the first byte in the source * TLV element * @param compareBuffer a reference to the comparison buffer * @param compareOffset the position in the comparison buffer * @param compareLength the length to be compared * * @return the result of the comparison as follows: <ul> * <li><code>0</code> if identical * <li><code>-1</code> if the first miscomparing byte in * simple TLV is less than that in <code>compareBuffer</code>, * <li><code>1</code> if the first miscomparing byte in simple * TLV is greater than that in <code>compareBuffer</code>.</ul> * * @exception NullPointerException if <code>compareBuffer</code> * is <code>null</code> * @exception ArrayIndexOutOfBoundsException if findAndCompareValue * would cause access of data outside array bounds. * @exception ToolkitException with the following reason codes: <ul> * <li><code>HANDLER_NOT_AVAILABLE</code> if the handler is busy * <li><code>UNAVAILABLE_ELEMENT</code> in case of unavailable * TLV element * <li><code>OUT_OF_TLV_BOUNDARIES</code> if: * <ul> * <li><code>valueOffset</code> parameter is negative or * <li><code>valueOffset + compareLength</code> is greater * than the length of the current TLV * </ul> * <li><code>BAD_INPUT_PARAMETER</code> if an input parameter is * not valid (e.g. occurrence = 0)</ul> */ public byte findAndCompareValue(byte tag, byte occurrence, short valueOffset, byte[] compareBuffer, short compareOffset, short compareLength) throws NullPointerException, ArrayIndexOutOfBoundsException, ToolkitException { byte[] buffer = getAPDUBuffer(); short Lc = (short)(buffer[OFFSET_LC] & 0xFF); short TLVOffset = getTLVOffset(buffer, tag, Lc, occurrence); if (TLVOffset >= Lc) { // TLV not found ToolkitException.throwIt(ToolkitException.UNAVAILABLE_ELEMENT); } // this is the current TLV currentTLVOffset = TLVOffset; short length = buffer[(short)(TLVOffset+1)]; if ((valueOffset < 0) || (short) (valueOffset + compareLength) > length) { ToolkitException.throwIt(ToolkitException.OUT_OF_TLV_BOUNDARIES); } return Util.arrayCompare(buffer, (short)(TLVOffset+2+valueOffset), compareBuffer, compareOffset, compareLength); } /** * Helper method for <code>findAndCompareValue</code>. * @param buffer APDU buffer * @param tag What tag we are finding * @param Lc Length of command data * @param occurrence The occurrence number of the TLV element * @return Offset of the tag */ protected short getTLVOffset(byte[] buffer, byte tag, short Lc, short occurrence) { byte count = 0; // count of occurances short offset = firstTLVOffset; tag = (byte)(tag & 0x7F); while (offset < Lc) { if ((byte)(buffer[offset] & 0x7F) == tag) { count++; if (count != occurrence) { continue; } return offset; } else { // advance to next TLV offset++; short length = buffer[offset]; offset = (short)(offset + length + 1); } } return offset; // not found } /** * Helper method for <code>getValue...</code> and * <code>copyValue...</code>. * @param buffer APDU buffer * @param Lc Length of command data * @return Offset of the tag */ protected short getLastTLVOffset(byte[] buffer, short Lc) { short offset = firstTLVOffset; short lastTLVOffset; do { lastTLVOffset = offset; // advance to next TLV offset++; short length = buffer[offset]; offset = (short)(offset + length + 1); } while (offset < Lc); return lastTLVOffset; } /** * Copies the APDUBuffer content into provided buffer. * @param buffer The buffer * @return Provided buffer filled with APDUBuffer content */ public static byte[] getAPDUBuffer(byte[] buffer) { short len = SATAccessor.getAPDUBufferLength(); for (short i = 0; i < len; i++) { buffer[i] = SATAccessor.getAPDUBufferByte(i); } return buffer; } /** * Copies the APDUBuffer content into current buffer. * @return apdu buffer */ public static byte[] getAPDUBuffer() { return getAPDUBuffer(currentTI.getAPDUBuffer()); } /** * Copies content of provided buffer into the APDUBuffer. * @param buffer The buffer * @param length Length of the buffer */ public static void setAPDUBuffer(byte[] buffer, short length) { for (short i = 0; i < length; i++) { SATAccessor.setAPDUBufferByte(i, buffer[i]); } } /** * Copies content of current buffer into the APDUBuffer. * @param length Length of the current buffer */ public static void setAPDUBuffer(short length) { setAPDUBuffer(currentTI.getAPDUBuffer(), length); } /** * Sets the data in the out buffer. * @param length Length of data */ public static void setOutBufferData(short length) { setAPDUBuffer(length); SATAccessor.setOutBufferData(length); } }