From ff50f6d45ddb265e06fe275c1d4ad2cf1e4e5440 Mon Sep 17 00:00:00 2001 From: J08nY Date: Thu, 14 Mar 2019 17:29:43 +0100 Subject: Fix chunking. --- .gitignore | 4 + build-applet.xml | 1 - src/cz/crcs/ectester/applet/AppletBase.java | 42 +++++++---- .../ectester/applet/ECTesterAppletExtended.java | 2 + src/cz/crcs/ectester/reader/CardMngr.java | 85 ++++++++++------------ src/cz/crcs/ectester/reader/ECTesterReader.java | 2 + src/cz/crcs/ectester/reader/response/Response.java | 3 +- 7 files changed, 75 insertions(+), 64 deletions(-) diff --git a/.gitignore b/.gitignore index 4024180..3162005 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ /dist/*.degenerate /dist/*.edge-cases /dist/*.xml +/dist/*.yml # Built binaries in /src. /src/**/*.a @@ -34,3 +35,6 @@ /src/**/*.exp /src/**/*.lib /src/**/*.pdb + +# Python stuff +/util/__pycache__/ \ No newline at end of file diff --git a/build-applet.xml b/build-applet.xml index d74af6d..5c8da5c 100644 --- a/build-applet.xml +++ b/build-applet.xml @@ -23,7 +23,6 @@ - diff --git a/src/cz/crcs/ectester/applet/AppletBase.java b/src/cz/crcs/ectester/applet/AppletBase.java index 31ddbd9..7e79dd6 100644 --- a/src/cz/crcs/ectester/applet/AppletBase.java +++ b/src/cz/crcs/ectester/applet/AppletBase.java @@ -51,6 +51,7 @@ public abstract class AppletBase extends Applet { public static final short SW_KA_NULL = (short) 0x0ee4; public static final short SW_SIGNATURE_NULL = (short) 0x0ee5; public static final short SW_OBJECT_NULL = (short) 0x0ee6; + public static final short SW_CANNOT_FIT = (short) 0x0ee7; public static final short SW_Exception = (short) 0xff01; public static final short SW_ArrayIndexOutOfBoundsException = (short) 0xff02; public static final short SW_ArithmeticException = (short) 0xff03; @@ -67,6 +68,10 @@ public abstract class AppletBase extends Applet { public static final short BASE_221 = (short) 0x0221; public static final short BASE_222 = (short) 0x0222; + // + public static final short CDATA_BASIC = (short) 5; + public static final short CDATA_EXTENDED = (short) 7; + // public static final byte[] VERSION = {'v', '0', '.', '3', '.', '2'}; @@ -78,6 +83,7 @@ public abstract class AppletBase extends Applet { byte[] ramArray2 = null; byte[] apduArray = null; short apduEnd = 0; + short cdata = 0; RandomData randomData = null; @@ -99,7 +105,7 @@ public abstract class AppletBase extends Applet { */ short resetMemory = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_RESET); short deselectMemory = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT); - byte memoryType = (resetMemory > deselectMemory) ? JCSystem.CLEAR_ON_RESET : JCSystem.CLEAR_ON_DESELECT; + byte memoryType = (resetMemory >= deselectMemory) ? JCSystem.CLEAR_ON_RESET : JCSystem.CLEAR_ON_DESELECT; ramArray = JCSystem.makeTransientByteArray(ARRAY_LENGTH, memoryType); ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, memoryType); @@ -127,15 +133,24 @@ public abstract class AppletBase extends Applet { if (cla == CLA_ECTESTERAPPLET) { try { if (ins == INS_BUFFER) { - apduEnd += readAPDU(apdu, true); + short read = readAPDU(apdu, true); + if (read == -1) { + ISOException.throwIt(SW_CANNOT_FIT); + return; + } + apduEnd += read; apdu.setOutgoingAndSend((short) 0, (short) 0); return; } else { apduEnd = 0; if (ins == INS_PERFORM) { ins = apduArray[ISO7816.OFFSET_INS]; + apdu.setIncomingAndReceive(); } else { - readAPDU(apdu, false); + if (readAPDU(apdu, false) == -1) { + ISOException.throwIt(SW_CANNOT_FIT); + return; + } } } @@ -228,13 +243,19 @@ public abstract class AppletBase extends Applet { private short readAPDU(APDU apdu, boolean skipHeader) { byte[] apduBuffer = apdu.getBuffer(); - short cdataOffset = getOffsetCdata(apdu); /* How much stuff is in apduBuffer */ short read = apdu.setIncomingAndReceive(); + short cdataOffset = getOffsetCdata(apdu); read += cdataOffset; /* Where to start reading from? */ - short offset = skipHeader ? cdataOffset : 0; + short offset = 0; + if (skipHeader) { + offset = cdataOffset; + cdata = CDATA_EXTENDED; + } else { + cdata = CDATA_BASIC; + } /* How much stuff was really sent in this APDU? */ short total = (short) (getIncomingLength(apdu) + cdataOffset); @@ -268,7 +289,6 @@ public abstract class AppletBase extends Applet { * @return length of response */ private short insAllocateKA(APDU apdu) { - short cdata = getOffsetCdata(apdu); byte kaType = apduArray[cdata]; short sw = keyTester.allocateKA(kaType); Util.setShort(apdu.getBuffer(), (short) 0, sw); @@ -282,7 +302,6 @@ public abstract class AppletBase extends Applet { * @return length of response */ private short insAllocateSig(APDU apdu) { - short cdata = getOffsetCdata(apdu); byte sigType = apduArray[cdata]; short sw = keyTester.allocateSig(sigType); Util.setShort(apdu.getBuffer(), (short) 0, sw); @@ -301,7 +320,6 @@ public abstract class AppletBase extends Applet { */ private short insAllocate(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; - short cdata = getOffsetCdata(apdu); short keyLength = Util.getShort(apduArray, cdata); byte keyClass = apduArray[(short) (cdata + 2)]; @@ -347,7 +365,6 @@ public abstract class AppletBase extends Applet { private short insSet(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; byte curve = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); short params = Util.getShort(apduArray, cdata); short len = 0; @@ -375,7 +392,6 @@ public abstract class AppletBase extends Applet { private short insTransform(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; byte key = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); short params = Util.getShort(apduArray, cdata); short transformation = Util.getShort(apduArray, (short) (cdata + 2)); @@ -424,7 +440,6 @@ public abstract class AppletBase extends Applet { private short insExport(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; byte key = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); short params = Util.getShort(apduArray, cdata); short swOffset = 0; @@ -455,7 +470,6 @@ public abstract class AppletBase extends Applet { private short insECDH(APDU apdu) { byte pubkey = apduArray[ISO7816.OFFSET_P1]; byte privkey = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); byte export = apduArray[cdata]; short transformation = Util.getShort(apduArray, (short) (cdata + 1)); byte type = apduArray[(short) (cdata + 3)]; @@ -477,7 +491,6 @@ public abstract class AppletBase extends Applet { private short insECDH_direct(APDU apdu) { byte privkey = apduArray[ISO7816.OFFSET_P1]; byte export = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); short transformation = Util.getShort(apduArray, cdata); byte type = apduArray[(short) (cdata + 2)]; short length = Util.getShort(apduArray, (short) (cdata + 3)); @@ -499,7 +512,6 @@ public abstract class AppletBase extends Applet { private short insECDSA(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; byte export = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); byte sigType = apduArray[cdata]; short len = 0; @@ -524,7 +536,6 @@ public abstract class AppletBase extends Applet { private short insECDSA_sign(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; byte export = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); byte sigType = apduArray[cdata]; short len = 0; @@ -549,7 +560,6 @@ public abstract class AppletBase extends Applet { private short insECDSA_verify(APDU apdu) { byte keyPair = apduArray[ISO7816.OFFSET_P1]; byte sigType = apduArray[ISO7816.OFFSET_P2]; - short cdata = getOffsetCdata(apdu); short len = 0; if ((keyPair & KEYPAIR_LOCAL) != 0) { diff --git a/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java b/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java index c31544a..79ccf7b 100644 --- a/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java +++ b/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java @@ -27,6 +27,8 @@ package cz.crcs.ectester.applet; import javacard.framework.APDU; +import javacard.framework.CardRuntimeException; +import javacard.framework.ISO7816; import javacard.framework.ISOException; import javacardx.apdu.ExtendedLength; diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java index abbc440..87384c3 100644 --- a/src/cz/crcs/ectester/reader/CardMngr.java +++ b/src/cz/crcs/ectester/reader/CardMngr.java @@ -8,6 +8,7 @@ import javacard.framework.ISO7816; import javax.smartcardio.*; import java.util.*; +import java.util.function.Function; /** * @author Petr Svenda petr@svenda.com @@ -328,6 +329,39 @@ public class CardMngr { } } + private CommandAPDU chunk(CommandAPDU apdu) throws CardException { + if (verbose) { + System.out.print("Chunking:"); + } + byte[] data = apdu.getBytes(); + int numChunks = (data.length + 254) / 255; + for (int i = 0; i < numChunks; ++i) { + int chunkStart = i *255; + int chunkLength = 255; + if (chunkStart + chunkLength > data.length) { + chunkLength = data.length - chunkStart; + } + if (verbose) { + System.out.print(" " + chunkLength); + } + byte[] chunk = new byte[chunkLength]; + System.arraycopy(data, chunkStart, chunk, 0, chunkLength); + CommandAPDU cmd = new CommandAPDU(apdu.getCLA(), 0x7a, 0, 0, chunk); + ResponseAPDU resp; + if (simulate) { + resp = simulator.transmitCommand(cmd); + } else { + resp = channel.transmit(cmd); + } + if ((short) resp.getSW() != ISO7816.SW_NO_ERROR) { + throw new CardException("Chunking failed!"); + } + } + if (verbose) + System.out.println(); + return new CommandAPDU(apdu.getCLA(), 0x7b, 0, 0, 0xff); + } + public ResponseAPDU sendAPDU(CommandAPDU apdu) throws CardException { if (verbose) { System.out.println(">>>>"); @@ -338,31 +372,7 @@ public class CardMngr { long elapsed; if (chunking && apdu.getNc() >= 0xff) { - if (verbose) { - System.out.print("Chunking:"); - } - byte[] data = apdu.getBytes(); - int numChunks = (data.length + 254) / 255; - for (int i = 0; i < numChunks; ++i) { - int chunkStart = i *255; - int chunkLength = 255; - if (chunkStart + chunkLength > data.length) { - chunkLength = data.length - chunkStart; - } - if (verbose) { - System.out.print(" " + chunkLength); - } - byte[] chunk = new byte[chunkLength]; - System.arraycopy(data, chunkStart, chunk, 0, chunkLength); - CommandAPDU cmd = new CommandAPDU(apdu.getCLA(), 0x7a, 0, 0, chunk); - ResponseAPDU resp = channel.transmit(cmd); - if ((short) resp.getSW() != ISO7816.SW_NO_ERROR) { - return resp; - } - } - if (verbose) - System.out.println(); - apdu = new CommandAPDU(apdu.getCLA(), 0x7b, 0, 0, 0xff); + apdu = chunk(apdu); } elapsed = -System.nanoTime(); @@ -389,6 +399,7 @@ public class CardMngr { if (verbose) { System.out.println("<<<<"); System.out.println("Elapsed time (ms): " + elapsed / 1000000); + System.out.println("---------------------------------------------------------"); } return responseAPDU; } @@ -406,34 +417,16 @@ public class CardMngr { return simulator.selectApplet(appletAID); } - public ResponseAPDU sendAPDUSimulator(CommandAPDU apdu) { + public ResponseAPDU sendAPDUSimulator(CommandAPDU apdu) throws CardException { if (verbose) { System.out.println(">>>>"); System.out.println(apdu); System.out.println(ByteUtil.bytesToHex(apdu.getBytes())); } - /* if (chunking && apdu.getNc() >= 0xff) { - byte[] data = apdu.getBytes(); - int numChunks = (data.length + 254) / 255; - for (int i = 0; i < numChunks; ++i) { - int chunkStart = i *255; - int chunkLength = 255; - if (chunkStart + chunkLength > data.length) { - chunkLength = data.length - chunkStart; - } - byte[] chunk = new byte[chunkLength]; - System.arraycopy(data, chunkStart, chunk, 0, chunkLength); - CommandAPDU cmd = new CommandAPDU(apdu.getCLA(), 0x7a, 0, 0, chunk); - ResponseAPDU resp = simulator.transmitCommand(cmd); - if ((short) resp.getSW() != ISO7816.SW_NO_ERROR) { - return resp; - } - } - apdu = new CommandAPDU(apdu.getCLA(), 0x7b, 0, 0); + apdu = chunk(apdu); } - */ ResponseAPDU response = simulator.transmitCommand(apdu); byte[] responseBytes = response.getBytes(); @@ -447,7 +440,7 @@ public class CardMngr { return response; } - public ResponseAPDU sendAPDUSimulator(byte[] apdu) { + public ResponseAPDU sendAPDUSimulator(byte[] apdu) throws CardException { CommandAPDU commandAPDU = new CommandAPDU(apdu); return sendAPDUSimulator(commandAPDU); } diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java index ab21cd9..e0a8a24 100644 --- a/src/cz/crcs/ectester/reader/ECTesterReader.java +++ b/src/cz/crcs/ectester/reader/ECTesterReader.java @@ -140,6 +140,8 @@ public class ECTesterReader { if (!cardManager.prepareLocalSimulatorApplet(AID_221, INSTALL_DATA, ECTesterApplet.class)) { System.err.println(Colors.error("Failed to establish a simulator.")); System.exit(1); + } else { + cardManager.setChunking(true); } } else { if (!cardManager.connectToCardSelect()) { diff --git a/src/cz/crcs/ectester/reader/response/Response.java b/src/cz/crcs/ectester/reader/response/Response.java index 53a757b..f36d087 100644 --- a/src/cz/crcs/ectester/reader/response/Response.java +++ b/src/cz/crcs/ectester/reader/response/Response.java @@ -26,7 +26,7 @@ public abstract class Response { this.time = time; } - void parse(int numSW, int numParams) { + boolean parse(int numSW, int numParams) { this.numSW = numSW; this.sws = new short[numSW]; @@ -73,6 +73,7 @@ public abstract class Response { System.arraycopy(data, offset, params[i], 0, paramLength); offset += paramLength; } + return success; } public ResponseAPDU getAPDU() { -- cgit v1.2.3-70-g09d2