From dd620345feba56c413fcba1376c8a536033940b6 Mon Sep 17 00:00:00 2001
From: J08nY
Date: Wed, 13 Mar 2019 17:50:56 +0100
Subject: Add custom command chaining to be able to test T=0 cards.
---
src/cz/crcs/ectester/applet/AppletBase.java | 59 ++++++++++++++++++++++-------
1 file changed, 46 insertions(+), 13 deletions(-)
(limited to 'src/cz/crcs/ectester/applet/AppletBase.java')
diff --git a/src/cz/crcs/ectester/applet/AppletBase.java b/src/cz/crcs/ectester/applet/AppletBase.java
index 199d76c..94f790b 100644
--- a/src/cz/crcs/ectester/applet/AppletBase.java
+++ b/src/cz/crcs/ectester/applet/AppletBase.java
@@ -3,6 +3,13 @@ package cz.crcs.ectester.applet;
import javacard.framework.*;
import javacard.security.*;
+/**
+ * Applet base class, that handles instructions, given
+ * either basic or extended length APDUs.
+ *
+ * @author Petr Svenda petr@svenda.com
+ * @author Jan Jancar johny@neuromancer.sk
+ */
public abstract class AppletBase extends Applet {
// MAIN INSTRUCTION CLASS
@@ -25,6 +32,8 @@ public abstract class AppletBase extends Applet {
public static final byte INS_ALLOCATE_SIG = (byte) 0x77;
public static final byte INS_GET_INFO = (byte) 0x78;
public static final byte INS_SET_DRY_RUN_MODE = (byte) 0x79;
+ public static final byte INS_BUFFER = (byte) 0x7a;
+ public static final byte INS_PERFORM = (byte) 0x7b;
// PARAMETERS for P1 and P2
public static final byte KEYPAIR_LOCAL = (byte) 0x01;
@@ -68,6 +77,7 @@ public abstract class AppletBase extends Applet {
byte[] ramArray = null;
byte[] ramArray2 = null;
byte[] apduArray = null;
+ short apduEnd = 0;
RandomData randomData = null;
@@ -113,7 +123,18 @@ public abstract class AppletBase extends Applet {
if (cla == CLA_ECTESTERAPPLET) {
try {
- readAPDU(apdu, apduArray, APDU_MAX_LENGTH);
+ if (ins == INS_BUFFER) {
+ apduEnd += readAPDU(apdu, true);
+ apdu.setOutgoingAndSend((short) 0, (short) 0);
+ return;
+ } else {
+ apduEnd = 0;
+ if (ins == INS_PERFORM) {
+ ins = apduArray[ISO7816.OFFSET_INS];
+ } else {
+ readAPDU(apdu, false);
+ }
+ }
short length = 0;
switch (ins) {
@@ -201,22 +222,34 @@ public abstract class AppletBase extends Applet {
} else ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
- private void readAPDU(APDU apdu, byte[] buffer, short length) {
+ 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();
- read += getOffsetCdata(apdu);
- short total = getIncomingLength(apdu);
- if (total > length) {
- return;
- }
+ read += cdataOffset;
- byte[] apduBuffer = apdu.getBuffer();
- short sum = 0;
+ /* Where to start reading from? */
+ short offset = skipHeader ? cdataOffset : 0;
+
+ /* How much stuff was really sent in this APDU? */
+ short total = (short) (getIncomingLength(apdu) + cdataOffset);
+ short todo = (short) (total - offset);
+ /* Can we fit? */
+ if (todo > (short) (apduArray.length - apduEnd)) {
+ return -1;
+ }
- do {
- Util.arrayCopyNonAtomic(apduBuffer, (short) 0, buffer, sum, read);
- sum += read;
+ /* How much stuff was copied over. */
+ short written = 0;
+ while (written < todo) {
+ Util.arrayCopyNonAtomic(apduBuffer, offset, apduArray, (short) (apduEnd + written), (short) (read - offset));
+ written += (short) (read - offset);
+ offset = 0;
read = apdu.receiveBytes((short) 0);
- } while (sum < total);
+ }
+ return written;
}
abstract short getOffsetCdata(APDU apdu);
--
cgit v1.2.3-70-g09d2
From f3accb655d349bb6d78fdc3c66a5d2d0cd15731d Mon Sep 17 00:00:00 2001
From: J08nY
Date: Thu, 14 Mar 2019 13:38:22 +0100
Subject: Add better chunking support and detect it at runtime.
---
build-applet.xml | 7 ++++---
src/cz/crcs/ectester/applet/AppletBase.java | 9 ++++++---
src/cz/crcs/ectester/applet/ECTesterApplet.java | 2 +-
.../ectester/applet/ECTesterAppletExtended.java | 2 +-
src/cz/crcs/ectester/reader/CardMngr.java | 13 ++++++++++---
src/cz/crcs/ectester/reader/ECTesterReader.java | 21 +++++++++++++--------
6 files changed, 35 insertions(+), 19 deletions(-)
(limited to 'src/cz/crcs/ectester/applet/AppletBase.java')
diff --git a/build-applet.xml b/build-applet.xml
index 84d399a..d74af6d 100644
--- a/build-applet.xml
+++ b/build-applet.xml
@@ -16,7 +16,8 @@
-
+
+
@@ -43,7 +44,7 @@
-
+
@@ -51,7 +52,7 @@
-
+
diff --git a/src/cz/crcs/ectester/applet/AppletBase.java b/src/cz/crcs/ectester/applet/AppletBase.java
index 94f790b..31ddbd9 100644
--- a/src/cz/crcs/ectester/applet/AppletBase.java
+++ b/src/cz/crcs/ectester/applet/AppletBase.java
@@ -97,10 +97,13 @@ public abstract class AppletBase extends Applet {
// go to proprietary data
dataOffset++;
*/
+ 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;
- ramArray = JCSystem.makeTransientByteArray(ARRAY_LENGTH, JCSystem.CLEAR_ON_RESET);
- ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, JCSystem.CLEAR_ON_RESET);
- apduArray = JCSystem.makeTransientByteArray(APDU_MAX_LENGTH, JCSystem.CLEAR_ON_RESET);
+ ramArray = JCSystem.makeTransientByteArray(ARRAY_LENGTH, memoryType);
+ ramArray2 = JCSystem.makeTransientByteArray(ARRAY_LENGTH, memoryType);
+ apduArray = JCSystem.makeTransientByteArray(APDU_MAX_LENGTH, memoryType);
randomData = RandomData.getInstance(RandomData.ALG_SECURE_RANDOM);
EC_Consts.randomData = randomData;
diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java
index 95009aa..b222d46 100644
--- a/src/cz/crcs/ectester/applet/ECTesterApplet.java
+++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java
@@ -22,7 +22,7 @@
*/
/*
* PACKAGEID: 4543546573746572
- * APPLETID: 45435465737465723031
+ * APPLETID: 454354657374657230333262 // VERSION v0.3.2
*/
package cz.crcs.ectester.applet;
diff --git a/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java b/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java
index 8ddfeb9..c31544a 100644
--- a/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java
+++ b/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java
@@ -22,7 +22,7 @@
*/
/*
* PACKAGEID: 4543546573746572
- * APPLETID: 45435465737465723031
+ * APPLETID: 454354657374657230333278 // VERSION v0.3.2
*/
package cz.crcs.ectester.applet;
diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java
index 5479f31..abbc440 100644
--- a/src/cz/crcs/ectester/reader/CardMngr.java
+++ b/src/cz/crcs/ectester/reader/CardMngr.java
@@ -23,7 +23,7 @@ public class CardMngr {
private boolean simulate = false;
private boolean verbose = true;
- private boolean extendedLength = false;
+ private boolean chunking = false;
private final byte[] selectCM = {
(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0xa0, (byte) 0x00, (byte) 0x00,
@@ -59,6 +59,9 @@ public class CardMngr {
if (verbose)
System.out.println("T=1 failed, trying protocol '*'");
card = terminal.connect("*");
+ if (card.getProtocol().equals("T=0")) {
+ chunking = true;
+ }
}
}
@@ -176,6 +179,10 @@ public class CardMngr {
}
}
+ public void setChunking(boolean state) {
+ chunking = state;
+ }
+
// Functions for CPLC taken and modified from https://github.com/martinpaljak/GlobalPlatformPro
private static final byte CLA_GP = (byte) 0x80;
private static final byte ISO7816_INS_GET_DATA = (byte) 0xCA;
@@ -330,7 +337,7 @@ public class CardMngr {
}
long elapsed;
- if (card.getProtocol().equals("T=0") && apdu.getNc() >= 0xff) {
+ if (chunking && apdu.getNc() >= 0xff) {
if (verbose) {
System.out.print("Chunking:");
}
@@ -407,7 +414,7 @@ public class CardMngr {
}
/*
- if (apdu.getNc() >= 0xff) {
+ if (chunking && apdu.getNc() >= 0xff) {
byte[] data = apdu.getBytes();
int numChunks = (data.length + 254) / 255;
for (int i = 0; i < numChunks; ++i) {
diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java
index 9447814..ab21cd9 100644
--- a/src/cz/crcs/ectester/reader/ECTesterReader.java
+++ b/src/cz/crcs/ectester/reader/ECTesterReader.java
@@ -81,9 +81,9 @@ public class ECTesterReader {
private static String CLI_HEADER;
private static String CLI_FOOTER = "\n" + LICENSE;
- private static final byte[] SELECT_ECTESTERAPPLET = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0a,
- (byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x31};
- private static final byte[] AID = {(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x31};
+ private static final byte[] SELECT_PREFIX = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0c};
+ private static final byte[] AID_221 = {(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x62}; // VERSION v0.3.2
+ private static final byte[] AID_222 = {(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72, (byte) 0x30, (byte) 0x33, (byte) 0x32, (byte) 0x78}; // VERSION v0.3.2
private static final byte[] INSTALL_DATA = new byte[10];
static {
@@ -137,7 +137,7 @@ public class ECTesterReader {
//connect or simulate connection
if (cfg.simulate) {
- if (!cardManager.prepareLocalSimulatorApplet(AID, INSTALL_DATA, ECTesterApplet.class)) {
+ if (!cardManager.prepareLocalSimulatorApplet(AID_221, INSTALL_DATA, ECTesterApplet.class)) {
System.err.println(Colors.error("Failed to establish a simulator."));
System.exit(1);
}
@@ -146,11 +146,16 @@ public class ECTesterReader {
System.err.println(Colors.error("Failed to connect to card."));
System.exit(1);
}
- ResponseAPDU selectResp = cardManager.send(SELECT_ECTESTERAPPLET);
+ ResponseAPDU selectResp = cardManager.send(ByteUtil.concatenate(SELECT_PREFIX, AID_222));
if ((short) selectResp.getSW() != ISO7816.SW_NO_ERROR) {
- System.err.println(Colors.error("Failed to select ECTester applet, is it installed?"));
- cardManager.disconnectFromCard();
- System.exit(1);
+ selectResp = cardManager.send(ByteUtil.concatenate(SELECT_PREFIX, AID_221));
+ if ((short) selectResp.getSW() != ISO7816.SW_NO_ERROR) {
+ System.err.println(Colors.error("Failed to select ECTester applet, is it installed?"));
+ cardManager.disconnectFromCard();
+ System.exit(1);
+ } else {
+ cardManager.setChunking(true);
+ }
}
}
--
cgit v1.2.3-70-g09d2
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(-)
(limited to 'src/cz/crcs/ectester/applet/AppletBase.java')
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