All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javacard.framework.APDU Maven / Gradle / Ivy

The newest version!
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javacard.framework;

import com.licel.jcardsim.base.SimulatorSystem;

/**
 * 
 * Application Protocol Data Unit (APDU) is
 * the communication format between the card and the off-card applications.
 * The format of the APDU is defined in ISO specification 7816-4.

* * This class only supports messages which conform to the structure of * command and response defined in ISO 7816-4. The behavior of messages which * use proprietary structure of messages is * undefined. This class optionally supports extended length fields but only when * the currently selected applet implements the javacardx.apdu.ExtendedLength interface.

* * The APDU object is owned by the Java Card runtime environment. The APDU class maintains a byte array * buffer which is used to transfer incoming APDU header and data bytes as well as outgoing data. * The buffer length must be at least 133 bytes ( 5 bytes of header and 128 bytes of data ). * The Java Card runtime environment must zero out the APDU buffer before each new message received from the CAD.

* * The Java Card runtime environment designates the APDU object as a temporary Java Card runtime environment Entry Point Object * (See Runtime Environment * Specification for the Java Card Platform, section 6.2.1 for details). * A temporary Java Card runtime environment Entry Point Object can be accessed from any applet context. References * to these temporary objects cannot be stored in class variables or instance variables * or array components. *

The Java Card runtime environment similarly marks the APDU buffer as a global array * (See Runtime Environment * Specification for the Java Card Platform, section 6.2.2 for details). * A global array * can be accessed from any applet context. References to global arrays * cannot be stored in class variables or instance variables or array components. *

* * The applet receives the APDU instance to process from * the Java Card runtime environment in the Applet.process(APDU) method, and * the first five header bytes [ CLA, INS, P1, P2, P3 ] are available * in the APDU buffer. (The header format is the ISO7816-4 defined 7 byte extended APDU format * with a 3 byte Lc field when the Lc field in the incoming APDU header is 3 bytes long).

* * The APDU class API is designed to be transport protocol independent. * In other words, applets can use the same APDU methods regardless of whether * the underlying protocol in use is T=0 or T=1 (as defined in ISO 7816-3).

* The incoming APDU data size may be bigger than the APDU buffer size and may therefore * need to be read in portions by the applet. Similarly, the * outgoing response APDU data size may be bigger than the APDU buffer size and may * need to be written in portions by the applet. The APDU class has methods * to facilitate this.

* * For sending large byte arrays as response data, * the APDU class provides a special method sendBytesLong() which * manages the APDU buffer.

* *

 * // The purpose of this example is to show most of the methods
 * // in use and not to depict any particular APDU processing
 * 
 * class MyApplet extends javacard.framework.Applet{
 * // ...
 * public void process(APDU apdu){
 * // ...
 * byte[] buffer = apdu.getBuffer();
 * byte cla = buffer[ISO7816.OFFSET_CLA];
 * byte ins = buffer[ISO7816.OFFSET_INS];
 * ...
 * // assume this command has incoming data
 * // Lc tells us the incoming apdu command length
 * short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
 * if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
 * 
 * short readCount = apdu.setIncomingAndReceive();
 * while ( bytesLeft > 0){
 * // process bytes in buffer[5] to buffer[readCount+4];
 * bytesLeft -= readCount;
 * readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
 * }
 * //
 * //...
 * //
 * // Note that for a short response as in the case illustrated here
 * // the three APDU method calls shown : setOutgoing(),setOutgoingLength() & sendBytes()
 * // could be replaced by one APDU method call : setOutgoingAndSend().
 * 
 * // construct the reply APDU
 * short le = apdu.setOutgoing();
 * if (le < (short)2) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
 * apdu.setOutgoingLength( (short)3 );
 * 
 * // build response data in apdu.buffer[ 0.. outCount-1 ];
 * buffer[0] = (byte)1; buffer[1] = (byte)2; buffer[3] = (byte)3;
 * apdu.sendBytes ( (short)0 , (short)3 );
 * // return good complete status 90 00
 * }
 * // ...
 * }
 * 
* * The APDU class also defines a set of STATE_.. constants * which represent the various processing states of the APDU object based * on the methods invoked and the state of the data transfers. The * getCurrentState() method returns the current state. *

* Note that the state number assignments are ordered as follows: * STATE_INITIAL < STATE_PARTIAL_INCOMING < STATE_FULL_INCOMING < * STATE_OUTGOING < STATE_OUTGOING_LENGTH_KNOWN < STATE_PARTIAL_OUTGOING < * STATE_FULL_OUTGOING. *

* The following are processing error states and have negative state number * assignments : * STATE_ERROR_NO_T0_GETRESPONSE, STATE_ERROR_T1_IFD_ABORT, STATE_ERROR_IO and * STATE_ERROR_NO_T0_REISSUE. *

Note:

    *
  • The method descriptions use the ISO7816-4 notation * for the various APDU I/O cases of input and output directions. For example - * T=0 (Case 2S) protocol - refers to short length outbound only case * using the T=0 protocol. * The perspective of the notation used in the method descriptions * is that of the card(ICC) as seen at the transport layer(TPDU). External * transformations of the APDU I/O case may have occurred at the CAD * and therefore not visible to the card. *
* @see APDUException * @see ISOException */ public final class APDU { /** * This is the state of a new APDU object when only the command * header is valid. */ public static final byte STATE_INITIAL = 0; /** * This is the state of a APDU object when incoming data * has partially been received. */ public static final byte STATE_PARTIAL_INCOMING = 1; /** * This is the state of a APDU object when all the * incoming data been received. */ public static final byte STATE_FULL_INCOMING = 2; /** * This is the state of a new APDU object when data transfer * mode is outbound but length is not yet known. */ public static final byte STATE_OUTGOING = 3; /** * This is the state of a APDU object when data transfer * mode is outbound and outbound length is known. */ public static final byte STATE_OUTGOING_LENGTH_KNOWN = 4; /** * This is the state of a APDU object when some outbound * data has been transferred but not all. */ public static final byte STATE_PARTIAL_OUTGOING = 5; /** * This is the state of a APDU object when all outbound data * has been transferred. */ public static final byte STATE_FULL_OUTGOING = 6; /** * This error state of a APDU object occurs when an APDUException * with reason code APDUException.NO_T0_GETRESPONSE has been * thrown. */ public static final byte STATE_ERROR_NO_T0_GETRESPONSE = -1; /** * This error state of a APDU object occurs when an APDUException * with reason code APDUException.T1_IFD_ABORT has been * thrown. */ public static final byte STATE_ERROR_T1_IFD_ABORT = -2; /** * This error state of a APDU object occurs when an APDUException * with reason code APDUException.IO_ERROR has been * thrown */ public static final byte STATE_ERROR_IO = -3; /** * This error state of a APDU object occurs when an APDUException * with reason code APDUException.NO_T0_REISSUE has been * thrown. */ public static final byte STATE_ERROR_NO_T0_REISSUE = -4; /** * Media nibble mask in protocol byte */ public static final byte PROTOCOL_MEDIA_MASK = -16; /** * Type nibble mask in protocol byte */ public static final byte PROTOCOL_TYPE_MASK = 15; /** * ISO 7816 transport protocol type T=0. */ public static final byte PROTOCOL_T0 = 0; /** * This constant is used to denote both the ISO 7816 transport protocol * type T=1 and the variant for contactless cards defined in ISO 14443-4. */ public static final byte PROTOCOL_T1 = 1; /** * Transport protocol Media - Contacted Asynchronous Half Duplex */ public static final byte PROTOCOL_MEDIA_DEFAULT = 0; /** * Transport protocol Media - Contactless Type A */ public static final byte PROTOCOL_MEDIA_CONTACTLESS_TYPE_A = -128; /** * Transport protocol Media - Contactless Type B */ public static final byte PROTOCOL_MEDIA_CONTACTLESS_TYPE_B = -112; /** * Transport protocol Media - USB */ public static final byte PROTOCOL_MEDIA_USB = -96; // buffer size private static final short BUFFER_SIZE = 260; // input block size, for T0 protocol = 1 private static final short T0_IBS = 1; // output block size, for T0 protocol = 258 private static final short T0_OBS = 258; // NAD, for T0 protocol = 9 private static final byte T0_NAD = 0; // transient array to store variables private byte[] ramVars; // LE variable offset in ramVars private static final byte LE = 0; // LR variable offset in ramVars private static final byte LR = 1; // LC variable offset in ramVars private static final byte LC = 2; // PRE_READ_LENGTH variable offset in ramVars private static final byte PRE_READ_LENGTH = 3; // CURRENT_STATE variable offset in ramVars private static final byte CURRENT_STATE = 4; // LOGICAL_CHN variable offset in ramVars private static final byte LOGICAL_CHN = 5; // total length ramVars private static final byte RAM_VARS_LENGTH = 6; // transient array to store boolean flags private boolean[] flags; // outgoingFlag; private static final byte OUTGOING_FLAG = 0; // outgoingLenSetFlag; private static final byte OUTGOING_LEN_SET_FLAG = 1; // noChainingFlag; private static final byte NO_CHAINING_FLAG = 2; // incomingFlag; private static final byte INCOMING_FLAG = 3; // notGetResponseFlag; private static final byte NO_GET_RESPONSE_FLAG = 4; // total length flags private static final byte FLAGS_LENGTH = 5; // private byte[] buffer; // reference to this private static APDU thisAPDU; APDU() { buffer = JCSystem.makeTransientByteArray(BUFFER_SIZE, JCSystem.CLEAR_ON_RESET); ramVars = JCSystem.makeTransientByteArray(RAM_VARS_LENGTH, JCSystem.CLEAR_ON_RESET); flags = JCSystem.makeTransientBooleanArray(FLAGS_LENGTH, JCSystem.CLEAR_ON_RESET); thisAPDU = this; } /** * Returns the APDU buffer byte array. *

Note:

    *
  • References to the APDU buffer byte array * cannot be stored in class variables or instance variables or array components. * See Runtime * Specification for the Java Card Platform, section 6.2.2 for details. *
* @return byte array containing the APDU buffer */ public byte[] getBuffer() { return buffer; } /** * Returns the configured incoming block size. * In T=1 protocol, this corresponds to IFSC (information field size for ICC), * the maximum size of incoming data blocks into the card. In T=0 protocol, * this method returns 1. * IFSC is defined in ISO 7816-3.

* This information may be used to ensure that there is enough space remaining in the * APDU buffer when receiveBytes() is invoked. *

Note: *

    *
  • On receiveBytes() the bOff param * should account for this potential blocksize. *
* @return incoming block size setting * @see #receiveBytes(short) */ public static short getInBlockSize() { return T0_IBS; } /** * Returns the configured outgoing block size. * In T=1 protocol, this corresponds to IFSD (information field size for interface device), * the maximum size of outgoing data blocks to the CAD. * In T=0 protocol, this method returns 258 (accounts for 2 status bytes). * IFSD is defined in ISO 7816-3. *

This information may be used prior to invoking the setOutgoingLength() method, * to limit the length of outgoing messages when BLOCK CHAINING is not allowed. *

Note:

    *
  • On setOutgoingLength() the len param * should account for this potential blocksize. *
* @return outgoing block size setting * @see #setOutgoingLength(short) */ public static short getOutBlockSize() { return T0_OBS; } /** * Returns the ISO 7816 transport protocol type, T=1 or T=0 in the low nibble * and the transport media in the upper nibble in use. * @return he protocol media and type in progress * Valid nibble codes are listed in PROTOCOL_ .. constants above. * @see PROTOCOL_T0 */ public static byte getProtocol() { return PROTOCOL_T0; } /** * Returns the Node Address byte (NAD) in T=1 protocol, and 0 * in T=0 protocol. * This may be used as additional information to maintain multiple contexts. * @return NAD transport byte as defined in ISO 7816-3 */ public byte getNAD() { return T0_NAD; } /** * This method is used to set the data transfer direction to * outbound and to obtain the expected length of response (Le). This method * should only be called on a case 2 or case 4 command, otherwise erroneous * behavior may result. *

Notes.

    *
  • On a case 4 command, the setIncomingAndReceive() must * be invoked prior to calling this method. Otherwise, erroneous * behavior may result in T=0 protocol. *
  • Any remaining incoming data will be discarded. *
  • In T=0 (Case 4S) protocol, this method will return 256 with normal * semantics. *
  • In T=0 (Case 2E, 4S) protocol, this method will return 32767 when * the currently selected applet implements the * javacardx.apdu.ExtendedLength interface. *
  • In T=1 (Case 2E, 4E) protocol, this method will return 32767 when the * Le field in the APDU command is 0x0000 and the currently selected applet implements the * javacardx.apdu.ExtendedLength interface. *
  • This method sets the state of the APDU object to * STATE_OUTGOING. *
* @return Le, the expected length of response * @throws APDUException with the following reason codes:
    *
  • APDUException.ILLEGAL_USE if this method, or setOutgoingNoChaining() method already invoked. *
  • APDUException.IO_ERROR on I/O error. */ public short setOutgoing() throws APDUException { if (flags[OUTGOING_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } flags[OUTGOING_FLAG] = true; ramVars[CURRENT_STATE] = STATE_OUTGOING; return getLe(); } /** * This method is used to set the data transfer direction to * outbound without using BLOCK CHAINING (See ISO 7816-3/4) and to obtain the expected length of response (Le). * This method should be used in place of the * setOutgoing() method by applets which need * to be compatible with legacy CAD/terminals which do not support ISO 7816-3/4 defined block chaining. * See Runtime Environment * Specification for the Java Card Platform, section 9.4 for details. *

    Notes.

      *
    • On a case 4 command, the setIncomingAndReceive() must * be invoked prior to calling this method. Otherwise, erroneous * behavior may result in T=0 protocol. *
    • Any remaining incoming data will be discarded. *
    • In T=0 (Case 4S) protocol, this method will return 256 with normal * semantics. *
    • In T=0 (Case 2E, 4S) protocol, this method will return 256 when * the currently selected applet implements the * javacardx.apdu.ExtendedLength interface. *
    • When this method is used, the waitExtension() method cannot be used. *
    • In T=1 protocol, retransmission on error may be restricted. *
    • In T=0 protocol, the outbound transfer must be performed * without using (ISO7816.SW_BYTES_REMAINING_00+count) response status chaining. *
    • In T=1 protocol, the outbound transfer must not set the More(M) Bit in the PCB of the I block. See ISO 7816-3. *
    • This method sets the state of the APDU object to * STATE_OUTGOING. *
    * * @return Le, the expected length of response data * @throws APDUException with the following reason codes:
      *
    • APDUException.ILLEGAL_USE if this method, or setOutgoingNoChaining() method already invoked. *
    • APDUException.IO_ERROR on I/O error. */ public short setOutgoingNoChaining() throws APDUException { if (flags[OUTGOING_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } flags[OUTGOING_FLAG] = true; flags[NO_CHAINING_FLAG] = true; ramVars[CURRENT_STATE] = STATE_OUTGOING; return getLe(); } /** * Sets the actual length of response data. If a length of * 0 is specified, no data will be output. *

      Note:

        *
      • In T=0 (Case 2&4) protocol, the length is used by the Java Card runtime environment to prompt the CAD for GET RESPONSE commands. *
      • This method sets the state of the * APDU object to * STATE_OUTGOING_LENGTH_KNOWN. *
      *

      * * @param len the length of response data * @throws APDUException with the following reason codes:

        *
      • APDUException.ILLEGAL_USE if setOutgoing() or setOutgoingNoChaining() not called * or if setOutgoingAndSend() already invoked, or this method already invoked. *
      • APDUException.BAD_LENGTH if any one of the following is true:
          *
        • len is negative. *
        • len is greater than 256 and the currently selected applet does not implement the javacardx.apdu.ExtendedLength interface. *
        • T=0 protocol is in use, non BLOCK CHAINED data transfer is requested and len is greater than 256. *
        • T=1 protocol is in use, non BLOCK CHAINED data transfer is requested and len is greater than (IFSD-2), where IFSD is the Outgoing Block Size. The -2 accounts for the status bytes in T=1. *
        *
      • APDUException.NO_T0_GETRESPONSE if T=0 protocol is in use and the CAD does not respond to (ISO7816.SW_BYTES_REMAINING_00+count) response status * with GET RESPONSE command on the same origin logical channel number as that of the current APDU command. *
      • APDUException.NO_T0_REISSUE if T=0 protocol * is in use and the CAD does not respond to (ISO7816.SW_CORRECT_LENGTH_00+count) response status by re-issuing same APDU command on the same origin * logical channel number as that of the current APDU command with the corrected length. *
      • APDUException.IO_ERROR on I/O error. * @see #getOutBlockSize() */ public void setOutgoingLength(short len) throws APDUException { if (!flags[OUTGOING_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } if (flags[OUTGOING_LEN_SET_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } if (len > 255 || len < 0) { APDUException.throwIt(APDUException.BAD_LENGTH); } flags[OUTGOING_LEN_SET_FLAG] = true; ramVars[CURRENT_STATE] = STATE_OUTGOING_LENGTH_KNOWN; ramVars[LR] = (byte) len; } public short receiveBytes(short bOff) throws APDUException { if (!flags[INCOMING_FLAG] || flags[OUTGOING_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } short Lc = (short) (ramVars[LC] & 0xff); if (bOff < 0 || Lc >= 1 && (short) (bOff + 1) > 260) { APDUException.throwIt(APDUException.BUFFER_BOUNDS); } short pre = (short) (ramVars[PRE_READ_LENGTH] & 0xff); if (pre != 0) { ramVars[PRE_READ_LENGTH]=(byte) 0; if (Lc == 0) { ramVars[CURRENT_STATE]= STATE_FULL_INCOMING; } else { ramVars[CURRENT_STATE]= STATE_PARTIAL_INCOMING; } return pre; } if (Lc != 0) { short len = 0; if(buffer[ISO7816.OFFSET_LC] != 0) { len = (short) (buffer[ISO7816.OFFSET_LC] & 0xff); } Lc -= len; ramVars[LC] = (byte) Lc; if (Lc == 0) { ramVars[CURRENT_STATE]= STATE_FULL_INCOMING; } else { ramVars[CURRENT_STATE] = STATE_PARTIAL_INCOMING; } return len; } else { ramVars[CURRENT_STATE]= STATE_FULL_INCOMING; return 0; } } /** * This is the primary receive method. * Calling this method indicates that this APDU has incoming data. This method gets as many bytes * as will fit without buffer overflow in the APDU buffer following the header. * It gets all the incoming bytes if they fit.

        * This method should only be called on a case 3 or case 4 command, otherwise erroneous behavior may result. *

        Notes: *

          *
        • In T=0 ( Case 3&4 ) protocol, the P3 param is assumed to be Lc. *
        • Data is read into the buffer at offset 5 for normal APDU semantics. *
        • Data is read into the buffer at offset 7 for an extended length APDU (Case 3E/4E). *
        • In T=1 protocol, if all the incoming bytes do not fit in the buffer, this method may * return less bytes than the maximum incoming block size (IFSC). *
        • In T=0 protocol, if all the incoming bytes do not fit in the buffer, this method may * return less than a full buffer of bytes to optimize and reduce protocol overhead. *
        • This method sets the transfer direction to be inbound * and calls receiveBytes(5) for normal semantics or receiveBytes(7) for extended semantics. *
        • This method may only be called once in a Applet.process() method. *
        • This method sets the state of the APDU object to * STATE_PARTIAL_INCOMING if all incoming bytes are not received. *
        • This method sets the state of the APDU object to * STATE_FULL_INCOMING if all incoming bytes are received. *
        * @return number of data bytes read. The Le byte, if any, is not included in the count. * Returns 0 if no bytes are available. * @throws APDUException with the following reason codes: *
          *
        • APDUException.ILLEGAL_USE if setIncomingAndReceive() already invoked or * if setOutgoing() or setOutgoingNoChaining() previously invoked. *
        • APDUException.IO_ERROR on I/O error. *
        • APDUException.T1_IFD_ABORT if T=1 protocol is in use and the CAD sends * in an ABORT S-Block command to abort the data transfer. *
        */ public short setIncomingAndReceive() throws APDUException { if (ramVars[PRE_READ_LENGTH] == 0) { if (flags[INCOMING_FLAG] || flags[OUTGOING_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } flags[INCOMING_FLAG] = true; byte Lc = (byte) (buffer[ISO7816.OFFSET_LC]); ramVars[LC] = Lc; ramVars[LE] = (byte) 0; } return receiveBytes(ISO7816.OFFSET_CDATA); } public void sendBytes(short bOff, short len) throws APDUException { if (bOff < 0 || len < 0 || (short) (bOff + len) > 255) { APDUException.throwIt(APDUException.BUFFER_BOUNDS); } if (!flags[OUTGOING_LEN_SET_FLAG] || flags[NO_GET_RESPONSE_FLAG]) { APDUException.throwIt(APDUException.ILLEGAL_USE); } if (len == 0) { return; } short Lr = getLr(); if (len > Lr) { APDUException.throwIt(APDUException.ILLEGAL_USE); } short Le = getLe(); SimulatorSystem.sendAPDU(buffer, bOff, len); bOff += len; Lr -= len; Le = Lr; if (Lr == 0) { ramVars[CURRENT_STATE] = STATE_FULL_OUTGOING; } else { ramVars[CURRENT_STATE] = STATE_PARTIAL_OUTGOING; } ramVars[LE] = (byte) Le; ramVars[LR] = (byte) Lr; } /** * Sends len more bytes from outData byte array starting at specified offset * bOff.

        If the last of the response is being sent by the invocation * of this method, the APDU buffer must not be altered. If the data is altered, incorrect output may be sent to * the CAD. * Requiring that the buffer not be altered allows the implementation to reduce protocol overhead * by transmitting the last part of the response along with the status bytes. *

        The Java Card runtime environment may use the APDU buffer to send data to the CAD. *

        Notes: *

          *
        • If setOutgoingNoChaining() was invoked, output block chaining must not be used. *
        • In T=0 protocol, if setOutgoingNoChaining() was invoked, Le bytes must be transmitted * before (ISO7816.SW_BYTES_REMAINING_00+remaining bytes) response status is returned. *
        • In T=0 protocol, if this method throws an APDUException with * NO_T0_GETRESPONSE or NO_T0_REISSUE reason code, * the Java Card runtime environment will restart APDU command processing using the newly received command. No more output * data can be transmitted. No error status response can be returned. *
        • In T=1 protocol, if this method throws an APDUException * with T1_IFD_ABORT reason code, the Java Card runtime environment will restart APDU command processing using the newly * received command. No more output data can be transmitted. No error status response can be returned. *
        • This method sets the state of the APDU object to * STATE_PARTIAL_OUTGOING if all outgoing bytes have not been sent. *
        • This method sets the state of the APDU object to * STATE_FULL_OUTGOING if all outgoing bytes have been sent. *
        * @param outData the source data byte array * @param bOff the offset into OutData array * @param len the byte length of the data to send * @throws APDUException with the following reason codes: *
          *
        • APDUException.ILLEGAL_USE if setOutgoingLength() not called * or setOutgoingAndSend() previously invoked * or response byte count exceeded or if APDUException.NO_T0_GETRESPONSE or * APDUException.NO_T0_REISSUE or APDUException.NO_T0_REISSUE * previously thrown. *
        • APDUException.IO_ERROR on I/O error. *
        • APDUException.NO_T0_GETRESPONSE if T=0 protocol is in use and * CAD does not respond to (ISO7816.SW_BYTES_REMAINING_00+count) response status * with GET RESPONSE command on the same origin logical channel number as that of the current * APDU command. *
        • APDUException.T1_IFD_ABORT if T=1 protocol is in use and the CAD sends * in an ABORT S-Block command to abort the data transfer. *
        * @throws SecurityException if the outData array is not accessible in the caller's context * @see #setOutgoing() * @see #setOutgoingNoChaining() */ public void sendBytesLong(byte outData[], short bOff, short len) throws APDUException, SecurityException { short sendLength = (short) buffer.length; while (len > 0) { if (len < sendLength) { sendLength = len; } Util.arrayCopy(outData, bOff, buffer, (short) 0, sendLength); sendBytes((short) 0, sendLength); len -= sendLength; bOff += sendLength; } } /** * This is the "convenience" send method. It provides for the most efficient way to send a short * response which fits in the buffer and needs the least protocol overhead. * This method is a combination of setOutgoing(), setOutgoingLength( len ) followed by * sendBytes ( bOff, len ). In addition, once this method is invoked, sendBytes() and * sendBytesLong() methods cannot be invoked and the APDU buffer must not be altered.

        * Sends len byte response from the APDU buffer starting at the specified offset bOff. *

        Notes: *

          *
        • No other APDU send methods can be invoked. *
        • The APDU buffer must not be altered. If the data is altered, incorrect output may be sent to * the CAD. *
        • The actual data transmission may only take place on return from Applet.process() *
        • This method sets the state of the APDU object to * STATE_FULL_OUTGOING. *
        * @param bOff the offset into APDU buffer * @param len the bytelength of the data to send * @throws APDUException ith the following reason codes: *
          *
        • APDUException.ILLEGAL_USE if setOutgoing() * or setOutgoingAndSend() previously invoked * or response byte count exceeded. *
        • APDUException.IO_ERROR on I/O error.
        */ public void setOutgoingAndSend(short bOff, short len) throws APDUException { setOutgoing(); setOutgoingLength(len); sendBytes(bOff, len); } /** * This method returns the current processing state of the * APDU object. It is used by the BasicService class to help * services collaborate in the processing of an incoming APDU command. * Valid codes are listed in STATE_ .. constants above. * @see #STATE_INITIAL * @return the current processing state of the APDU */ public byte getCurrentState() { return ramVars[CURRENT_STATE]; } /** * This method is called during the Applet.process(APDU) method * to obtain a reference to the current APDU object. * This method can only be called in the context of the currently selected applet. *

        Note: *

          *
        • Do not call this method directly or indirectly from within a method * invoked remotely via Java Card RMI method invocation from the client. The * APDU object and APDU buffer are reserved for use by RMIService. Remote * method parameter data may become corrupted. *
        * @return the current APDU object being processed * @throws SecurityException if *
          *
        • the current context is not the context of the currently selected applet instance or *
        • this method was not called, directly or indirectly, from the applet's * process method (called directly by the Java Card runtime environment), or *
        • the method is called during applet installation or deletion. *
        */ public static APDU getCurrentAPDU() throws SecurityException { return thisAPDU; } /** * This method is called during the Applet.process(APDU) method * to obtain a reference to the current APDU object. * This method can only be called in the context of the currently selected applet. *

        Note:

          *
        • Do not call this method directly or indirectly from within a method * invoked remotely via Java Card RMI method invocation from the client. The * APDU object and APDU buffer are reserved for use by RMIService. Remote * method parameter data may become corrupted. *
        * @return the APDU buffer of the APDU object being processed * @throws SecurityException if *
          *
        • the current context is not the context of the currently selected applet or *
        • this method was not called, directly or indirectly, from the applet's * process method (called directly by the Java Card runtime environment), or *
        • the method is called during applet installation or deletion. *
        */ public static byte[] getCurrentAPDUBuffer() throws SecurityException { return thisAPDU.getBuffer(); } /** * Returns the logical channel number associated with the current APDU command * based on the CLA byte. A number in the range 0-19 based on the CLA byte encoding * is returned if the command contains logical channel encoding. * If the command does not contain logical channel information, 0 is returned. * See Runtime * Specification for the Java Card Platform, section * 4.3 for encoding details. * @return logical channel number, if present, within the CLA byte, 0 otherwise */ public static byte getCLAChannel() { return thisAPDU.ramVars[LOGICAL_CHN]; } /** * Requests additional processing time from CAD. The implementation should ensure that this method * needs to be invoked only under unusual conditions requiring excessive processing times. *

        Notes: *

          *
        • In T=0 protocol, a NULL procedure byte is sent to reset the work waiting time (see ISO 7816-3). *
        • In T=1 protocol, the implementation needs to request the same T=0 protocol work waiting time quantum * by sending a T=1 protocol request for wait time extension(see ISO 7816-3). *
        • If the implementation uses an automatic timer mechanism instead, this method may do nothing. *
        * @throws APDUException with the following reason codes: *
          *
        • APDUException.ILLEGAL_USE if setOutgoingNoChaining() previously invoked. *
        • APDUException.IO_ERROR on I/O error.
        */ public static void waitExtension() throws APDUException { if (thisAPDU.flags[NO_CHAINING_FLAG]) { APDUException.throwIt((short) 1); } } /** * Returns whether the current * APDU command is the first or * part of a command chain. Bit b5 of the CLA byte if set, indicates * that the * APDU is the first or part of a chain of commands. * See Runtime Environment Specification for the Java Card Platform, section 4.3 for encoding details. * @return true if this APDU is not the last APDU of a command chain, false otherwise. * @since 2.2.2 */ public boolean isCommandChainingCLA() { return (buffer[ISO7816.OFFSET_CLA] & 0x10) == 0x10; } /** * Returns * true if the encoding of the current * APDU * command based on the * CLA byte indicates secure messaging. The secure messaging information * is in bits (b4,b3) for commands with origin channel numbers 0-3, and in bit * b6 for origin channel numbers 4-19. * See Runtime Environment Specification for the Java Card Platform, section 4.3 for encoding details. * @return true if the secure messaging bit(s) is(are) nonzero, false otherwise * @since 2.2.2 */ public boolean isSecureMessagingCLA() { return (buffer[ISO7816.OFFSET_CLA] & 0x40) == 0x40 ? (buffer[ISO7816.OFFSET_CLA] & 0x20) == 0x20 : (buffer[ISO7816.OFFSET_CLA] & 0x0C) != 0; } /** * Returns whether the current * APDU command CLA byte corresponds * to an interindustry command as defined in ISO 7816-4:2005 specification. * Bit b8 of the CLA byte if * 0, indicates that the * APDU * is an interindustry command. * @return true if this APDU CLA byte corresponds to an interindustry command, false otherwise. * @since 2.2.2 */ public boolean isISOInterindustryCLA() { return (buffer[ISO7816.OFFSET_CLA]& 0x80) != 0x80; } /** * Returns the incoming data length(Lc). This method can be invoked * whenever inbound data processing methods can be invoked during case 1, 3 or 4 * processing. It is most useful for an extended length enabled applet to avoid * parsing the variable length Lc format in the APDU header. * @return the incoming byte length indicated by the Lc field in the APDU header. Return 0 if no incoming data (Case 1) * @throws APDUException with the following reason codes:
          *
        • APDUException.ILLEGAL_USE if setIncomingAndReceive() not called * or if setOutgoing() or setOutgoingNoChaining() previously invoked. *
        * @see #getOffsetCdata() * @since 2.2.2 */ public short getIncomingLength() { // TODO ExtendedLength support return buffer[ISO7816.OFFSET_LC]; } /** * Returns the offset within the APDU buffer for incoming command data. * This method can be invoked whenever inbound data processing methods can be * invoked during case 1, 3 or 4 processing. It is most useful for an extended * length enabled applet to avoid parsing the variable length Lc format in the * APDU header. * * @return the offset within the APDU buffer for incoming command data from the previous call to setIncomingAndReceive() method. The value returned is either 5 (Lc is 1 byte), or 7 (when Lc is 3 bytes) * @throws APDUException with the following reason codes:
          *
        • APDUException.ILLEGAL_USE if setIncomingAndReceive() not called * or if setOutgoing() or setOutgoingNoChaining() previously invoked. *
        * @see #getIncomingLength() * @since 2.2.2 */ public short getOffsetCdata() { // TODO ExtendedLength support return ISO7816.OFFSET_CDATA; } // return Le variable private short getLe() { if (ramVars[LE] == 0) { return 256; } else { return (short) (ramVars[LE] & 0xff); } } // return Lr variable private short getLr() { return (short) (ramVars[LR] & 0xff); } /** * clear internal state of the APDU */ public void reset(){ Util.arrayFillNonAtomic(buffer, (short)0, (short) buffer.length, (byte)0); Util.arrayFillNonAtomic(ramVars, (short)0, (short) ramVars.length, (byte)0); for(byte i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy