diff options
| author | J08nY | 2019-03-13 17:50:56 +0100 |
|---|---|---|
| committer | J08nY | 2019-03-13 17:50:56 +0100 |
| commit | dd620345feba56c413fcba1376c8a536033940b6 (patch) | |
| tree | 9a0872ed38ef115ed3ddee07055450d03dcaa310 | |
| parent | 26e5f00e782d3d060e3d78d34c16c405656f8c69 (diff) | |
| download | ECTester-dd620345feba56c413fcba1376c8a536033940b6.tar.gz ECTester-dd620345feba56c413fcba1376c8a536033940b6.tar.zst ECTester-dd620345feba56c413fcba1376c8a536033940b6.zip | |
| -rw-r--r-- | LICENSE | 2 | ||||
| -rw-r--r-- | build-applet.xml | 2 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/AppletBase.java | 59 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECTesterApplet.java | 4 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/applet/ECTesterAppletExtended.java | 2 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/CardMngr.java | 74 | ||||
| -rw-r--r-- | src/cz/crcs/ectester/reader/ECTesterReader.java | 5 | ||||
| -rw-r--r-- | util/utils.py | 2 |
8 files changed, 121 insertions, 29 deletions
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016-2018 +Copyright (c) 2016-2019 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/build-applet.xml b/build-applet.xml index cfd95e6..84d399a 100644 --- a/build-applet.xml +++ b/build-applet.xml @@ -42,7 +42,7 @@ <target name="build-221" description="Builds the CAP file for JavaCard 2.2.1." unless="cap_extended"> <javacard jckit="${JC221}"> - <cap output="applet/ectester221.cap" sources="src/cz/crcs/ectester/applet" aid="${pkg_aid}" excludes="ECTesterAppletExtended.*"> + <cap verify="false" output="applet/ectester221.cap" sources="src/cz/crcs/ectester/applet" aid="${pkg_aid}" excludes="ECTesterAppletExtended.*"> <applet class="cz.crcs.ectester.applet.ECTesterApplet" aid="${applet_aid}"/> </cap> </javacard> 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")) { diff --git a/util/utils.py b/util/utils.py index bddfc35..664373f 100644 --- a/util/utils.py +++ b/util/utils.py @@ -21,7 +21,7 @@ def plot_hist(axes, data, xlabel=None, log=False): time_min = min(data) time_avg = np.average(data) time_median = np.median(data) - axes.hist(data, bins=time_max - time_min, log=log) + axes.hist(data, bins=time_max - time_min + 1, log=log, align="mid") axes.axvline(x=time_avg, alpha=0.7, linestyle="dotted", color="blue", label="avg = {}".format(time_avg)) axes.axvline(x=time_median, alpha=0.7, linestyle="dotted", color="green", label="median = {}".format(time_median)) axes.set_ylabel("count" + ("\n(log)" if log else "")) |
