package aspects; import javacard.framework.APDU; import javacard.framework.ISO7816; import anoncard.util.Helpers; import anoncard.util.ResponseException; /** * This aspect makes the APDU class testable. It is only used for testing. * - add a new private variable "apduBuffer" to each APDU which can be set from the outside * - return this apduBuffer when calling apdu.getBuffer() * - Override the constructor to make it testable (the normal constructor throws exceptions when it is ran) * - override "setOutgoingAndSend" method to immediately return with an exception which contains the response. * This trick is needed to emulate the card behavior. * * @author christoph * */ public privileged aspect APDUAspect { /** * Add a new APDU buffer to the APDU class */ private byte[] APDU.apduBuffer; /** * Setter for the emulated apdu buffer. */ public void APDU.setBuffer(byte[] buffer) { apduBuffer = buffer; } /** * Constructor of APDU */ void around() : execution(APDU.new(..)) { // We don't want to do anything on construction } /** * Return the fake buffer. */ byte[] around(APDU apdu) : target(apdu) && call(byte[] getBuffer()) { return apdu.apduBuffer; } /** * Return the length of the fake buffer. */ short around(APDU apdu) : target(apdu) && call(short getIncomingLength()) { return (short) apdu.apduBuffer[ISO7816.OFFSET_LC]; } /** * Create ResponseException containing the response. */ void around(APDU apdu, short offset, short length) : target(apdu) && args(offset, length) && call(* setOutgoingAndSend(short, short) throws *) { byte[] response = new byte[length]; for (int i = 0; i < length; i++) { response[i] = apdu.getBuffer()[ISO7816.OFFSET_CDATA + i]; } throw new ResponseException(Helpers.makeResponse(response)); } }