aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJ08nY2019-03-13 17:50:56 +0100
committerJ08nY2019-03-13 17:50:56 +0100
commitdd620345feba56c413fcba1376c8a536033940b6 (patch)
tree9a0872ed38ef115ed3ddee07055450d03dcaa310 /src
parent26e5f00e782d3d060e3d78d34c16c405656f8c69 (diff)
downloadECTester-dd620345feba56c413fcba1376c8a536033940b6.tar.gz
ECTester-dd620345feba56c413fcba1376c8a536033940b6.tar.zst
ECTester-dd620345feba56c413fcba1376c8a536033940b6.zip
Diffstat (limited to 'src')
-rw-r--r--src/cz/crcs/ectester/applet/AppletBase.java59
-rw-r--r--src/cz/crcs/ectester/applet/ECTesterApplet.java4
-rw-r--r--src/cz/crcs/ectester/applet/ECTesterAppletExtended.java2
-rw-r--r--src/cz/crcs/ectester/reader/CardMngr.java74
-rw-r--r--src/cz/crcs/ectester/reader/ECTesterReader.java5
5 files changed, 118 insertions, 26 deletions
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);
diff --git a/src/cz/crcs/ectester/applet/ECTesterApplet.java b/src/cz/crcs/ectester/applet/ECTesterApplet.java
index 41bee9b..95009aa 100644
--- a/src/cz/crcs/ectester/applet/ECTesterApplet.java
+++ b/src/cz/crcs/ectester/applet/ECTesterApplet.java
@@ -1,6 +1,6 @@
/*
* ECTester, tool for testing Elliptic curve cryptography implementations.
- * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
+ * Copyright (c) 2016-2019 Petr Svenda <petr@svenda.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -53,7 +53,7 @@ public class ECTesterApplet extends AppletBase {
short getIncomingLength(APDU apdu) {
byte[] apduBuffer = apdu.getBuffer();
- return apduBuffer[ISO7816.OFFSET_LC];
+ return (short) (0xff & apduBuffer[ISO7816.OFFSET_LC]);
}
short getBase() {
diff --git a/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java b/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java
index 83e0851..8ddfeb9 100644
--- a/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java
+++ b/src/cz/crcs/ectester/applet/ECTesterAppletExtended.java
@@ -1,6 +1,6 @@
/*
* ECTester, tool for testing Elliptic curve cryptography implementations.
- * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
+ * Copyright (c) 2016-2019 Petr Svenda <petr@svenda.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java
index 8b6241d..5479f31 100644
--- a/src/cz/crcs/ectester/reader/CardMngr.java
+++ b/src/cz/crcs/ectester/reader/CardMngr.java
@@ -23,6 +23,7 @@ public class CardMngr {
private boolean simulate = false;
private boolean verbose = true;
+ private boolean extendedLength = false;
private final byte[] selectCM = {
(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0xa0, (byte) 0x00, (byte) 0x00,
@@ -51,6 +52,16 @@ public class CardMngr {
this.simulate = simulate;
}
+ private void connectWithHighest() throws CardException {
+ try {
+ card = terminal.connect("T=1");
+ } catch (CardException ex) {
+ if (verbose)
+ System.out.println("T=1 failed, trying protocol '*'");
+ card = terminal.connect("*");
+ }
+ }
+
public boolean connectToCard() throws CardException {
if (simulate)
return true;
@@ -72,13 +83,7 @@ public class CardMngr {
terminal = terminalList.get(i);
if (terminal.isCardPresent()) {
- try {
- card = terminal.connect("T=1");
- } catch (CardException ex) {
- if (verbose)
- System.out.println("T=1 failed, trying protocol '*'");
- card = terminal.connect("*");
- }
+ connectWithHighest();
if (verbose)
System.out.println("card: " + card);
@@ -132,7 +137,7 @@ public class CardMngr {
}
if (terminal != null) {
- card = terminal.connect("*");
+ connectWithHighest();
if (verbose)
System.out.println("card: " + card);
channel = card.getBasicChannel();
@@ -324,7 +329,36 @@ public class CardMngr {
System.out.println(ByteUtil.bytesToHex(apdu.getBytes()));
}
- long elapsed = -System.nanoTime();
+ long elapsed;
+ if (card.getProtocol().equals("T=0") && 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);
+ }
+
+ elapsed = -System.nanoTime();
ResponseAPDU responseAPDU = channel.transmit(apdu);
@@ -372,6 +406,28 @@ public class CardMngr {
System.out.println(ByteUtil.bytesToHex(apdu.getBytes()));
}
+ /*
+ if (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);
+ }
+ */
+
ResponseAPDU response = simulator.transmitCommand(apdu);
byte[] responseBytes = response.getBytes();
diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java
index 6372248..9447814 100644
--- a/src/cz/crcs/ectester/reader/ECTesterReader.java
+++ b/src/cz/crcs/ectester/reader/ECTesterReader.java
@@ -1,6 +1,6 @@
/*
* ECTester, tool for testing Elliptic curve cryptography implementations.
- * Copyright (c) 2016-2018 Petr Svenda <petr@svenda.com>
+ * Copyright (c) 2016-2019 Petr Svenda <petr@svenda.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -163,6 +163,9 @@ public class ECTesterReader {
Security.addProvider(new BouncyCastleProvider());
} catch (SecurityException | NoClassDefFoundError ignored) {
}
+ // Make BouncyCastle more lenient when we work with signatures in ASN.1 DER format,
+ // cards sometimes are not fully compliant.
+ System.setProperty("org.bouncycastle.asn1.allow_unsafe_integer", "true");
//do action
if (cli.hasOption("export")) {