diff options
| author | J08nY | 2024-03-22 23:58:55 +0100 |
|---|---|---|
| committer | J08nY | 2024-03-25 14:52:43 +0100 |
| commit | 73af477a8774e1ede5dd8de6491eb353dc0b12bd (patch) | |
| tree | 2d4e3b19bc5fb55308b886032312be76341736d4 /src/cz/crcs/ectester/reader | |
| parent | 64b95fa059295e1dc23371c849f2302c1c18f5b4 (diff) | |
| download | ECTester-73af477a8774e1ede5dd8de6491eb353dc0b12bd.tar.gz ECTester-73af477a8774e1ede5dd8de6491eb353dc0b12bd.tar.zst ECTester-73af477a8774e1ede5dd8de6491eb353dc0b12bd.zip | |
Basic Gradle setup.
Diffstat (limited to 'src/cz/crcs/ectester/reader')
26 files changed, 0 insertions, 5547 deletions
diff --git a/src/cz/crcs/ectester/reader/CardMngr.java b/src/cz/crcs/ectester/reader/CardMngr.java deleted file mode 100644 index 0a01d9e..0000000 --- a/src/cz/crcs/ectester/reader/CardMngr.java +++ /dev/null @@ -1,478 +0,0 @@ -package cz.crcs.ectester.reader; - -import com.licel.jcardsim.io.JavaxSmartCardInterface; -import cz.crcs.ectester.common.util.ByteUtil; -import javacard.framework.AID; -import javacard.framework.Applet; -import javacard.framework.ISO7816; - -import javax.smartcardio.*; -import java.util.*; - -/** - * @author Petr Svenda petr@svenda.com - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardMngr { - private CardTerminal terminal = null; - private CardChannel channel = null; - private Card card = null; - - // Simulator related attributes - private JavaxSmartCardInterface simulator = null; - - private boolean simulate = false; - private boolean verbose = true; - private boolean chunking = false; - - private final byte[] selectCM = { - (byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x07, (byte) 0xa0, (byte) 0x00, (byte) 0x00, - (byte) 0x00, (byte) 0x18, (byte) 0x43, (byte) 0x4d}; - - public static final byte OFFSET_CLA = 0x00; - public static final byte OFFSET_INS = 0x01; - public static final byte OFFSET_P1 = 0x02; - public static final byte OFFSET_P2 = 0x03; - public static final byte OFFSET_LC = 0x04; - public static final byte OFFSET_DATA = 0x05; - public static final byte HEADER_LENGTH = 0x05; - - public static final short DATA_RECORD_LENGTH = (short) 0x80; // 128B per record - public static final short NUMBER_OF_RECORDS = (short) 0x0a; // 10 records - - public CardMngr() { - } - - public CardMngr(boolean verbose) { - this.verbose = verbose; - } - - public CardMngr(boolean verbose, boolean simulate) { - this(verbose); - 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("*"); - if (card.getProtocol().equals("T=0")) { - chunking = true; - } - } - } - - public boolean connectToCard() throws CardException { - if (simulate) - return true; - - // TRY ALL READERS, FIND FIRST SELECTABLE - List<CardTerminal> terminalList = getReaderList(); - - if (terminalList == null || terminalList.isEmpty()) { - System.err.println("No terminals found"); - return false; - } - - //List numbers of Card readers - boolean cardFound = false; - for (int i = 0; i < terminalList.size(); i++) { - - if (verbose) - System.out.println(i + " : " + terminalList.get(i)); - - terminal = terminalList.get(i); - if (terminal.isCardPresent()) { - connectWithHighest(); - - if (verbose) - System.out.println("card: " + card); - channel = card.getBasicChannel(); - - //reset the card - if (verbose) - System.out.println(ByteUtil.bytesToHex(card.getATR().getBytes())); - - cardFound = true; - } - } - - return cardFound; - } - - public boolean connectToCardSelect() throws CardException { - if (simulate) - return true; - - // Test available card - if more present, let user to select one - List<CardTerminal> terminalList = CardMngr.getReaderList(); - if (terminalList == null || terminalList.isEmpty()) { - System.err.println("ERROR: No suitable reader with card detected. Please check your reader connection"); - return false; - } else { - if (terminalList.size() == 1) { - terminal = terminalList.get(0); // return first and only reader - } else { - int terminalIndex = 1; - // Let user select target terminal - for (CardTerminal terminal : terminalList) { - Card card; - try { - card = terminal.connect("*"); - ATR atr = card.getATR(); - System.out.println(terminalIndex + " : " + terminal.getName() + " - " + ByteUtil.bytesToHex(atr.getBytes())); - terminalIndex++; - } catch (CardException ex) { - ex.printStackTrace(System.out); - } - } - System.out.print("Select index of target reader you like to use 1.." + (terminalIndex - 1) + ": "); - Scanner sc = new Scanner(System.in); - int answ = sc.nextInt(); - System.out.println(String.format("%d", answ)); - answ--; // is starting with 0 - // BUGBUG; verify allowed index range - terminal = terminalList.get(answ); - } - } - - if (terminal != null) { - connectWithHighest(); - if (verbose) - System.out.println("card: " + card); - channel = card.getBasicChannel(); - } - - return true; - } - - public boolean reconnectToCard(byte[] selectAPDU) throws CardException { - if (simulate) - return true; - - if (connected()) { - disconnectFromCard(); - } - - boolean result = connectToCard(); - if (result) { - // Select our application on card - send(selectAPDU); - } - return result; - } - - public boolean connected() { - return simulate || card != null; - } - - public void disconnectFromCard() throws CardException { - if (simulate) - return; - - if (card != null) { - card.disconnect(false); - card = null; - } - } - - public void setChunking(boolean state) { - chunking = state; - } - - public String getProtocol() { - if (simulate) { - return simulator.getProtocol(); - } else { - if (card != null) { - return card.getProtocol(); - } else { - return null; - } - } - } - - // 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; - private static final byte[] FETCH_GP_CPLC_APDU = {CLA_GP, ISO7816_INS_GET_DATA, (byte) 0x9F, (byte) 0x7F, (byte) 0x00}; - private static final byte[] FETCH_ISO_CPLC_APDU = {ISO7816.CLA_ISO7816, ISO7816_INS_GET_DATA, (byte) 0x9F, (byte) 0x7F, (byte) 0x00}; - private static final byte[] FETCH_GP_CARDDATA_APDU = {CLA_GP, ISO7816_INS_GET_DATA, (byte) 0x00, (byte) 0x66, (byte) 0x00}; - - public byte[] fetchCPLC() throws CardException { - // Try CPLC via GP - ResponseAPDU resp = send(FETCH_GP_CPLC_APDU); - // If GP CLA fails, try with ISO - if (resp.getSW() == (ISO7816.SW_CLA_NOT_SUPPORTED & 0xffff)) { - resp = send(FETCH_ISO_CPLC_APDU); - } - if (resp.getSW() == (ISO7816.SW_NO_ERROR & 0xffff)) { - return resp.getData(); - } - return null; - } - - public static final class CPLC { - public enum Field { - ICFabricator, - ICType, - OperatingSystemID, - OperatingSystemReleaseDate, - OperatingSystemReleaseLevel, - ICFabricationDate, - ICSerialNumber, - ICBatchIdentifier, - ICModuleFabricator, - ICModulePackagingDate, - ICCManufacturer, - ICEmbeddingDate, - ICPrePersonalizer, - ICPrePersonalizationEquipmentDate, - ICPrePersonalizationEquipmentID, - ICPersonalizer, - ICPersonalizationDate, - ICPersonalizationEquipmentID - } - - private Map<Field, byte[]> values = new TreeMap<>(); - - public CPLC(byte[] data) { - if (data == null) { - return; - } - if (data.length < 3 || data[2] != 0x2A) { - throw new IllegalArgumentException("CPLC must be 0x2A bytes long"); - } - //offset = TLVUtils.skipTag(data, offset, (short)0x9F7F); - short offset = 3; - values.put(Field.ICFabricator, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICType, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.OperatingSystemID, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.OperatingSystemReleaseDate, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.OperatingSystemReleaseLevel, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICFabricationDate, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICSerialNumber, Arrays.copyOfRange(data, offset, offset + 4)); - offset += 4; - values.put(Field.ICBatchIdentifier, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICModuleFabricator, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICModulePackagingDate, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICCManufacturer, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICEmbeddingDate, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICPrePersonalizer, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICPrePersonalizationEquipmentDate, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICPrePersonalizationEquipmentID, Arrays.copyOfRange(data, offset, offset + 4)); - offset += 4; - values.put(Field.ICPersonalizer, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICPersonalizationDate, Arrays.copyOfRange(data, offset, offset + 2)); - offset += 2; - values.put(Field.ICPersonalizationEquipmentID, Arrays.copyOfRange(data, offset, offset + 4)); - offset += 4; - } - - public Map<Field, byte[]> values() { - return values; - } - } - - public ATR getATR() { - if (simulate) { - return new ATR(simulator.getATR()); - } else { - if (card != null) { - return card.getATR(); - } else { - return null; - } - } - } - - public CPLC getCPLC() throws CardException { - byte[] data = fetchCPLC(); - return new CPLC(data); - } - - public static String mapCPLCField(CPLC.Field field, byte[] value) { - switch (field) { - case ICFabricator: - String id = ByteUtil.bytesToHex(value, false); - String fabricatorName = "unknown"; - if (id.equals("3060")) { - fabricatorName = "Renesas"; - } - if (id.equals("4090")) { - fabricatorName = "Infineon"; - } - if (id.equals("4180")) { - fabricatorName = "Atmel"; - } - if (id.equals("4250")) { - fabricatorName = "Samsung"; - } - if (id.equals("4790")) { - fabricatorName = "NXP"; - } - return id + " (" + fabricatorName + ")"; - default: - return ByteUtil.bytesToHex(value, false); - } - } - - - public static List<CardTerminal> getReaderList() { - try { - TerminalFactory factory = TerminalFactory.getDefault(); - return factory.terminals().list(); - } catch (CardException ex) { - System.err.println("Exception : " + ex); - return null; - } - } - - 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(">>>>"); - System.out.println(apdu); - - System.out.println(ByteUtil.bytesToHex(apdu.getBytes())); - } - - long elapsed; - if (chunking && apdu.getNc() >= 0xff) { - apdu = chunk(apdu); - } - - elapsed = -System.nanoTime(); - - ResponseAPDU responseAPDU = channel.transmit(apdu); - - elapsed += System.nanoTime(); - - if (verbose) { - System.out.println(responseAPDU); - System.out.println(ByteUtil.bytesToHex(responseAPDU.getBytes())); - } - - if (responseAPDU.getSW1() == (byte) 0x61) { - CommandAPDU apduToSend = new CommandAPDU((byte) 0x00, - (byte) 0xC0, (byte) 0x00, (byte) 0x00, - responseAPDU.getSW2()); - - responseAPDU = channel.transmit(apduToSend); - if (verbose) - System.out.println(ByteUtil.bytesToHex(responseAPDU.getBytes())); - } - - if (verbose) { - System.out.println("<<<<"); - System.out.println("Elapsed time (ms): " + elapsed / 1000000); - System.out.println("---------------------------------------------------------"); - } - return responseAPDU; - } - - public ResponseAPDU sendAPDU(byte[] apdu) throws CardException { - CommandAPDU commandAPDU = new CommandAPDU(apdu); - return sendAPDU(commandAPDU); - } - - public boolean prepareLocalSimulatorApplet(byte[] appletAIDArray, byte[] installData, Class<? extends Applet> appletClass) { - simulator = new JavaxSmartCardInterface(); - AID appletAID = new AID(appletAIDArray, (short) 0, (byte) appletAIDArray.length); - - simulator.installApplet(appletAID, appletClass, installData, (short) 0, (byte) installData.length); - return simulator.selectApplet(appletAID); - } - - 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) { - apdu = chunk(apdu); - } - - ResponseAPDU response = simulator.transmitCommand(apdu); - byte[] responseBytes = response.getBytes(); - - if (verbose) { - System.out.println(response); - System.out.println(ByteUtil.bytesToHex(responseBytes)); - System.out.println("<<<<"); - } - - return response; - } - - public ResponseAPDU sendAPDUSimulator(byte[] apdu) throws CardException { - CommandAPDU commandAPDU = new CommandAPDU(apdu); - return sendAPDUSimulator(commandAPDU); - } - - public ResponseAPDU send(CommandAPDU apdu) throws CardException { - ResponseAPDU response; - if (simulate) { - response = sendAPDUSimulator(apdu); - } else { - response = sendAPDU(apdu); - } - return response; - } - - public ResponseAPDU send(byte[] apdu) throws CardException { - CommandAPDU commandAPDU = new CommandAPDU(apdu); - return send(commandAPDU); - } -} diff --git a/src/cz/crcs/ectester/reader/ECTesterReader.java b/src/cz/crcs/ectester/reader/ECTesterReader.java deleted file mode 100644 index fdfb4cb..0000000 --- a/src/cz/crcs/ectester/reader/ECTesterReader.java +++ /dev/null @@ -1,1104 +0,0 @@ -/* - * ECTester, tool for testing Elliptic curve cryptography implementations. - * Copyright (c) 2016-2019 Petr Svenda <petr@svenda.com> - * Copyright (c) 2016-2019 Jan Jancar <johny@neuromancer.sk> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package cz.crcs.ectester.reader; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.cli.CLITools; -import cz.crcs.ectester.common.cli.Colors; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.output.OutputLogger; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.util.Util; -import cz.crcs.ectester.common.util.*; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.output.FileTestWriter; -import cz.crcs.ectester.reader.output.ResponseWriter; -import cz.crcs.ectester.reader.response.Response; -import cz.crcs.ectester.reader.test.*; -import javacard.framework.ISO7816; -import javacard.security.KeyPair; -import org.apache.commons.cli.*; -import org.bouncycastle.jce.provider.BouncyCastleProvider; - -import javax.smartcardio.CardException; -import javax.smartcardio.ResponseAPDU; -import javax.xml.parsers.ParserConfigurationException; -import java.io.*; -import java.math.BigInteger; -import java.net.URL; -import java.nio.file.Files; -import java.security.Security; -import java.security.spec.ECParameterSpec; -import java.util.*; -import java.util.jar.Manifest; - -import static cz.crcs.ectester.applet.EC_Consts.KeyAgreement_ALG_EC_SVDP_DH; -import static cz.crcs.ectester.applet.EC_Consts.Signature_ALG_ECDSA_SHA; - -/** - * Reader part of ECTester, a tool for testing Elliptic curve support on javacards. - * - * @author Petr Svenda petr@svenda.com - * @author Jan Jancar johny@neuromancer.sk - * @version v0.3.3 - */ -public class ECTesterReader { - private CardMngr cardManager; - private OutputLogger logger; - private ResponseWriter respWriter; - private Config cfg; - - private Options opts = new Options(); - public static final String VERSION = "v0.3.3"; - public static String GIT_COMMIT = ""; - private static String DESCRIPTION; - private static String LICENSE = "MIT Licensed\nCopyright © 2016-2019 Petr Svenda <petr@svenda.com>\nCopyright © 2016-2019 Jan Jancar <johny@neuromancer.sk>"; - private static String CLI_HEADER; - private static String CLI_FOOTER = "\n" + LICENSE; - - private static final byte[] SELECT_PREFIX = {(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x00, (byte) 0x0c}; - private static final byte[] AID_PREFIX = {(byte) 0x45, (byte) 0x43, (byte) 0x54, (byte) 0x65, (byte) 0x73, (byte) 0x74, (byte) 0x65, (byte) 0x72}; - private static final byte[] AID_CURRENT_VERSION = {(byte) 0x30, (byte) 0x33, (byte) 0x33}; // VERSION v0.3.3 - private static final byte[] AID_SUFFIX_221 = {(byte) 0x62}; - private static final byte[] AID_SUFFIX_222 = {(byte) 0x78}; - private static final byte[] INSTALL_DATA = new byte[10]; - private static final int TRY_VERSIONS = 10; - - static { - ClassLoader cl = ECTesterReader.class.getClassLoader(); - try { - URL url = cl.getResource("META-INF/MANIFEST.MF"); - Manifest manifest = new Manifest(url.openStream()); - String commit = manifest.getMainAttributes().getValue("Git-Commit"); - GIT_COMMIT = (commit == null) ? "" : "(git " + commit + ")"; - } catch (Exception ignored) { - } - - DESCRIPTION = "ECTesterReader " + VERSION + GIT_COMMIT + ", a javacard Elliptic Curve Cryptography support tester/utility."; - CLI_HEADER = "\n" + DESCRIPTION + "\n\n"; - } - - private void run(String[] args) { - try { - CommandLine cli = parseArgs(args); - - cfg = new Config(); - boolean optsOk = cfg.readOptions(cli); - - //if help, print and quit - if (cli.hasOption("help")) { - CLITools.help("ECTesterReader.jar", CLI_HEADER, opts, CLI_FOOTER, true); - return; - } else if (cli.hasOption("version")) { - CLITools.version(DESCRIPTION, LICENSE); - return; - } - - //if opts failed, quit - if (!optsOk) { - return; - } - - //if list, print and quit - if (cli.hasOption("list-named")) { - CLITools.listNamed(EC_Store.getInstance(), cli.getOptionValue("list-named")); - return; - } - - if (cli.hasOption("list-suites")) { - listSuites(); - return; - } - - //init CardManager - cardManager = new CardMngr(cfg.verbose, cfg.simulate); - - //connect or simulate connection - if (cfg.simulate) { - if (!cardManager.prepareLocalSimulatorApplet(ByteUtil.concatenate(AID_PREFIX, AID_CURRENT_VERSION, AID_SUFFIX_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()) { - System.err.println(Colors.error("Failed to connect to card.")); - System.exit(1); - } - //Try the highest known version first - byte[] versionByte = AID_CURRENT_VERSION.clone(); - boolean selected = false; - for (int i = 0; i < TRY_VERSIONS; ++i) { - byte[] select222 = ByteUtil.concatenate(SELECT_PREFIX, AID_PREFIX, versionByte, AID_SUFFIX_222); - ResponseAPDU selectResp = cardManager.send(select222); - if ((short) selectResp.getSW() != ISO7816.SW_NO_ERROR) { - byte[] select221 = ByteUtil.concatenate(SELECT_PREFIX, AID_PREFIX, versionByte, AID_SUFFIX_221); - selectResp = cardManager.send(select221); - if ((short) selectResp.getSW() == ISO7816.SW_NO_ERROR) { - cardManager.setChunking(true); - selected = true; - break; - } - } else { - selected = true; - break; - } - // Count down by versions - if (versionByte[2] == 0x30) { - if (versionByte[1] == 0x30) { - if (versionByte[0] == 0x30) { - break; - } else { - versionByte[0]--; - versionByte[1] = 0x39; - versionByte[2] = 0x39; - } - } else { - versionByte[1]--; - versionByte[2] = 0x39; - } - } else { - versionByte[2]--; - } - } - if (!selected) { - System.err.println(Colors.error("Failed to select ECTester applet, is it installed?")); - cardManager.disconnectFromCard(); - System.exit(1); - } - } - - // Setup logger and respWriter - logger = new OutputLogger(true, cfg.log); - respWriter = new ResponseWriter(logger.getPrintStream()); - - // Try adding the BouncyCastleProvider, which might be used in some parts of ECTester. - try { - 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")) { - export(); - } else if (cli.hasOption("generate")) { - generate(); - } else if (cli.hasOption("test")) { - test(); - } else if (cli.hasOption("ecdh") || cli.hasOption("ecdhc")) { - ecdh(); - } else if (cli.hasOption("ecdsa")) { - ecdsa(); - } else if (cli.hasOption("info")) { - info(); - } - - //disconnect - cardManager.disconnectFromCard(); - logger.close(); - - } catch (MissingOptionException moex) { - System.err.println(Colors.error("Missing required options, one of:")); - for (Object opt : moex.getMissingOptions().toArray()) { - if (opt instanceof OptionGroup) { - for (Option o : ((OptionGroup) opt).getOptions()) { - System.err.print("-" + o.getOpt()); - - if (o.hasLongOpt()) { - System.err.print("\t/ --" + o.getLongOpt() + " "); - } - - if (o.hasArg()) { - if (o.hasOptionalArg()) { - System.err.print("[" + o.getArgName() + "] "); - } else { - System.err.print("<" + o.getArgName() + "> "); - } - } - - if (o.getDescription() != null) { - System.err.print("\t\t\t" + o.getDescription()); - } - System.err.println(); - } - } else if (opt instanceof String) { - System.err.println(opt); - } - } - } catch (MissingArgumentException maex) { - System.err.println(Colors.error("Option, " + maex.getOption().getOpt() + " requires an argument: " + maex.getOption().getArgName())); - } catch (NumberFormatException nfex) { - System.err.println(Colors.error("Not a number. " + nfex.getMessage())); - } catch (FileNotFoundException fnfe) { - System.err.println(Colors.error("File " + fnfe.getMessage() + " not found.")); - } catch (ParseException | IOException ex) { - System.err.println(Colors.error(ex.getMessage())); - } catch (CardException ex) { - if (logger != null) - logger.println(ex.getMessage()); - ex.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } finally { - if (logger != null) - logger.flush(); - } - } - - /** - * Parses command-line options. - * - * @param args cli arguments - * @return parsed CommandLine object - * @throws ParseException if there are any problems encountered while parsing the command line tokens - */ - private CommandLine parseArgs(String[] args) throws ParseException { - OptionGroup actions = new OptionGroup(); - actions.setRequired(true); - actions.addOption(Option.builder("V").longOpt("version").desc("Print version info.").build()); - actions.addOption(Option.builder("h").longOpt("help").desc("Print help.").build()); - actions.addOption(Option.builder("ln").longOpt("list-named").desc("Print the list of supported named curves and keys.").hasArg().argName("what").optionalArg(true).build()); - actions.addOption(Option.builder("ls").longOpt("list-suites").desc("List supported test suites.").build()); - actions.addOption(Option.builder("e").longOpt("export").desc("Export the defaut curve parameters of the card(if any).").build()); - actions.addOption(Option.builder("g").longOpt("generate").desc("Generate <amount> of EC keys.").hasArg().argName("amount").optionalArg(true).build()); - actions.addOption(Option.builder("t").longOpt("test").desc("Test ECC support. Optionally specify a test number to run only a part of a test suite. <test_suite>:\n- default\n- compression\n- invalid\n- twist\n- degenerate\n- cofactor\n- wrong\n- signature\n- composite\n- test-vectors\n- edge-cases\n- miscellaneous").hasArg().argName("test_suite[:from[:to]]").optionalArg(true).build()); - actions.addOption(Option.builder("dh").longOpt("ecdh").desc("Do EC KeyAgreement (ECDH...), [count] times.").hasArg().argName("count").optionalArg(true).build()); - actions.addOption(Option.builder("dsa").longOpt("ecdsa").desc("Sign data with ECDSA, [count] times.").hasArg().argName("count").optionalArg(true).build()); - actions.addOption(Option.builder("nf").longOpt("info").desc("Get applet info.").build()); - - opts.addOptionGroup(actions); - - opts.addOption(Option.builder("b").longOpt("bit-size").desc("Set curve size.").hasArg().argName("bits").build()); - opts.addOption(Option.builder("fp").longOpt("prime-field").desc("Use a prime field.").build()); - opts.addOption(Option.builder("f2m").longOpt("binary-field").desc("Use a binary field.").build()); - - OptionGroup curve = new OptionGroup(); - curve.addOption(Option.builder("nc").longOpt("named-curve").desc("Use a named curve, from CurveDB: <cat/id>").hasArg().argName("cat/id").build()); - curve.addOption(Option.builder("c").longOpt("curve").desc("Use curve from file <curve_file> (field,a,b,gx,gy,r,k).").hasArg().argName("curve_file").build()); - curve.addOption(Option.builder("u").longOpt("custom").desc("Use a custom curve (applet-side embedded, SECG curves).").build()); - opts.addOptionGroup(curve); - - OptionGroup pub = new OptionGroup(); - pub.addOption(Option.builder("npub").longOpt("named-public").desc("Use public key from KeyDB: <cat/id>").hasArg().argName("cat/id").build()); - pub.addOption(Option.builder("pub").longOpt("public").desc("Use public key from file <pubkey_file> (wx,wy).").hasArg().argName("pubkey_file").build()); - opts.addOptionGroup(pub); - - OptionGroup priv = new OptionGroup(); - priv.addOption(Option.builder("npriv").longOpt("named-private").desc("Use private key from KeyDB: <cat/id>").hasArg().argName("cat/id").build()); - priv.addOption(Option.builder("priv").longOpt("private").desc("Use private key from file <privkey_file> (s).").hasArg().argName("privkey_file").build()); - opts.addOptionGroup(priv); - - OptionGroup key = new OptionGroup(); - key.addOption(Option.builder("nk").longOpt("named-key").desc("Use keyPair from KeyDB: <cat/id>").hasArg().argName("cat/id").build()); - key.addOption(Option.builder("k").longOpt("key").desc("Use keyPair from file <key_file> (wx,wy,s).").hasArg().argName("key_file").build()); - opts.addOptionGroup(key); - - opts.addOption(Option.builder("i").longOpt("input").desc("Input from file <input_file>, for ECDSA signing.").hasArg().argName("input_file").build()); - opts.addOption(Option.builder("o").longOpt("output").desc("Output into file <output_file>. The file can be prefixed by the format (one of text,yml,xml), such as: xml:<output_file>.").hasArgs().argName("output_file").build()); - opts.addOption(Option.builder("l").longOpt("log").desc("Log output into file [log_file].").hasArg().argName("log_file").optionalArg(true).build()); - opts.addOption(Option.builder("v").longOpt("verbose").desc("Turn on verbose logging.").build()); - opts.addOption(Option.builder().longOpt("format").desc("Output format to use. One of: text,yml,xml.").hasArg().argName("format").build()); - - opts.addOption(Option.builder("kb").longOpt("key-builder").desc("Allocate KeyPair using KeyBuilder.").build()); - opts.addOption(Option.builder().longOpt("fixed").desc("Generate key(s) only once, keep them for later operations.").build()); - opts.addOption(Option.builder().longOpt("fixed-private").desc("Generate private key only once, keep it for later ECDH.").build()); - opts.addOption(Option.builder().longOpt("fixed-public").desc("Generate public key only once, keep it for later ECDH.").build()); - opts.addOption(Option.builder("f").longOpt("fresh").desc("Generate fresh keys (set domain parameters before every generation).").build()); - opts.addOption(Option.builder().longOpt("time").desc("Output better timing values, by running command in dry run mode and normal mode, and subtracting the two.").build()); - opts.addOption(Option.builder().longOpt("time-unit").desc("Use given time unit in measurement, one of: milli, micro, nano.").hasArg().argName("unit").build()); - opts.addOption(Option.builder().longOpt("cleanup").desc("Send the cleanup command trigerring JCSystem.requestObjectDeletion() after some operations.").build()); - opts.addOption(Option.builder("s").longOpt("simulate").desc("Simulate a card with jcardsim instead of using a terminal.").build()); - opts.addOption(Option.builder("y").longOpt("yes").desc("Accept all warnings and prompts.").build()); - opts.addOption(Option.builder("to").longOpt("test-options").desc("Test options to use:\n- preset: Use preset semi-random private keys (derived from curve) instead of generating keypairs on the cards when the test needs one.\n- random: Use fully random private keys instead of generating keypairs.").hasArg().argName("options").build()); - - opts.addOption(Option.builder("ka").longOpt("ka-type").desc("Set KeyAgreement object [type], corresponds to JC.KeyAgreement constants.").hasArg().argName("type").optionalArg(true).build()); - opts.addOption(Option.builder("sig").longOpt("sig-type").desc("Set Signature object [type], corresponds to JC.Signature constants.").hasArg().argName("type").optionalArg(true).build()); - opts.addOption(Option.builder("C").longOpt("color").desc("Print stuff with color, requires ANSI terminal.").build()); - - CommandLineParser parser = new DefaultParser(); - return parser.parse(opts, args); - } - - private void listSuites() { - CardTestSuite[] suites = new CardTestSuite[]{ - new CardDefaultSuite(null, null, null), - new CardTestVectorSuite(null, null, null), - new CardCompressionSuite(null, null, null), - new CardWrongSuite(null, null, null), - new CardDegenerateSuite(null, null, null), - new CardCofactorSuite(null, null, null), - new CardCompositeSuite(null, null, null), - new CardInvalidSuite(null, null, null), - new CardEdgeCasesSuite(null, null, null), - new CardSignatureSuite(null, null, null), - new CardTwistSuite(null, null, null), - new CardMiscSuite(null, null, null)}; - for (CardTestSuite suite : suites) { - System.out.println(" - " + Colors.bold(suite.getName())); - for (String line : suite.getDescription()) { - System.out.println("\t" + line); - } - if (suite.getOptions() != null) { - System.out.println("\t" + Colors.underline("Options:") + " " + Arrays.toString(suite.getOptions())); - } - } - System.out.println(); - System.out.println("For more information, look at the documentation at https://github.com/crocs-muni/ECTester."); - } - - private void info() throws CardException { - Response.GetInfo info = new Command.GetInfo(cardManager).send(); - System.out.println(String.format("Card ATR:\t\t\t\t%s", ByteUtil.bytesToHex(cardManager.getATR().getBytes(), false))); - System.out.println(String.format("Card protocol:\t\t\t\t%s", cardManager.getProtocol())); - System.out.println(String.format("ECTester applet version:\t\t%s", info.getVersion())); - System.out.println(String.format("ECTester applet APDU support:\t\t%s", (info.getBase() == ECTesterApplet.BASE_221) ? "basic" : "extended length")); - System.out.println(String.format("JavaCard API version:\t\t\t%.1f", info.getJavaCardVersion())); - System.out.println(String.format("JavaCard supports system cleanup:\t%s", info.getCleanupSupport())); - System.out.println(String.format("Array sizes (apduBuf,ram,ram2,apduArr):\t%d %d %d %d", info.getApduBufferLength(), info.getRamArrayLength(), info.getRamArray2Length(), info.getApduArrayLength())); - } - - /** - * Exports default card/simulation EC domain parameters to output file. - * - * @throws CardException if APDU transmission fails - * @throws IOException if an IO error occurs when writing to key file. - */ - private void export() throws CardException, IOException { - byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - - List<Response> sent = new LinkedList<>(); - sent.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.keyBuilder, cfg.bits, keyClass).send()); - //sent.add(new Command.Clear(cardManager, ECTesterApplet.KEYPAIR_LOCAL).send()); - sent.add(new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL).send()); - - // Also support exporting set parameters, to verify they are set correctly. - Command curve = Command.prepareCurve(cardManager, cfg, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass); - if (curve != null) { - sent.add(curve.send()); - } - - // Cofactor generally isn't set on the default curve parameters on cards, - // since its not necessary for ECDH, only ECDHC which not many cards implement - // TODO: check if its assumend to be == 1? - short domain = cfg.primeField ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; - Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, domain).send(); - if (!export.successful()) { - domain = (short) (domain ^ EC_Consts.PARAMETER_K); - export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, domain).send(); - } - sent.add(export); - - for (Response r : sent) { - respWriter.outputResponse(r); - } - if (cfg.cleanup) { - Response cleanup = new Command.Cleanup(cardManager).send(); - respWriter.outputResponse(cleanup); - } - - PrintStream out = new PrintStream(FileUtil.openStream(cfg.outputs)); - byte[][] params = export.getParams(); - for (int i = 0; i < params.length; ++i) { - out.print(ByteUtil.bytesToHex(params[i], false)); - if (i != params.length - 1) { - out.print(","); - } - } - out.close(); - } - - /** - * Generates EC keyPairs and outputs them to output file. - * - * @throws CardException if APDU transmission fails - * @throws IOException if an IO error occurs when writing to key file. - */ - private void generate() throws CardException, IOException { - byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - Command curve = Command.prepareCurve(cardManager, cfg, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass); - - Response allocate = new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.keyBuilder, cfg.bits, keyClass).send(); - respWriter.outputResponse(allocate); - - OutputStreamWriter keysFile = FileUtil.openFiles(cfg.outputs); - keysFile.write(String.format("index;genTime[%s];exportTime[%s];pubW;privS\n", cfg.timeUnit, cfg.timeUnit)); - - int generated = 0; - int retry = 0; - while (generated < cfg.generateAmount || cfg.generateAmount == 0) { - if ((cfg.fresh || generated == 0) && curve != null) { - Response fresh = curve.send(); - respWriter.outputResponse(fresh); - } - - Command.Generate generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL); - long time = 0; - if (cfg.time) { - time = -Command.dryRunTime(cardManager, generate, 2, respWriter); - } - Response.Generate response = generate.send(); - time += response.getDuration(); - respWriter.outputResponse(response); - - Response.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_BOTH, EC_Consts.PARAMETERS_KEYPAIR).send(); - respWriter.outputResponse(export); - - if (!response.successful() || !export.successful()) { - if (retry < 10) { - retry++; - continue; - } else { - System.err.println(Colors.error("Keys could not be generated/exported.")); - break; - } - } - - String pub = ByteUtil.bytesToHex(export.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W), false); - String priv = ByteUtil.bytesToHex(export.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S), false); - String line = String.format("%d;%d;%d;%s;%s\n", generated, Util.convertTime(time, cfg.timeUnit), Util.convertTime(export.getDuration(), cfg.timeUnit), pub, priv); - keysFile.write(line); - keysFile.flush(); - generated++; - } - if (cfg.cleanup) { - Response cleanup = new Command.Cleanup(cardManager).send(); - respWriter.outputResponse(cleanup); - } - - keysFile.close(); - } - - /** - * Tests Elliptic curve support for a given curve/curves. - * - * @throws IOException if an IO error occurs - */ - private void test() throws ParserConfigurationException, IOException { - TestWriter writer = new FileTestWriter(cfg.format, true, cfg.outputs); - - CardTestSuite suite; - - switch (cfg.testSuite) { - case "default": - suite = new CardDefaultSuite(writer, cfg, cardManager); - break; - case "test-vectors": - suite = new CardTestVectorSuite(writer, cfg, cardManager); - break; - case "compression": - suite = new CardCompressionSuite(writer, cfg, cardManager); - break; - case "miscellaneous": - suite = new CardMiscSuite(writer, cfg, cardManager); - break; - case "signature": - suite = new CardSignatureSuite(writer, cfg, cardManager); - break; - default: - // These run are dangerous, prompt before them. - System.out.println("The test you selected (" + cfg.testSuite + ") is potentially dangerous."); - System.out.println("Some of these run have caused temporary(or even permanent) DoS of some cards."); - if (!cfg.yes) { - System.out.print("Do you want to proceed? (y/n): "); - Scanner in = new Scanner(System.in); - String confirmation = in.nextLine().toLowerCase(); - if (!Arrays.asList("yes", "y").contains(confirmation)) { - return; - } - in.close(); - } - switch (cfg.testSuite) { - case "wrong": - suite = new CardWrongSuite(writer, cfg, cardManager); - break; - case "composite": - suite = new CardCompositeSuite(writer, cfg, cardManager); - break; - case "invalid": - suite = new CardInvalidSuite(writer, cfg, cardManager); - break; - case "degenerate": - suite = new CardDegenerateSuite(writer, cfg, cardManager); - break; - case "twist": - suite = new CardTwistSuite(writer, cfg, cardManager); - break; - case "cofactor": - suite = new CardCofactorSuite(writer, cfg, cardManager); - break; - case "edge-cases": - suite = new CardEdgeCasesSuite(writer, cfg, cardManager); - break; - default: - System.err.println(Colors.error("Unknown test suite.")); - return; - } - break; - } - - suite.run(cfg.testFrom, cfg.testTo); - } - - /** - * Performs ECDH key exchange. - * - * @throws CardException if APDU transmission fails - * @throws IOException if an IO error occurs when writing to key file. - */ - private void ecdh() throws IOException, CardException { - byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - Command curve = Command.prepareCurve(cardManager, cfg, ECTesterApplet.KEYPAIR_BOTH, cfg.bits, keyClass); - List<Response> prepare = new LinkedList<>(); - prepare.add(new Command.AllocateKeyAgreement(cardManager, cfg.ECKAType).send()); // Prepare KeyAgreement or required type - prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_BOTH, cfg.keyBuilder, cfg.bits, keyClass).send()); - if (curve != null) - prepare.add(curve.send()); - - for (Response r : prepare) { - respWriter.outputResponse(r); - } - - OutputStreamWriter out = null; - if (cfg.outputs != null) { - out = FileUtil.openFiles(cfg.outputs); - out.write(String.format("index;time[%s];pubW;privS;secret[%s]\n", cfg.timeUnit, CardUtil.getKexHashName(cfg.ECKAType))); - } - - Response gen = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_BOTH).send(); - respWriter.outputResponse(gen); - if (cfg.anyPublicKey || cfg.anyKey) { - Response prep = Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.PARAMETER_W).send(); - respWriter.outputResponse(prep); - } - if (cfg.anyPrivateKey || cfg.anyKey) { - Response prep = Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S).send(); - respWriter.outputResponse(prep); - } - - byte kp = ECTesterApplet.KEYPAIR_BOTH; - if (cfg.fixedPrivate || cfg.anyPrivateKey) { - kp ^= ECTesterApplet.KEYPAIR_LOCAL; - } - if (cfg.fixedPublic || cfg.anyPublicKey) { - kp ^= ECTesterApplet.KEYPAIR_REMOTE; - } - if (cfg.fixedKey || cfg.anyKey) { - kp = 0; - } - - Command generate = null; - if (kp != 0) { - generate = new Command.Generate(cardManager, kp); - } - - int retry = 0; - int done = 0; - while (done < cfg.ECKACount || cfg.ECKACount == 0) { - if (generate != null) { - Response regen = generate.send(); - respWriter.outputResponse(regen); - } - - Response.Export exportRemote = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W).send(); - respWriter.outputResponse(exportRemote); - Response.Export exportLocal = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PRIVATE, EC_Consts.PARAMETER_S).send(); - respWriter.outputResponse(exportLocal); - byte[] pubkey_bytes = exportRemote.getParameter(ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.PARAMETER_W); - byte[] privkey_bytes = exportLocal.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S); - - Command.ECDH perform = new Command.ECDH(cardManager, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, cfg.ECKAType); - - long time = 0; - if (cfg.time) { - time = -Command.dryRunTime(cardManager, perform, 2, respWriter); - } - - Response.ECDH result = perform.send(); - respWriter.outputResponse(result); - - if (!result.successful() || !result.hasSecret()) { - if (retry < 10) { - ++retry; - continue; - } else { - System.err.println(Colors.error("Couldn't obtain ECDH secret from card response.")); - break; - } - } - - if (out != null) { - time += result.getDuration(); - - out.write(String.format("%d;%d;%s;%s;%s\n", done, Util.convertTime(time, cfg.timeUnit), ByteUtil.bytesToHex(pubkey_bytes, false), ByteUtil.bytesToHex(privkey_bytes, false), ByteUtil.bytesToHex(result.getSecret(), false))); - out.flush(); - } - - ++done; - } - if (cfg.cleanup) { - Response cleanup = new Command.Cleanup(cardManager).send(); - respWriter.outputResponse(cleanup); - } - - if (out != null) - out.close(); - } - - /** - * Performs ECDSA signature, on random or provided data. - * - * @throws CardException if APDU transmission fails - * @throws IOException if an IO error occurs when writing to key file. - */ - private void ecdsa() throws CardException, IOException { - //read file, if asked to sign - byte[] data; - if (cfg.input != null) { - File in = new File(cfg.input); - long len = in.length(); - if (len == 0) { - throw new FileNotFoundException(cfg.input); - } - data = Files.readAllBytes(in.toPath()); - } else { - Random rand = new Random(); - data = new byte[32]; - rand.nextBytes(data); - } - - Command generate; - if (cfg.anyKeypart) { - generate = Command.prepareKey(cardManager, EC_Store.getInstance(), cfg, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETERS_KEYPAIR); - } else { - generate = new Command.Generate(cardManager, ECTesterApplet.KEYPAIR_LOCAL); - } - - byte keyClass = cfg.primeField ? KeyPair.ALG_EC_FP : KeyPair.ALG_EC_F2M; - List<Response> prepare = new LinkedList<>(); - prepare.add(new Command.AllocateSignature(cardManager, cfg.ECDSAType).send()); - prepare.add(new Command.Allocate(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.keyBuilder, cfg.bits, keyClass).send()); - Command curve = Command.prepareCurve(cardManager, cfg, ECTesterApplet.KEYPAIR_LOCAL, cfg.bits, keyClass); - if (curve != null) - prepare.add(curve.send()); - - for (Response r : prepare) { - respWriter.outputResponse(r); - } - - OutputStreamWriter out = FileUtil.openFiles(cfg.outputs); - if (out != null) { - out.write(String.format("index;signTime[%s];verifyTime[%s];data;pubW;privS;signature[%s];nonce;valid\n", cfg.timeUnit, cfg.timeUnit, CardUtil.getSigHashAlgo(cfg.ECDSAType))); - } - - Command.Export export = new Command.Export(cardManager, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_BOTH, EC_Consts.PARAMETERS_KEYPAIR); - Response.Export exported = null; - if (cfg.fixedKey) { - respWriter.outputResponse(generate.send()); - exported = export.send(); - respWriter.outputResponse(exported); - } - - int retry = 0; - int done = 0; - while (done < cfg.ECDSACount || cfg.ECDSACount == 0) { - if (!cfg.fixedKey) { - respWriter.outputResponse(generate.send()); - exported = export.send(); - respWriter.outputResponse(exported); - } - - Command.ECDSA_sign sign = new Command.ECDSA_sign(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.ECDSAType, ECTesterApplet.EXPORT_TRUE, data); - - long signTime = 0; - if (cfg.time) { - signTime = -Command.dryRunTime(cardManager, sign, 2, respWriter); - } - - Response.ECDSA signResp = sign.send(); - signTime += signResp.getDuration(); - respWriter.outputResponse(signResp); - if (!signResp.successful() || !signResp.hasSignature()) { - if (retry < 10) { - ++retry; - continue; - } else { - System.err.println(Colors.error("Couldn't obtain ECDSA signature from card response.")); - break; - } - } - byte[] signature = signResp.getSignature(); - Command.ECDSA_verify verify = new Command.ECDSA_verify(cardManager, ECTesterApplet.KEYPAIR_LOCAL, cfg.ECDSAType, data, signature); - long verifyTime = 0; - if (cfg.time) { - verifyTime = -Command.dryRunTime(cardManager, verify, 2, respWriter); - } - Response.ECDSA verifyResp = verify.send(); - verifyTime += verifyResp.getDuration(); - respWriter.outputResponse(verifyResp); - - if (verifyResp.error()) { - if (retry < 10) { - ++retry; - continue; - } else { - System.err.println(Colors.error("Couldn't obtain ECDSA signature from card response.")); - break; - } - } - - if (out != null) { - String pub = ByteUtil.bytesToHex(exported.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W), false); - String priv = ByteUtil.bytesToHex(exported.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S), false); - String dataString = (cfg.input != null) ? "" : ByteUtil.bytesToHex(data, false); - BigInteger privkey = new BigInteger(1, exported.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_S)); - EC_Curve actualCurve = Command.findCurve(cfg, cfg.bits, keyClass); - String k = ""; - if (actualCurve != null) { - ECParameterSpec params = actualCurve.toSpec(); - BigInteger kValue = ECUtil.recoverSignatureNonce(signature, data, privkey, params, CardUtil.getSigHashName(cfg.ECDSAType), "ECDSA"); - if (kValue != null) { - k = ByteUtil.bytesToHex(kValue.toByteArray(), false); - } - } - out.write(String.format("%d;%d;%d;%s;%s;%s;%s;%s;%d\n", done, Util.convertTime(signTime, cfg.timeUnit), Util.convertTime(verifyTime, cfg.timeUnit), dataString, pub, priv, ByteUtil.bytesToHex(signature, false), k, verifyResp.successful() ? 1 : 0)); - out.flush(); - } - - ++done; - } - if (cfg.cleanup) { - Response cleanup = new Command.Cleanup(cardManager).send(); - respWriter.outputResponse(cleanup); - } - if (out != null) - out.close(); - } - - public static void main(String[] args) { - ECTesterReader app = new ECTesterReader(); - app.run(args); - } - - public static class Config { - - //Options - public short bits; - public boolean all; - public boolean primeField = false; - public boolean binaryField = false; - - - public String namedCurve; - public String curveFile; - public boolean customCurve = false; - - public boolean anyPublicKey = false; - public String namedPublicKey; - public String publicKey; - - public boolean anyPrivateKey = false; - public String namedPrivateKey; - public String privateKey; - - public boolean anyKey = false; - public String namedKey; - public String key; - - public boolean anyKeypart = false; - public boolean fixedKey = false; - public boolean fixedPrivate = false; - public boolean fixedPublic = false; - public byte keyBuilder; - - public String log; - - public boolean verbose = false; - public String input; - public String[] outputs; - public boolean fresh = false; - public boolean time = false; - public String timeUnit; - public boolean cleanup = false; - public boolean simulate = false; - public boolean yes = false; - public String format; - public boolean color; - - //Action-related options - public String listNamed; - public String testSuite; - public int testFrom; - public int testTo; - public int generateAmount; - public int ECKACount; - public byte ECKAType = KeyAgreement_ALG_EC_SVDP_DH; - public int ECDSACount; - public byte ECDSAType = Signature_ALG_ECDSA_SHA; - public Set<String> testOptions; - - /** - * Reads and validates options, also sets defaults. - * - * @param cli cli object, with parsed args - * @return whether the options are valid. - */ - boolean readOptions(CommandLine cli) { - bits = Short.parseShort(cli.getOptionValue("bit-size", "0")); - all = cli.hasOption("all"); - primeField = cli.hasOption("fp"); - binaryField = cli.hasOption("f2m"); - - - namedCurve = cli.getOptionValue("named-curve"); - customCurve = cli.hasOption("custom"); - curveFile = cli.getOptionValue("curve"); - - namedPublicKey = cli.getOptionValue("named-public"); - publicKey = cli.getOptionValue("public"); - anyPublicKey = (publicKey != null) || (namedPublicKey != null); - - namedPrivateKey = cli.getOptionValue("named-private"); - privateKey = cli.getOptionValue("private"); - anyPrivateKey = (privateKey != null) || (namedPrivateKey != null); - - namedKey = cli.getOptionValue("named-key"); - key = cli.getOptionValue("key"); - anyKey = (key != null) || (namedKey != null); - anyKeypart = anyKey || anyPublicKey || anyPrivateKey; - fixedKey = cli.hasOption("fixed"); - fixedPrivate = cli.hasOption("fixed-private"); - fixedPublic = cli.hasOption("fixed-public"); - keyBuilder = cli.hasOption("key-builder") ? ECTesterApplet.BUILD_KEYBUILDER : ECTesterApplet.BUILD_KEYPAIR; - - if (cli.hasOption("log")) { - log = cli.getOptionValue("log", String.format("ECTESTER_log_%d.log", System.currentTimeMillis() / 1000)); - } - - verbose = cli.hasOption("verbose"); - input = cli.getOptionValue("input"); - outputs = cli.getOptionValues("output"); - fresh = cli.hasOption("fresh"); - time = cli.hasOption("time"); - cleanup = cli.hasOption("cleanup"); - simulate = cli.hasOption("simulate"); - yes = cli.hasOption("yes"); - color = cli.hasOption("color"); - Colors.enabled = color; - - timeUnit = cli.getOptionValue("time-unit", "micro"); - String[] times = new String[]{"milli", "micro", "nano"}; - if (!Arrays.asList(times).contains(timeUnit)) { - System.err.println(Colors.error("Wrong time unit " + timeUnit + ". Should be one of " + Arrays.toString(times))); - return false; - } - - if (cli.hasOption("list-named")) { - listNamed = cli.getOptionValue("list-named"); - return true; - } - - format = cli.getOptionValue("format"); - String[] formats = new String[]{"text", "xml", "yaml", "yml"}; - if (format != null && !Arrays.asList(formats).contains(format)) { - System.err.println(Colors.error("Wrong output format " + format + ". Should be one of " + Arrays.toString(formats))); - return false; - } - - if ((key != null || namedKey != null) && (anyPublicKey || anyPrivateKey)) { - System.err.print(Colors.error("Can only specify the whole key with --key/--named-key or pubkey and privkey with --public/--named-public and --private/--named-private.")); - return false; - } - if (bits < 0) { - System.err.println(Colors.error("Bit-size must not be negative.")); - return false; - } - - if (key != null && namedKey != null || publicKey != null && namedPublicKey != null || privateKey != null && namedPrivateKey != null) { - System.err.println(Colors.error("You cannot specify both a named key and a key file.")); - return false; - } - - if (cli.hasOption("export")) { - if (primeField == binaryField) { - System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)")); - return false; - } - if (anyKeypart) { - System.err.println(Colors.error("Keys should not be specified when exporting curve params.")); - return false; - } - if (outputs == null) { - System.err.println(Colors.error("You have to specify an output file for curve parameter export.")); - return false; - } - if (all || bits == 0) { - System.err.println(Colors.error("You have to specify curve bit-size with -b")); - return false; - } - } else if (cli.hasOption("generate")) { - if (primeField == binaryField) { - System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)")); - return false; - } - if (anyKeypart) { - System.err.println(Colors.error("Keys should not be specified when generating keys.")); - return false; - } - if (outputs == null) { - System.err.println(Colors.error("You have to specify an output file for the key generation process.")); - return false; - } - if (all || bits == 0) { - System.err.println(Colors.error("You have to specify curve bit-size with -b")); - return false; - } - - generateAmount = Integer.parseInt(cli.getOptionValue("generate", "0")); - if (generateAmount < 0) { - System.err.println(Colors.error("Amount of keys generated cant be negative.")); - return false; - } - } else if (cli.hasOption("test")) { - if (!(binaryField || primeField)) { - binaryField = true; - primeField = true; - } - - String suiteOpt = cli.getOptionValue("test", "default").toLowerCase(); - if (suiteOpt.contains(":")) { - String[] parts = suiteOpt.split(":"); - testSuite = parts[0]; - try { - testFrom = Integer.parseInt(parts[1]); - } catch (NumberFormatException nfe) { - System.err.println("Invalid test_from number: " + parts[1] + "."); - return false; - } - if (parts.length == 3) { - try { - testTo = Integer.parseInt(parts[2]); - } catch (NumberFormatException nfe) { - System.err.println("Invalid test_to number: " + parts[2] + "."); - return false; - } - } else if (parts.length != 2) { - System.err.println("Invalid test suite selection."); - return false; - } else { - testTo = -1; - } - } else { - testSuite = suiteOpt; - testFrom = 0; - testTo = -1; - } - - String[] tests = new String[]{"default", "composite", "compression", "invalid", "degenerate", "test-vectors", "wrong", "twist", "cofactor", "edge-cases", "miscellaneous", "signature"}; - String selected = null; - for (String test : tests) { - if (test.startsWith(testSuite)) { - if (selected != null) { - System.err.println(Colors.error("Test suite ambiguous " + test + " or " + selected + "?")); - return false; - } else { - selected = test; - } - } - } - if (selected == null) { - System.err.println(Colors.error("Unknown test suite " + testSuite + ". Should be one of: " + Arrays.toString(tests))); - return false; - } else { - testSuite = selected; - } - - String[] opts = cli.getOptionValue("test-options", "").split(","); - List<String> validOpts = Arrays.asList("preset", "random"); - testOptions = new HashSet<>(); - for (String opt : opts) { - if (opt.equals("")) { - continue; - } - if (!validOpts.contains(opt)) { - System.err.println(Colors.error("Unknown test option " + opt + ". Should be one of: " + Arrays.toString(validOpts.toArray()))); - return false; - } else { - testOptions.add(opt); - } - } - - if (testOptions.contains("preset") && testOptions.contains("random")) { - System.err.println("Cannot have both preset and random option enabled."); - return false; - } - } else if (cli.hasOption("ecdh")) { - if (primeField == binaryField) { - System.err.print(Colors.error("Need to specify field with -fp or -f2m. (not both)")); - return false; - } - if (all || bits == 0) { - System.err.println(Colors.error("You have to specify curve bit-size with -b")); - return false; - } - - ECKACount = Integer.parseInt(cli.getOptionValue("ecdh", "1")); - if (ECKACount < 0) { - System.err.println(Colors.error("ECDH count cannot be < 0.")); - return false; - } - - ECKAType = CardUtil.parseKAType(cli.getOptionValue("ka-type", "1")); - } else if (cli.hasOption("ecdsa")) { - if (primeField == binaryField) { - System.err.print(Colors.error("Need to specify field with -fp or -f2m. (but not both)")); - return false; - } - if (all || bits == 0) { - System.err.println(Colors.error("You have to specify curve bit-size with -b")); - return false; - } - - if ((anyPublicKey) != (anyPrivateKey) && !anyKey) { - System.err.println(Colors.error("You cannot only specify a part of a keypair.")); - return false; - } - - ECDSACount = Integer.parseInt(cli.getOptionValue("ecdsa", "1")); - if (ECDSACount < 0) { - System.err.println(Colors.error("ECDSA count cannot be < 0.")); - return false; - } - - ECDSAType = CardUtil.parseSigType(cli.getOptionValue("sig-type", "17")); - } - return true; - } - } -} diff --git a/src/cz/crcs/ectester/reader/ISO7816_status_words.txt b/src/cz/crcs/ectester/reader/ISO7816_status_words.txt deleted file mode 100644 index bf5af2b..0000000 --- a/src/cz/crcs/ectester/reader/ISO7816_status_words.txt +++ /dev/null @@ -1,71 +0,0 @@ -public interface ISO7816 { - - // Fields - public static final byte INS_EXTERNAL_AUTHENTICATE = -126; - public static final byte INS_SELECT = -92; - public static final byte CLA_ISO7816 = 0; - public static final byte OFFSET_CDATA = 5; - public static final byte OFFSET_LC = 4; - public static final byte OFFSET_P2 = 3; - public static final byte OFFSET_P1 = 2; - public static final byte OFFSET_INS = 1; - public static final byte OFFSET_CLA = 0; - public static final short SW_FILE_FULL = 27268; 0x6A84 - public static final short SW_UNKNOWN = 28416; 0x6F00 - public static final short SW_CLA_NOT_SUPPORTED = 28160; 0x6E00 - public static final short SW_INS_NOT_SUPPORTED = 27904; 0x6D00 - public static final short SW_CORRECT_LENGTH_00 = 27648; 0x6C00 - public static final short SW_WRONG_P1P2 = 27392; 0x6B00 - public static final short SW_INCORRECT_P1P2 = 27270; 0x6A86 - public static final short SW_RECORD_NOT_FOUND = 27267; 0x6A83 - public static final short SW_FILE_NOT_FOUND = 27266; 0x6A82 - public static final short SW_FUNC_NOT_SUPPORTED = 27265; 0x6A81 - public static final short SW_WRONG_DATA = 27264; 0x6A80 - public static final short SW_APPLET_SELECT_FAILED = 27033; 0x6999 - public static final short SW_COMMAND_NOT_ALLOWED = 27014; 0x6986 - public static final short SW_CONDITIONS_NOT_SATISFIED = 27013; 0x6985 - public static final short SW_DATA_INVALID = 27012; 0x6984 - public static final short SW_FILE_INVALID = 27011; 0x6983 - public static final short SW_SECURITY_STATUS_NOT_SATISFIED = 27010; 0x6982 - public static final short SW_WRONG_LENGTH = 26368; 0x6700 - public static final short SW_BYTES_REMAINING_00 = 24832; 0x6100 - public static final short SW_NO_ERROR = -28672; 0x9000 -} - -public interface JCStatus { -static int ALGORITHM_NOT_SUPPORTED = 0x9484; -static int APPLET_INVALIDATED = 0x6283; -static int APPLET_SELECT_FAILED = 0x6999 -static int AUTHENTICATION_FAILED = 0x6300 -static int AUTHORIZATION_FAILED = 0x9482 -static int CHECKSUM_FAILED = 0x9584 -static int CLA_NOT_SUPPORTED = 0x6E00 -static int COMMAND_NOT_ALLOWED = 0x6986 -static int CONDITIONS_NOT_SATISFIED = 0x6985 -static int CORRECT_LENGTH_00 = 0x6C00 -static int DATA_INVALID = 0x6984 -static int DECRYPTION_FAILED = 0x9583 -static int FILE_FULL = 0x6A84 -static int FILE_INVALID = 0x6983 -static int FILE_NOT_FOUND = 0x6A82 -static int FUNC_NOT_SUPPORTED = 0x6A81 -static int INCORRECT_P1P2 = 0x6A86 -static int INS_NOT_SUPPORTED = 0x6D00 -static int INSTALLATION_FAILED = 0x9585 -static int INVALID_STATE = 0x9481 -static int NO_ERROR = 0x9000 -static int NO_SPECIFIC_DIAGNOSIS = 0x6400 -static int PIN_REQUIRED = 0x6982 -static int RECORD_NOT_FOUND = 0x6A83 -static int REFERENCE_DATA_NOT_FOUND = 0x6A88 -static int REGISTRATION_FAILED = 0x9586 -static int SECURITY_STATUS_NOT_SATISFIED = 0x6982 -static int SIGNATURE_CHECK_FAILED = 0x9582 -static int SM_INCORRECT = 0x6988 -static int SM_MISSING = 0x6987 -static int TRUNCATED_DATA = 0x6100 -static int UNKNOWN = 0x6F00 -static int WRONG_DATA = 0x6A80 -static int WRONG_LENGTH = 0x6700 -static int WRONG_P1P2 = 0x6B00 -}
\ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/command/Command.java b/src/cz/crcs/ectester/reader/command/Command.java deleted file mode 100644 index 61e3900..0000000 --- a/src/cz/crcs/ectester/reader/command/Command.java +++ /dev/null @@ -1,920 +0,0 @@ -package cz.crcs.ectester.reader.command; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Params; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.output.ResponseWriter; -import cz.crcs.ectester.reader.response.Response; -import javacard.security.KeyPair; - -import javax.smartcardio.CardException; -import javax.smartcardio.CommandAPDU; -import javax.smartcardio.ResponseAPDU; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public abstract class Command implements Cloneable { - CommandAPDU cmd; - CardMngr cardManager; - // Workaround for a stupid Java bug that went unfixed for !12! years, - // and for the even more stupid module system, which cannot properly work - // with the fact that JCardSim has some java.* packages... - final byte[] GOD_DAMN_JAVA_BUG_6474858_AND_GOD_DAMN_JAVA_12_MODULE_SYSTEM = new byte[]{0}; - - - Command(CardMngr cardManager) { - this.cardManager = cardManager; - } - - public CommandAPDU getAPDU() { - return cmd; - } - - public abstract Response send() throws CardException; - - public static List<Response> sendAll(List<Command> commands) throws CardException { - List<Response> result = new ArrayList<>(); - for (Command cmd : commands) { - result.add(cmd.send()); - } - return result; - } - - public abstract String getDescription(); - - @Override - protected Command clone() throws CloneNotSupportedException { - return (Command) super.clone(); - } - - public static EC_Curve findCurve(ECTesterReader.Config cfg, short keyLength, byte keyClass) throws IOException { - if (cfg.customCurve) { - byte curveId = EC_Consts.getCurve(keyLength, keyClass); - return EC_Store.getInstance().getObject(EC_Curve.class, "secg", CardUtil.getCurveName(curveId)); - } else if (cfg.namedCurve != null) { - EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, cfg.namedCurve); - if (curve == null) { - throw new IOException("Curve could no be found."); - } - if (curve.getBits() != keyLength) { - throw new IOException("Curve bits mismatch: " + curve.getBits() + " vs " + keyLength + " entered."); - } - if (curve.getField() != keyClass) { - throw new IOException("Curve field mismatch."); - } - return curve; - } else if (cfg.curveFile != null) { - EC_Curve curve = new EC_Curve(null, keyLength, keyClass); - - FileInputStream in = new FileInputStream(cfg.curveFile); - curve.readCSV(in); - in.close(); - return curve; - } else { - return null; - } - } - - - /** - * @param keyPair which keyPair/s (local/remote) to set curve domain parameters on - * @param keyLength key length to choose - * @param keyClass key class to choose - * @return a Command to send in order to prepare the curve on the keypairs. - * @throws IOException if curve file cannot be found/opened - */ - public static Command prepareCurve(CardMngr cardManager, ECTesterReader.Config cfg, byte keyPair, short keyLength, byte keyClass) throws IOException { - if (cfg.customCurve) { - // Set custom curve (one of the SECG curves embedded applet-side) - short domainParams = keyClass == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; - return new Command.Set(cardManager, keyPair, EC_Consts.getCurve(keyLength, keyClass), domainParams, null); - } - - EC_Curve curve = findCurve(cfg, keyLength, keyClass); - if ((curve == null || curve.flatten() == null) && (cfg.namedCurve != null || cfg.curveFile != null)) { - if (cfg.namedCurve != null) { - throw new IOException("Couldn't read named curve data."); - } - throw new IOException("Couldn't read the curve file correctly."); - } else if (curve == null) { - return null; - } - return new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()); - } - - - /** - * @param cardManager - * @param dataStore - * @param cfg - * @param keyPair which keyPair/s to set the key params on - * @param allowedParams - * @return a CommandAPDU setting params loaded on the keyPair/s - * @throws IOException if any of the key files cannot be found/opened - */ - public static Command prepareKey(CardMngr cardManager, EC_Store dataStore, ECTesterReader.Config cfg, byte keyPair, short allowedParams) throws IOException { - short params = EC_Consts.PARAMETERS_NONE; - byte[] data = null; - - if (cfg.key != null || cfg.namedKey != null) { - params |= EC_Consts.PARAMETERS_KEYPAIR; - EC_Params keypair = ECUtil.loadParams(EC_Consts.PARAMETERS_KEYPAIR, cfg.namedKey, cfg.key); - if (keypair == null) { - throw new IOException("KeyPair not found."); - } - - data = keypair.flatten(); - if (data == null) { - throw new IOException("Couldn't read the key file correctly."); - } - } - - if ((cfg.publicKey != null || cfg.namedPublicKey != null) && ((allowedParams & EC_Consts.PARAMETER_W) != 0)) { - params |= EC_Consts.PARAMETER_W; - EC_Params pub = ECUtil.loadParams(EC_Consts.PARAMETER_W, cfg.namedPublicKey, cfg.publicKey); - if (pub == null) { - throw new IOException("Public key not found."); - } - - byte[] pubkey = pub.flatten(EC_Consts.PARAMETER_W); - if (pubkey == null) { - throw new IOException("Couldn't read the public key file correctly."); - } - data = pubkey; - } - - if ((cfg.privateKey != null || cfg.namedPrivateKey != null) && ((allowedParams & EC_Consts.PARAMETER_S) != 0)) { - params |= EC_Consts.PARAMETER_S; - EC_Params priv = ECUtil.loadParams(EC_Consts.PARAMETER_S, cfg.namedPrivateKey, cfg.privateKey); - if (priv == null) { - throw new IOException("Private key not found."); - } - - byte[] privkey = priv.flatten(EC_Consts.PARAMETER_S); - if (privkey == null) { - throw new IOException("Couldn't read the private key file correctly."); - } - data = ByteUtil.concatenate(data, privkey); - } - return new Command.Set(cardManager, keyPair, EC_Consts.CURVE_external, params, data); - } - - public static long dryRunTime(CardMngr cardManager, Command cmd, int num, ResponseWriter respWriter) throws CardException { - long time = 0; - respWriter.outputResponse(new Command.SetDryRunMode(cardManager, ECTesterApplet.MODE_DRY_RUN).send()); - for (int i = 0; i < num; ++i) { - Response dry = cmd.send(); - respWriter.outputResponse(dry); - time += dry.getDuration(); - } - time /= num; - respWriter.outputResponse(new Command.SetDryRunMode(cardManager, ECTesterApplet.MODE_NORMAL).send()); - return time; - } - - /** - * - */ - public static class AllocateKeyAgreement extends Command { - private byte kaType; - - /** - * Creates the INS_ALLOCATE_KA instruction. - * - * @param cardManager cardManager to send APDU through - * @param kaType which type of KeyAgreement to use - */ - public AllocateKeyAgreement(CardMngr cardManager, byte kaType) { - super(cardManager); - this.kaType = kaType; - byte[] data = new byte[]{kaType}; - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE_KA, 0x00, 0x00, data); - } - - @Override - public Response.AllocateKeyAgreement send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.AllocateKeyAgreement(response, getDescription(), elapsed, kaType); - } - - @Override - public String getDescription() { - return String.format("Allocate KeyAgreement(%s) object", CardUtil.getKATypeString(kaType)); - } - } - - /** - * - */ - public static class AllocateSignature extends Command { - private byte sigType; - - /** - * Creates the INS_ALLOCATE_SIG instruction. - * - * @param cardManager cardManager to send APDU through - * @param sigType which type of Signature to use - */ - public AllocateSignature(CardMngr cardManager, byte sigType) { - super(cardManager); - this.sigType = sigType; - byte[] data = new byte[]{sigType}; - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE_SIG, 0x00, 0x00, data); - } - - @Override - public Response.AllocateSignature send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.AllocateSignature(response, getDescription(), elapsed, sigType); - } - - @Override - public String getDescription() { - return String.format("Allocate Signature(%s) object", CardUtil.getSigTypeString(sigType)); - } - } - - /** - * - */ - public static class Allocate extends Command { - private byte keyPair; - private byte build; - private short keyLength; - private byte keyClass; - - /** - * Creates the INS_ALLOCATE instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair which keyPair to use, local/remote (KEYPAIR_* | ...) - * @param build whether to use KeyBuilder or Keypair alloc - * @param keyLength key length to set - * @param keyClass key class to allocate - */ - public Allocate(CardMngr cardManager, byte keyPair, byte build, short keyLength, byte keyClass) { - super(cardManager); - this.keyPair = keyPair; - this.build = build; - this.keyLength = keyLength; - this.keyClass = keyClass; - - byte[] data = new byte[]{0, 0, keyClass}; - ByteUtil.setShort(data, 0, keyLength); - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ALLOCATE, keyPair, build, data); - } - - public Allocate(CardMngr cardManager, byte keyPair, short keyLength, byte keyClass) { - this(cardManager, keyPair, (byte) (ECTesterApplet.BUILD_KEYPAIR | ECTesterApplet.BUILD_KEYBUILDER), keyLength, keyClass); - } - - @Override - public Response.Allocate send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Allocate(response, getDescription(), elapsed, keyPair, keyLength, keyClass); - } - - @Override - public String getDescription() { - String field = keyClass == KeyPair.ALG_EC_FP ? "ALG_EC_FP" : "ALG_EC_F2M"; - String key; - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - key = "both keypairs"; - } else { - key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; - } - return String.format("Allocate %s %db %s", key, keyLength, field); - } - } - - /** - * - */ - public static class Clear extends Command { - private byte keyPair; - - /** - * @param cardManager cardManager to send APDU through - * @param keyPair which keyPair clear, local/remote (KEYPAIR_* || ...) - */ - public Clear(CardMngr cardManager, byte keyPair) { - super(cardManager); - this.keyPair = keyPair; - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_CLEAR, keyPair, 0x00, GOD_DAMN_JAVA_BUG_6474858_AND_GOD_DAMN_JAVA_12_MODULE_SYSTEM); - } - - @Override - public Response.Clear send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Clear(response, getDescription(), elapsed, keyPair); - } - - @Override - public String getDescription() { - String key; - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - key = "both keypairs"; - } else { - key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; - } - return String.format("Clear %s", key); - } - } - - /** - * - */ - public static class Set extends Command { - private byte keyPair; - private byte curve; - private short params; - private byte[] external; - - /** - * Creates the INS_SET instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair which keyPair to set params on, local/remote (KEYPAIR_* || ...) - * @param curve curve to set (EC_Consts.CURVE_*) - * @param params parameters to set (EC_Consts.PARAMETER_* | ...) - * @param external external curve data, can be null - */ - public Set(CardMngr cardManager, byte keyPair, byte curve, short params, byte[] external) { - super(cardManager); - this.keyPair = keyPair; - this.curve = curve; - this.params = params; - this.external = external; - - int len = external != null ? 2 + external.length : 2; - byte[] data = new byte[len]; - ByteUtil.setShort(data, 0, params); - if (external != null) { - System.arraycopy(external, 0, data, 2, external.length); - } - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_SET, keyPair, curve, data); - } - - @Override - public Response.Set send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Set(response, getDescription(), elapsed, keyPair, curve, params); - } - - @Override - public String getDescription() { - String name = CardUtil.getCurveName(curve); - String what = CardUtil.getParameterString(params); - - String pair; - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - pair = "both keypairs"; - } else { - pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; - } - return String.format("Set %s %s parameters on %s", name, what, pair); - } - } - - /** - * - */ - public static class Transform extends Command { - private byte keyPair; - private byte key; - private short params; - private short transformation; - - /** - * @param cardManager cardManager to send APDU through - * @param keyPair which keyPair to transform, local/remote (KEYPAIR_* || ...) - * @param key key to transform (EC_Consts.KEY_* | ...) - * @param params parameters to transform (EC_Consts.PARAMETER_* | ...) - * @param transformation transformation type (EC_Consts.TRANSFORMATION_*) - */ - public Transform(CardMngr cardManager, byte keyPair, byte key, short params, short transformation) { - super(cardManager); - this.keyPair = keyPair; - this.key = key; - this.params = params; - this.transformation = transformation; - - byte[] data = new byte[4]; - ByteUtil.setShort(data, 0, params); - ByteUtil.setShort(data, 2, transformation); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_TRANSFORM, keyPair, key, data); - } - - @Override - public Response.Transform send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Transform(response, getDescription(), elapsed, keyPair, key, params, transformation); - } - - @Override - public String getDescription() { - String stringParams = CardUtil.getParams(params); - String transform = CardUtil.getTransformation(transformation); - - String pair; - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - pair = "both keypairs"; - } else { - pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; - } - return String.format("Transform params %s of %s, %s", stringParams, pair, transform); - } - } - - /** - * - */ - public static class Generate extends Command { - private byte keyPair; - - /** - * Creates the INS_GENERATE instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair which keyPair to generate, local/remote (KEYPAIR_* || ...) - */ - public Generate(CardMngr cardManager, byte keyPair) { - super(cardManager); - this.keyPair = keyPair; - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_GENERATE, keyPair, 0, GOD_DAMN_JAVA_BUG_6474858_AND_GOD_DAMN_JAVA_12_MODULE_SYSTEM); - } - - @Override - public Response.Generate send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Generate(response, getDescription(), elapsed, keyPair); - } - - @Override - public String getDescription() { - String key; - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - key = "both keypairs"; - } else { - key = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; - } - return String.format("Generate %s", key); - } - } - - /** - * - */ - public static class Export extends Command { - private byte keyPair; - private byte key; - private short params; - - /** - * Creates the INS_EXPORT instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair keyPair to export from (KEYPAIR_* | ...) - * @param key key to export from (EC_Consts.KEY_* | ...) - * @param params params to export (EC_Consts.PARAMETER_* | ...) - */ - public Export(CardMngr cardManager, byte keyPair, byte key, short params) { - super(cardManager); - this.keyPair = keyPair; - this.key = key; - this.params = params; - - byte[] data = new byte[2]; - ByteUtil.setShort(data, 0, params); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_EXPORT, keyPair, key, data); - } - - @Override - public Response.Export send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Export(response, getDescription(), elapsed, keyPair, key, params); - } - - @Override - public String getDescription() { - String what = CardUtil.getParameterString(params); - - String source; - if (key == EC_Consts.KEY_BOTH) { - source = "both keys"; - } else { - source = ((key == EC_Consts.KEY_PUBLIC) ? "public" : "private") + " key"; - } - String pair; - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - pair = "both keypairs"; - } else { - pair = ((keyPair == ECTesterApplet.KEYPAIR_LOCAL) ? "local" : "remote") + " keypair"; - } - return String.format("Export %s params from %s of %s", what, source, pair); - } - } - - /** - * - */ - public static class ECDH extends Command { - private byte pubkey; - private byte privkey; - private byte export; - private short transformation; - private byte type; - - /** - * Creates the INS_ECDH instruction. - * - * @param cardManager cardManager to send APDU through - * @param pubkey keyPair to use for public key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param export whether to export ECDH secret - * @param transformation whether to transform the pubkey before ECDH (EC_Consts.TRANSFORMATION_* | ...) - * @param type ECDH algorithm type (EC_Consts.KA_* | ...) - */ - public ECDH(CardMngr cardManager, byte pubkey, byte privkey, byte export, short transformation, byte type) { - super(cardManager); - this.pubkey = pubkey; - this.privkey = privkey; - this.export = export; - this.transformation = transformation; - this.type = type; - - byte[] data = new byte[]{export, 0, 0, type}; - ByteUtil.setShort(data, 1, transformation); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH, pubkey, privkey, data); - } - - @Override - public Response.ECDH send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.ECDH(response, getDescription(), elapsed, pubkey, privkey, export, transformation, type); - } - - @Override - public String getDescription() { - String algo = CardUtil.getKATypeString(type); - - String pub = pubkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; - String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; - - String validity; - if (transformation == EC_Consts.TRANSFORMATION_NONE) { - validity = ""; - } else { - validity = String.format("(%s point)", CardUtil.getTransformation(transformation)); - } - return String.format("%s of %s pubkey and %s privkey%s", algo, pub, priv, validity); - } - } - - /** - * - */ - public static class ECDH_direct extends Command { - private byte privkey; - private byte export; - private short transformation; - private byte type; - private byte[] pubkey; - - /** - * Creates the INS_ECDH_DIRECT instruction. - * - * @param cardManager cardManager to send APDU through - * @param privkey keyPair to use for private key, (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param export whether to export ECDH secret - * @param transformation whether to transform the pubkey before ECDH (EC_Consts.TRANSFORMATION_* | ...) - * @param type EC KeyAgreement type - * @param pubkey pubkey data to do ECDH with. - */ - public ECDH_direct(CardMngr cardManager, byte privkey, byte export, short transformation, byte type, byte[] pubkey) { - super(cardManager); - this.privkey = privkey; - this.export = export; - this.transformation = transformation; - this.type = type; - this.pubkey = pubkey; - - byte[] data = new byte[3 + pubkey.length]; - ByteUtil.setShort(data, 0, transformation); - data[2] = type; - System.arraycopy(pubkey, 0, data, 3, pubkey.length); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDH_DIRECT, privkey, export, data); - } - - @Override - public Response.ECDH send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.ECDH(response, getDescription(), elapsed, ECTesterApplet.KEYPAIR_REMOTE, privkey, export, transformation, type); - } - - @Override - public String getDescription() { - String algo = CardUtil.getKATypeString(type); - - String priv = privkey == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; - - String validity; - if (transformation == EC_Consts.TRANSFORMATION_NONE) { - validity = ""; - } else { - validity = String.format("(%s point)", CardUtil.getTransformation(transformation)); - } - return String.format("%s of external pubkey and %s privkey%s", algo, priv, validity); - } - } - - public static class ECDSA extends Command { - private byte keyPair; - private byte sigType; - private byte export; - private byte[] raw; - - /** - * Creates the INS_ECDSA instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param sigType Signature type to use - * @param export whether to export ECDSA signature - * @param raw data to sign, can be null, in which case random data is signed. - */ - public ECDSA(CardMngr cardManager, byte keyPair, byte sigType, byte export, byte[] raw) { - super(cardManager); - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - throw new IllegalArgumentException(); - } - - this.keyPair = keyPair; - this.sigType = sigType; - this.export = export; - this.raw = raw; - - int len = raw != null ? raw.length : 0; - byte[] data = new byte[3 + len]; - data[0] = sigType; - ByteUtil.setShort(data, 1, (short) len); - if (raw != null) { - System.arraycopy(raw, 0, data, 3, len); - } - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA, keyPair, export, data); - } - - @Override - public Response.ECDSA send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, export, raw); - } - - @Override - public String getDescription() { - String algo = CardUtil.getSigTypeString(sigType); - String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; - String data = raw == null ? "random" : "provided"; - return String.format("%s with %s keypair(%s data)", algo, key, data); - } - } - - public static class ECDSA_sign extends Command { - private byte keyPair; - private byte sigType; - private byte export; - private byte[] raw; - - /** - * Creates the INS_ECDSA_SIGN instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param sigType Signature type to use - * @param export whether to export ECDSA signature - * @param raw data to sign, can be null, in which case random data is signed. - */ - public ECDSA_sign(CardMngr cardManager, byte keyPair, byte sigType, byte export, byte[] raw) { - super(cardManager); - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - throw new IllegalArgumentException(); - } - - this.keyPair = keyPair; - this.sigType = sigType; - this.export = export; - this.raw = raw; - - int len = raw != null ? raw.length : 0; - byte[] data = new byte[3 + len]; - data[0] = sigType; - ByteUtil.setShort(data, 1, (short) len); - if (raw != null) { - System.arraycopy(raw, 0, data, 3, len); - } - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA_SIGN, keyPair, export, data); - } - - @Override - public Response.ECDSA send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, export, raw); - } - - @Override - public String getDescription() { - String algo = CardUtil.getSigTypeString(sigType); - String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; - String data = raw == null ? "random" : "provided"; - return String.format("%s signature with %s keypair(%s data)", algo, key, data); - } - } - - public static class ECDSA_verify extends Command { - private byte keyPair; - private byte sigType; - private byte[] raw; - private byte[] signature; - - /** - * Creates the INS_ECDSA_VERIFY instruction. - * - * @param cardManager cardManager to send APDU through - * @param keyPair keyPair to use for signing and verification (KEYPAIR_LOCAL || KEYPAIR_REMOTE) - * @param sigType Signature type to use - * @param raw data to sign - * @param signature signature data - */ - public ECDSA_verify(CardMngr cardManager, byte keyPair, byte sigType, byte[] raw, byte[] signature) { - super(cardManager); - if (keyPair == ECTesterApplet.KEYPAIR_BOTH) { - throw new IllegalArgumentException(); - } - if (raw == null || signature == null) { - throw new IllegalArgumentException(); - } - - this.keyPair = keyPair; - this.sigType = sigType; - this.raw = raw; - this.signature = signature; - - byte[] data = new byte[4 + raw.length + signature.length]; - ByteUtil.setShort(data, 0, (short) raw.length); - System.arraycopy(raw, 0, data, 2, raw.length); - ByteUtil.setShort(data, 2 + raw.length, (short) signature.length); - System.arraycopy(signature, 0, data, 2 + raw.length + 2, signature.length); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_ECDSA_VERIFY, keyPair, sigType, data); - } - - @Override - public Response.ECDSA send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.ECDSA(response, getDescription(), elapsed, keyPair, sigType, ECTesterApplet.EXPORT_FALSE, raw); - } - - @Override - public String getDescription() { - String algo = CardUtil.getSigTypeString(sigType); - String key = keyPair == ECTesterApplet.KEYPAIR_LOCAL ? "local" : "remote"; - String data = raw == null ? "random" : "provided"; - return String.format("%s verification with %s keypair(%s data)", algo, key, data); - } - } - - /** - * - */ - public static class Cleanup extends Command { - - /** - * @param cardManager cardManager to send APDU through - */ - public Cleanup(CardMngr cardManager) { - super(cardManager); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_CLEANUP, 0, 0, GOD_DAMN_JAVA_BUG_6474858_AND_GOD_DAMN_JAVA_12_MODULE_SYSTEM); - } - - @Override - public Response.Cleanup send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.Cleanup(response, getDescription(), elapsed); - } - - @Override - public String getDescription() { - return "Request JCSystem object deletion"; - } - } - - /** - * - */ - public static class GetInfo extends Command { - - /** - * @param cardManager cardManager to send APDU through - */ - public GetInfo(CardMngr cardManager) { - super(cardManager); - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_GET_INFO, 0, 0, GOD_DAMN_JAVA_BUG_6474858_AND_GOD_DAMN_JAVA_12_MODULE_SYSTEM); - } - - @Override - public Response.GetInfo send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.GetInfo(response, getDescription(), elapsed); - } - - @Override - public String getDescription() { - return "Get applet info"; - } - } - - /** - * - */ - public static class SetDryRunMode extends Command { - private byte dryRunMode; - - /** - * @param cardManager - * @param dryRunMode - */ - public SetDryRunMode(CardMngr cardManager, byte dryRunMode) { - super(cardManager); - this.dryRunMode = dryRunMode; - - this.cmd = new CommandAPDU(ECTesterApplet.CLA_ECTESTERAPPLET, ECTesterApplet.INS_SET_DRY_RUN_MODE, dryRunMode, 0, GOD_DAMN_JAVA_BUG_6474858_AND_GOD_DAMN_JAVA_12_MODULE_SYSTEM); - } - - @Override - public Response.SetDryRunMode send() throws CardException { - long elapsed = -System.nanoTime(); - ResponseAPDU response = cardManager.send(cmd); - elapsed += System.nanoTime(); - return new Response.SetDryRunMode(response, getDescription(), elapsed); - } - - @Override - public String getDescription() { - return (dryRunMode == ECTesterApplet.MODE_NORMAL ? "Disable" : "Enable") + " dry run mode"; - } - } -} - diff --git a/src/cz/crcs/ectester/reader/output/FileTestWriter.java b/src/cz/crcs/ectester/reader/output/FileTestWriter.java deleted file mode 100644 index 69e5f41..0000000 --- a/src/cz/crcs/ectester/reader/output/FileTestWriter.java +++ /dev/null @@ -1,53 +0,0 @@ -package cz.crcs.ectester.reader.output; - -import cz.crcs.ectester.common.output.TeeTestWriter; -import cz.crcs.ectester.common.output.TestWriter; - -import javax.xml.parsers.ParserConfigurationException; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.util.regex.Pattern; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class FileTestWriter extends TeeTestWriter { - - private static final Pattern PREFIX = Pattern.compile("(text|xml|yaml|yml):.+"); - - public FileTestWriter(String defaultFormat, boolean systemOut, String[] files) throws ParserConfigurationException, FileNotFoundException { - int fLength = files == null ? 0 : files.length; - writers = new TestWriter[systemOut ? fLength + 1 : fLength]; - if (systemOut) { - writers[0] = createWriter(defaultFormat, System.out); - } - for (int i = 0; i < fLength; ++i) { - String fName = files[i]; - String format = null; - if (PREFIX.matcher(fName).matches()) { - String[] split = fName.split(":", 2); - format = split[0]; - fName = split[1]; - } - writers[i + 1] = createWriter(format, new PrintStream(new FileOutputStream(fName))); - } - } - - private TestWriter createWriter(String format, PrintStream out) throws ParserConfigurationException { - if (format == null) { - return new TextTestWriter(out); - } - switch (format) { - case "text": - return new TextTestWriter(out); - case "xml": - return new XMLTestWriter(out); - case "yaml": - case "yml": - return new YAMLTestWriter(out); - default: - return null; - } - } -} diff --git a/src/cz/crcs/ectester/reader/output/ResponseWriter.java b/src/cz/crcs/ectester/reader/output/ResponseWriter.java deleted file mode 100644 index 85bf79a..0000000 --- a/src/cz/crcs/ectester/reader/output/ResponseWriter.java +++ /dev/null @@ -1,43 +0,0 @@ -package cz.crcs.ectester.reader.output; - -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.reader.response.Response; - -import java.io.PrintStream; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class ResponseWriter { - private PrintStream output; - - public ResponseWriter(PrintStream output) { - this.output = output; - } - - public String responseSuffix(Response r) { - StringBuilder suffix = new StringBuilder(); - for (int j = 0; j < r.getNumSW(); ++j) { - short sw = r.getSW(j); - if (sw != 0) { - suffix.append(" ").append(CardUtil.getSWString(sw)); - } - } - if (suffix.length() == 0) { - suffix.append(" [").append(CardUtil.getSW(r.getNaturalSW())).append(String.format(" 0x%04x", r.getNaturalSW())).append("]"); - } - return String.format("%4d ms ┃ %s", r.getDuration() / 1000000, suffix); - } - - public String responseString(Response r) { - String out = ""; - out += String.format("%-70s", r.getDescription()) + " ┃ "; - out += responseSuffix(r); - return out; - } - - public void outputResponse(Response r) { - output.println(responseString(r)); - output.flush(); - } -} diff --git a/src/cz/crcs/ectester/reader/output/TextTestWriter.java b/src/cz/crcs/ectester/reader/output/TextTestWriter.java deleted file mode 100644 index 2775647..0000000 --- a/src/cz/crcs/ectester/reader/output/TextTestWriter.java +++ /dev/null @@ -1,71 +0,0 @@ -package cz.crcs.ectester.reader.output; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.common.cli.Colors; -import cz.crcs.ectester.common.output.BaseTextTestWriter; -import cz.crcs.ectester.common.test.TestSuite; -import cz.crcs.ectester.common.test.Testable; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; -import cz.crcs.ectester.reader.test.CardTestSuite; -import cz.crcs.ectester.reader.test.CommandTestable; - -import javax.smartcardio.CardException; -import java.io.PrintStream; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class TextTestWriter extends BaseTextTestWriter { - private ResponseWriter writer; - - public TextTestWriter(PrintStream output) { - super(output); - this.writer = new ResponseWriter(output); - } - - @Override - protected String testableString(Testable t) { - if (t instanceof CommandTestable) { - CommandTestable cmd = (CommandTestable) t; - Response response = cmd.getResponse(); - if (response != null) { - return writer.responseSuffix(response); - } - } - return ""; - } - - @Override - protected String deviceString(TestSuite suite) { - if (suite instanceof CardTestSuite) { - CardTestSuite cardSuite = (CardTestSuite) suite; - StringBuilder sb = new StringBuilder(); - try { - sb.append("═══ ").append(Colors.underline("ECTester version:")).append(" ").append(ECTesterReader.VERSION).append(ECTesterReader.GIT_COMMIT).append(System.lineSeparator()); - Response.GetInfo info = new Command.GetInfo(cardSuite.getCard()).send(); - sb.append("═══ ").append(Colors.underline("ECTester applet version:")).append(" ").append(info.getVersion()).append(info.getBase() == ECTesterApplet.BASE_221 ? "" : " (extended length)").append(System.lineSeparator()); - sb.append("═══ ").append(Colors.underline("Card ATR:")).append(" ").append(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)).append(System.lineSeparator()); - sb.append("═══ ").append(Colors.underline("JavaCard version:")).append(" ").append(info.getJavaCardVersion()).append(System.lineSeparator()); - sb.append("═══ ").append(Colors.underline("Array sizes (apduBuf, ram, ram2, apduArr):")).append(" ").append(String.format("%d %d %d %d", info.getApduBufferLength(), info.getRamArrayLength(), info.getRamArray2Length(), info.getApduArrayLength())).append(System.lineSeparator()); - sb.append("═══ ").append(Colors.underline("Test options:")).append(" ").append(String.join(",", cardSuite.getCfg().testOptions)).append(System.lineSeparator()); - CardMngr.CPLC cplc = cardSuite.getCard().getCPLC(); - if (!cplc.values().isEmpty()) { - sb.append("═══ ").append(Colors.underline("Card CPLC data:")).append(System.lineSeparator()); - for (Map.Entry<CardMngr.CPLC.Field, byte[]> entry : cplc.values().entrySet()) { - CardMngr.CPLC.Field field = entry.getKey(); - byte[] value = entry.getValue(); - sb.append("═══ ").append(field.name()).append(": ").append(CardMngr.mapCPLCField(field, value)); - } - } - } catch (CardException ignored) { - } - return sb.toString(); - } - return ""; - } -} diff --git a/src/cz/crcs/ectester/reader/output/XMLTestWriter.java b/src/cz/crcs/ectester/reader/output/XMLTestWriter.java deleted file mode 100644 index fc41805..0000000 --- a/src/cz/crcs/ectester/reader/output/XMLTestWriter.java +++ /dev/null @@ -1,159 +0,0 @@ -package cz.crcs.ectester.reader.output; - -import cz.crcs.ectester.common.output.BaseXMLTestWriter; -import cz.crcs.ectester.common.test.TestSuite; -import cz.crcs.ectester.common.test.Testable; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; -import cz.crcs.ectester.reader.test.CardTestSuite; -import cz.crcs.ectester.reader.test.CommandTestable; -import org.w3c.dom.Element; - -import javax.smartcardio.CardException; -import javax.xml.parsers.ParserConfigurationException; -import java.io.OutputStream; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class XMLTestWriter extends BaseXMLTestWriter { - public XMLTestWriter(OutputStream output) throws ParserConfigurationException { - super(output); - } - - private Element commandElement(Command c) { - Element commandElem = doc.createElement("command"); - if (c == null) { - return commandElem; - } - - Element apdu = doc.createElement("apdu"); - apdu.setTextContent(ByteUtil.bytesToHex(c.getAPDU().getBytes())); - commandElem.appendChild(apdu); - - Element description = doc.createElement("desc"); - description.setTextContent(c.getDescription()); - commandElem.appendChild(description); - - return commandElem; - } - - private Element responseElement(Response r) { - Element responseElem = doc.createElement("response"); - if (r == null) { - return responseElem; - } - - responseElem.setAttribute("successful", r.successful() ? "true" : "false"); - - Element apdu = doc.createElement("apdu"); - apdu.setTextContent(ByteUtil.bytesToHex(r.getAPDU().getBytes())); - responseElem.appendChild(apdu); - - Element naturalSW = doc.createElement("natural-sw"); - naturalSW.setTextContent(String.valueOf(Short.toUnsignedInt(r.getNaturalSW()))); - responseElem.appendChild(naturalSW); - - Element sws = doc.createElement("sws"); - for (int i = 0; i < r.getNumSW(); ++i) { - Element sw = doc.createElement("sw"); - sw.setTextContent(String.valueOf(Short.toUnsignedInt(r.getSW(i)))); - sws.appendChild(sw); - } - responseElem.appendChild(sws); - - Element duration = doc.createElement("duration"); - duration.setTextContent(String.valueOf(r.getDuration())); - responseElem.appendChild(duration); - - Element description = doc.createElement("desc"); - description.setTextContent(r.getDescription()); - responseElem.appendChild(description); - - return responseElem; - } - - @Override - protected Element testableElement(Testable t) { - if (t instanceof CommandTestable) { - CommandTestable cmd = (CommandTestable) t; - Element result = doc.createElement("test"); - result.setAttribute("type", "command"); - result.appendChild(commandElement(cmd.getCommand())); - result.appendChild(responseElement(cmd.getResponse())); - return result; - } - return null; - } - - private Element cplcElement(CardMngr card) { - Element result = doc.createElement("cplc"); - try { - CardMngr.CPLC cplc = card.getCPLC(); - if (!cplc.values().isEmpty()) { - for (Map.Entry<CardMngr.CPLC.Field, byte[]> entry : cplc.values().entrySet()) { - CardMngr.CPLC.Field field = entry.getKey(); - byte[] value = entry.getValue(); - Element keyVal = doc.createElement(field.name()); - keyVal.setTextContent(ByteUtil.bytesToHex(value, false)); - result.appendChild(keyVal); - } - } - } catch (CardException ignored) { - } - return result; - } - - private Element appletElement(CardMngr card) { - Element result = doc.createElement("applet"); - try { - Response.GetInfo info = new Command.GetInfo(card).send(); - result.setAttribute("version", info.getVersion()); - result.setAttribute("javacard", String.format("%.1f", info.getJavaCardVersion())); - result.setAttribute("base", String.format("%#x", info.getBase())); - result.setAttribute("cleanup", String.valueOf(info.getCleanupSupport())); - Element arrays = doc.createElement("arrays"); - Element apduBuf = doc.createElement("length"); - apduBuf.setAttribute("name", "apduBuf"); - apduBuf.setTextContent(String.valueOf(info.getApduBufferLength())); - Element ramArray = doc.createElement("length"); - ramArray.setAttribute("name", "ramArray"); - ramArray.setTextContent(String.valueOf(info.getRamArrayLength())); - Element ramArray2 = doc.createElement("length"); - ramArray2.setAttribute("name", "ramArray2"); - ramArray2.setTextContent(String.valueOf(info.getRamArray2Length())); - Element apduArray = doc.createElement("length"); - apduArray.setAttribute("name", "apduArray"); - apduArray.setTextContent(String.valueOf(info.getApduArrayLength())); - arrays.appendChild(apduBuf); - arrays.appendChild(ramArray); - arrays.appendChild(ramArray2); - arrays.appendChild(apduArray); - result.appendChild(arrays); - } catch (CardException ignored) { - } - return result; - } - - @Override - protected Element deviceElement(TestSuite suite) { - if (suite instanceof CardTestSuite) { - CardTestSuite cardSuite = (CardTestSuite) suite; - Element result = doc.createElement("device"); - result.setAttribute("type", "card"); - result.setAttribute("ectester", ECTesterReader.VERSION + ECTesterReader.GIT_COMMIT); - result.appendChild(cplcElement(cardSuite.getCard())); - result.appendChild(appletElement(cardSuite.getCard())); - - Element atr = doc.createElement("ATR"); - atr.setTextContent(ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)); - result.appendChild(atr); - return result; - } - return null; - } -}
\ No newline at end of file diff --git a/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java b/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java deleted file mode 100644 index 56ecb71..0000000 --- a/src/cz/crcs/ectester/reader/output/YAMLTestWriter.java +++ /dev/null @@ -1,119 +0,0 @@ -package cz.crcs.ectester.reader.output; - -import cz.crcs.ectester.common.output.BaseYAMLTestWriter; -import cz.crcs.ectester.common.test.TestSuite; -import cz.crcs.ectester.common.test.Testable; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; -import cz.crcs.ectester.reader.test.CardTestSuite; -import cz.crcs.ectester.reader.test.CommandTestable; - -import javax.smartcardio.CardException; -import java.io.PrintStream; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class YAMLTestWriter extends BaseYAMLTestWriter { - public YAMLTestWriter(PrintStream output) { - super(output); - } - - private Map<String, Object> commandObject(Command c) { - Map<String, Object> commandObj = new LinkedHashMap<>(); - if (c == null) { - return commandObj; - } - commandObj.put("apdu", ByteUtil.bytesToHex(c.getAPDU().getBytes())); - commandObj.put("desc", c.getDescription()); - return commandObj; - } - - private Map<String, Object> responseObject(Response r) { - Map<String, Object> responseObj = new LinkedHashMap<>(); - if (r == null) { - return responseObj; - } - responseObj.put("successful", r.successful()); - responseObj.put("apdu", ByteUtil.bytesToHex(r.getAPDU().getBytes())); - responseObj.put("natural_sw", Short.toUnsignedInt(r.getNaturalSW())); - List<Integer> sws = new LinkedList<>(); - for (int i = 0; i < r.getNumSW(); ++i) { - sws.add(Short.toUnsignedInt(r.getSW(i))); - } - responseObj.put("sws", sws); - responseObj.put("duration", r.getDuration()); - responseObj.put("desc", r.getDescription()); - return responseObj; - } - - @Override - protected Map<String, Object> testableObject(Testable t) { - if (t instanceof CommandTestable) { - CommandTestable cmd = (CommandTestable) t; - Map<String, Object> result = new LinkedHashMap<>(); - result.put("type", "command"); - result.put("command", commandObject(cmd.getCommand())); - result.put("response", responseObject(cmd.getResponse())); - return result; - } - return null; - } - - private Map<String, Object> cplcObject(CardMngr card) { - Map<String, Object> result = new LinkedHashMap<>(); - try { - CardMngr.CPLC cplc = card.getCPLC(); - if (!cplc.values().isEmpty()) { - for (Map.Entry<CardMngr.CPLC.Field, byte[]> entry : cplc.values().entrySet()) { - CardMngr.CPLC.Field field = entry.getKey(); - byte[] value = entry.getValue(); - result.put(field.name(), ByteUtil.bytesToHex(value, false)); - } - } - } catch (CardException ignored) { - } - return result; - } - - private Map<String, Object> appletObject(CardMngr card) { - Map<String, Object> result = new LinkedHashMap<>(); - try { - Response.GetInfo info = new Command.GetInfo(card).send(); - result.put("version", info.getVersion()); - result.put("javacard", info.getJavaCardVersion()); - result.put("base", info.getBase()); - result.put("cleanup", info.getCleanupSupport()); - Map<String, Integer> arrays = new LinkedHashMap<>(); - arrays.put("apduBuf", Short.toUnsignedInt(info.getApduBufferLength())); - arrays.put("ramArray", Short.toUnsignedInt(info.getRamArrayLength())); - arrays.put("ramArray2", Short.toUnsignedInt(info.getRamArray2Length())); - arrays.put("apduArray", Short.toUnsignedInt(info.getApduArrayLength())); - result.put("arrays", arrays); - } catch (CardException ignored) { - } - return result; - } - - @Override - protected Map<String, Object> deviceObject(TestSuite suite) { - if (suite instanceof CardTestSuite) { - CardTestSuite cardSuite = (CardTestSuite) suite; - Map<String, Object> result = new LinkedHashMap<>(); - result.put("type", "card"); - result.put("ectester", ECTesterReader.VERSION + ECTesterReader.GIT_COMMIT); - result.put("cplc", cplcObject(cardSuite.getCard())); - result.put("applet", appletObject(cardSuite.getCard())); - result.put("ATR", ByteUtil.bytesToHex(cardSuite.getCard().getATR().getBytes(), false)); - return result; - } - return null; - } -} diff --git a/src/cz/crcs/ectester/reader/response/Response.java b/src/cz/crcs/ectester/reader/response/Response.java deleted file mode 100644 index f36d087..0000000 --- a/src/cz/crcs/ectester/reader/response/Response.java +++ /dev/null @@ -1,526 +0,0 @@ -package cz.crcs.ectester.reader.response; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.util.ByteUtil; -import javacard.framework.ISO7816; - -import javax.smartcardio.ResponseAPDU; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public abstract class Response { - private ResponseAPDU resp; - private long time; - private short[] sws; - private int numSW = 0; - private byte[][] params; - private boolean success = true; - private boolean error = false; - private String description; - - public Response(ResponseAPDU response, String description, long time) { - this.resp = response; - this.description = description; - this.time = time; - } - - boolean parse(int numSW, int numParams) { - this.numSW = numSW; - this.sws = new short[numSW]; - - byte[] data = resp.getData(); - int offset = 0; - - //parse SWs in response - for (int i = 0; i < numSW; ++i) { - if (getLength() >= (offset + 2)) { - short sw = ByteUtil.getShort(data, offset); - offset += 2; - sws[i] = sw; - if (sw != ISO7816.SW_NO_ERROR) { - success = false; - } - } else { - success = false; - error = true; - } - } - - if ((short) resp.getSW() != ISO7816.SW_NO_ERROR) { - success = false; - error = true; - } - - - //try to parse numParams.. - params = new byte[numParams][]; - for (int i = 0; i < numParams; i++) { - if (data.length - offset < 2) { - success = false; - error = true; - break; - } - short paramLength = ByteUtil.getShort(data, offset); - offset += 2; - if (data.length < offset + paramLength) { - error = true; - success = false; - break; - } - params[i] = new byte[paramLength]; - System.arraycopy(data, offset, params[i], 0, paramLength); - offset += paramLength; - } - return success; - } - - public ResponseAPDU getAPDU() { - return resp; - } - - public byte[] getData() { - return resp.getData(); - } - - public long getDuration() { - return time; - } - - public short getNaturalSW() { - return (short) resp.getSW(); - } - - public short[] getSWs() { - return sws; - } - - public short getSW(int index) { - return sws[index]; - } - - public int getNumSW() { - return numSW; - } - - public boolean hasParam(int index) { - return params.length >= index + 1 && params[index] != null; - } - - public int getParamLength(int index) { - return params[index].length; - } - - public byte[] getParam(int index) { - return params[index]; - } - - public byte[][] getParams() { - return params; - } - - public int getLength() { - return resp.getNr(); - } - - public boolean successful() { - return this.success; - } - - public boolean error() { - return this.error; - } - - public String getDescription() { - return description; - } - - /** - * - */ - public static class AllocateKeyAgreement extends Response { - private byte kaType; - - public AllocateKeyAgreement(ResponseAPDU response, String description, long time, byte kaType) { - super(response, description, time); - this.kaType = kaType; - - parse(1, 0); - } - } - - /** - * - */ - public static class AllocateSignature extends Response { - private byte sigType; - - public AllocateSignature(ResponseAPDU response, String description, long time, byte sigType) { - super(response, description, time); - this.sigType = sigType; - - parse(1, 0); - } - } - - /** - * - */ - public static class Allocate extends Response { - private byte keyPair; - private short keyLength; - private byte keyClass; - - public Allocate(ResponseAPDU response, String description, long time, byte keyPair, short keyLength, byte keyClass) { - super(response, description, time); - this.keyPair = keyPair; - this.keyLength = keyLength; - this.keyClass = keyClass; - - int pairs = 0; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; - parse(pairs, 0); - } - } - - /** - * - */ - public static class Clear extends Response { - private byte keyPair; - - public Clear(ResponseAPDU response, String description, long time, byte keyPair) { - super(response, description, time); - this.keyPair = keyPair; - - int pairs = 0; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; - parse(pairs, 0); - } - } - - /** - * - */ - public static class Set extends Response { - private byte keyPair; - private byte curve; - private short parameters; - - public Set(ResponseAPDU response, String description, long time, byte keyPair, byte curve, short parameters) { - super(response, description, time); - this.keyPair = keyPair; - this.curve = curve; - this.parameters = parameters; - - int pairs = 0; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; - - parse(pairs, 0); - } - } - - /** - * - */ - public static class Transform extends Response { - private byte keyPair; - private byte key; - private short params; - private short transformation; - - public Transform(ResponseAPDU response, String description, long time, byte keyPair, byte key, short params, short transformation) { - super(response, description, time); - this.keyPair = keyPair; - this.key = key; - this.params = params; - this.transformation = transformation; - - int pairs = 0; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) pairs++; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) pairs++; - - parse(pairs, 0); - } - } - - /** - * - */ - public static class Generate extends Response { - private byte keyPair; - - public Generate(ResponseAPDU response, String description, long time, byte keyPair) { - super(response, description, time); - this.keyPair = keyPair; - - int generated = 0; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) generated++; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) generated++; - parse(generated, 0); - } - } - - /** - * - */ - public static class Export extends Response { - private byte keyPair; - private byte key; - private short parameters; - - public Export(ResponseAPDU response, String description, long time, byte keyPair, byte key, short parameters) { - super(response, description, time); - this.keyPair = keyPair; - this.key = key; - this.parameters = parameters; - - int exported = 0; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) exported++; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) exported++; - int keys = 0; - if ((key & EC_Consts.KEY_PUBLIC) != 0) keys++; - if ((key & EC_Consts.KEY_PRIVATE) != 0) keys++; - int paramCount = 0; - short mask = EC_Consts.PARAMETER_FP; - while (mask <= EC_Consts.PARAMETER_K) { - if ((mask & parameters) != 0) { - paramCount++; - } - mask = (short) (mask << 1); - } - int other = 0; - if ((key & EC_Consts.KEY_PUBLIC) != 0 && (parameters & EC_Consts.PARAMETER_W) != 0) other++; - if ((key & EC_Consts.KEY_PRIVATE) != 0 && (parameters & EC_Consts.PARAMETER_S) != 0) other++; - - parse(exported, exported * keys * paramCount + exported * other); - } - - private int getIndex(byte keyPair, short param) { - byte pair = ECTesterApplet.KEYPAIR_LOCAL; - int index = 0; - while (pair <= ECTesterApplet.KEYPAIR_REMOTE) { - short mask = EC_Consts.PARAMETER_FP; - while (mask <= EC_Consts.PARAMETER_S) { - if (pair == keyPair && param == mask) { - return index; - } - if ((parameters & mask) != 0 && (pair & this.keyPair) != 0) { - if (mask == EC_Consts.PARAMETER_W) { - if ((key & EC_Consts.KEY_PUBLIC) != 0) - index++; - } else if (mask == EC_Consts.PARAMETER_S) { - if ((key & EC_Consts.KEY_PRIVATE) != 0) - index++; - } else { - index++; - } - } - mask = (short) (mask << 1); - } - - pair = (byte) (pair << 1); - } - return -1; - } - - public boolean hasParameters(byte keyPair, short params) { - if ((keyPair & this.keyPair) == 0 || (params ^ parameters) != 0) { - return false; - } - short param = EC_Consts.PARAMETER_FP; - while (param <= EC_Consts.PARAMETER_S) { - short masked = (short) (param & params); - if (masked != 0 && !hasParameter(keyPair, masked)) { - return false; - } - param = (short) (param << 1); - } - return true; - } - - public boolean hasParameter(byte keyPair, short param) { - if ((keyPair & this.keyPair) == 0 || (parameters & param) == 0) { - return false; - } - int index = getIndex(keyPair, param); - return index != -1 && hasParam(index); - } - - public byte[] getParameter(byte keyPair, short param) { - return getParam(getIndex(keyPair, param)); - } - } - - /** - * - */ - public static class ECDH extends Response { - private byte pubkey; - private byte privkey; - private byte export; - private short transformation; - private byte type; - - public ECDH(ResponseAPDU response, String description, long time, byte pubkey, byte privkey, byte export, short transformation, byte type) { - super(response, description, time); - this.pubkey = pubkey; - this.privkey = privkey; - this.export = export; - this.transformation = transformation; - this.type = type; - - parse(1, (export == ECTesterApplet.EXPORT_TRUE) ? 1 : 0); - } - - public short getTransformation() { - return transformation; - } - - public byte getType() { - return type; - } - - public boolean hasSecret() { - return hasParam(0); - } - - public byte[] getSecret() { - return getParam(0); - } - - public int secretLength() { - return getParamLength(0); - } - } - - /** - * - */ - public static class ECDSA extends Response { - private byte keyPair; - private byte sigType; - private byte export; - private byte[] raw; - - public ECDSA(ResponseAPDU response, String description, long time, byte keyPair, byte sigType, byte export, byte[] raw) { - super(response, description, time); - this.keyPair = keyPair; - this.sigType = sigType; - this.export = export; - this.raw = raw; - - parse(1, (export == ECTesterApplet.EXPORT_TRUE) ? 1 : 0); - } - - public boolean hasSignature() { - return hasParam(0); - } - - public byte[] getSignature() { - return getParam(0); - } - } - - /** - * - */ - public static class Cleanup extends Response { - - public Cleanup(ResponseAPDU response, String description, long time) { - super(response, description, time); - - parse(1, 0); - } - } - - /** - * - */ - public static class GetInfo extends Response { - private short base; - private short jcVersion; - private short cleanupSupport; - private short apduBufferLength; - private short ramArrayLength; - private short ramArray2Length; - private short apduArrayLength; - - public GetInfo(ResponseAPDU response, String description, long time) { - super(response, description, time); - - parse(1, 1); - int offset = 2 + 2 + getParamLength(0); - byte[] data = getData(); - base = ByteUtil.getShort(data, offset); - offset += 2; - jcVersion = ByteUtil.getShort(data, offset); - offset += 2; - cleanupSupport = ByteUtil.getShort(data, offset); - offset += 2; - apduBufferLength = ByteUtil.getShort(data, offset); - offset += 2; - ramArrayLength = ByteUtil.getShort(data, offset); - offset += 2; - ramArray2Length = ByteUtil.getShort(data, offset); - offset += 2; - apduArrayLength = ByteUtil.getShort(data, offset); - } - - public String getVersion() { - return new String(getParam(0)); - } - - public short getBase() { - return base; - } - - public float getJavaCardVersion() { - byte major = (byte) (jcVersion >> 8); - byte minor = (byte) (jcVersion & 0xff); - int minorSize; - if (minor == 0) { - minorSize = 1; - } else { - minorSize = (int) Math.ceil(Math.log10(minor)); - } - return (major + ((float) (minor) / (minorSize * 10))); - } - - public boolean getCleanupSupport() { - return cleanupSupport == 1; - } - - public short getApduBufferLength() { - return apduBufferLength; - } - - public short getRamArrayLength() { - return ramArrayLength; - } - - public short getRamArray2Length() { - return ramArray2Length; - } - - public short getApduArrayLength() { - return apduArrayLength; - } - } - - /** - * - */ - public static class SetDryRunMode extends Response { - - public SetDryRunMode(ResponseAPDU response, String description, long time) { - super(response, description, time); - - parse(1, 0); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java b/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java deleted file mode 100644 index d1eb2b1..0000000 --- a/src/cz/crcs/ectester/reader/test/CardCofactorSuite.java +++ /dev/null @@ -1,65 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardCofactorSuite extends CardTestSuite { - public CardCofactorSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "cofactor", new String[]{"preset", "random"}, "The cofactor test suite tests whether the card correctly rejects points on the curve", - "but not in the subgroup generated by the generator(so of small order, dividing the cofactor) during ECDH."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "cofactor"); - Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { - EC_Curve curve = e.getKey(); - List<EC_Key.Public> keys = e.getValue(); - - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS); - Test generate = setupKeypairs(curve, ExpectedValue.SUCCESS, ECTesterApplet.KEYPAIR_LOCAL); - - Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); - - List<Test> ecdhTests = new LinkedList<>(); - for (EC_Key.Public pub : keys) { - Test setPub = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE); - Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with cofactor pubkey.", setPub, ecdh); - Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); - Test rawEcdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on non-generator subgroup.", "Card incorrectly accepted point on non-generator subgroup."); - ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " cofactor key test.", objectEcdh, rawEcdh)); - } - Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with public points on non-generator subgroup.", ecdhTests.toArray(new Test[0])); - - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", prepare, ecdh, cleanup)); - } else { - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Cofactor test of " + curve.getId() + ".", prepare, ecdh)); - } - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java b/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java deleted file mode 100644 index babe732..0000000 --- a/src/cz/crcs/ectester/reader/test/CardCompositeSuite.java +++ /dev/null @@ -1,122 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardCompositeSuite extends CardTestSuite { - - public CardCompositeSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "composite", new String[]{"preset", "random"}, "The composite suite runs ECDH over curves with composite order.", - "Various types of compositeness is tested: smooth numbers, Carmichael pseudo-prime, prime square, product of two large primes."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_Key> keys = EC_Store.getInstance().getObjects(EC_Key.class, "composite"); - Map<EC_Curve, List<EC_Key>> mappedKeys = EC_Store.mapKeyToCurve(keys.values()); - for (Map.Entry<EC_Curve, List<EC_Key>> curveKeys : mappedKeys.entrySet()) { - EC_Curve curve = curveKeys.getKey(); - List<Test> tests = new LinkedList<>(); - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate)); - continue; - } - tests.add(allocate); - tests.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY)); - - String name; - if (cfg.testOptions.contains("preset")) { - name = "preset semi-random private key"; - } else { - name = "generated private key"; - } - tests.add(setupKeypairs(curve, ExpectedValue.ANY, ECTesterApplet.KEYPAIR_LOCAL)); - for (EC_Key key : curveKeys.getValue()) { - Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, key.flatten()); - Test ecdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a composite order curve.", "Card incorrectly does ECDH over a composite order curve, leaks bits of private key."); - tests.add(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ", with " + name + ", " + key.getDesc(), ecdh)); - } - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Composite test of " + curve.getId() + ".", tests.toArray(new Test[0]))); - } - - - Map<String, EC_Curve> results = EC_Store.getInstance().getObjects(EC_Curve.class, "composite"); - Map<String, List<EC_Curve>> groups = EC_Store.mapToPrefix(results.values()); - /* Test the whole curves with both keypairs generated on card(no small-order public points provided). - */ - List<EC_Curve> wholeCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("whole")).findFirst().get().getValue(); - testGroup(wholeCurves, "Composite generator order", ExpectedValue.FAILURE, "Card rejected to do ECDH with composite order generator.", "Card did not reject to do ECDH with composite order generator."); - - /* Also test having a G of small order, so small R. - */ - List<EC_Curve> smallRCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("small")).findFirst().get().getValue(); - testGroup(smallRCurves, "Small generator order", ExpectedValue.FAILURE, "Card correctly rejected to do ECDH over a small order generator.", "Card incorrectly does ECDH over a small order generator."); - - /* Test increasingly larger prime R, to determine where/if card behavior changes. - */ - List<EC_Curve> varyingCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("varying")).findFirst().get().getValue(); - testGroup(varyingCurves, null, ExpectedValue.ANY, "", ""); - - /* Also test having a G of large but composite order, R = p * q, - */ - List<EC_Curve> pqCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("pq")).findFirst().get().getValue(); - testGroup(pqCurves, null, ExpectedValue.ANY, "", ""); - - /* Also test having G or large order being a Carmichael pseudoprime, R = p * q * r, - */ - List<EC_Curve> ppCurves = groups.entrySet().stream().filter((e) -> e.getKey().equals("pp")).findFirst().get().getValue(); - testGroup(ppCurves, "Generator order = Carmichael pseudo-prime", ExpectedValue.ANY, "", ""); - - /* Also test rg0 curves. - */ - List<EC_Curve> rg0Curves = groups.entrySet().stream().filter((e) -> e.getKey().equals("rg0")).findFirst().get().getValue(); - testGroup(rg0Curves, null, ExpectedValue.ANY, "", ""); - } - - private void testGroup(List<EC_Curve> curves, String testName, ExpectedValue dhValue, String ok, String nok) throws Exception { - for (EC_Curve curve : curves) { - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.ANY); - Test generate = setupKeypairs(curve, ExpectedValue.ANY, ECTesterApplet.KEYPAIR_BOTH); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), dhValue, ok, nok); - Test ecdsa = CommandTest.expect(new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), dhValue, ok, nok); - - String description; - if (testName == null) { - description = curve.getDesc() + " test of " + curve.getId() + "."; - } else { - description = testName + " test of " + curve.getId() + "."; - } - - Test perform = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH and ECDSA.", ecdh, ecdsa); - - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, description, allocate, set, generate, perform, cleanup)); - } else { - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, description, allocate, set, generate, perform)); - } - } - - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java b/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java deleted file mode 100644 index 9eed814..0000000 --- a/src/cz/crcs/ectester/reader/test/CardCompressionSuite.java +++ /dev/null @@ -1,155 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; -import javacard.security.KeyPair; - -import java.security.spec.ECPoint; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardCompressionSuite extends CardTestSuite { - public CardCompressionSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "compression", null, "The compression test suite tests cards support for compressed points in ECDH (as per ANSI X9.62).", - "It also tests for handling of bogus input in ECDH by using the point at infinity and a hybrid point with the y coordinate corrupted.", - "It also tests handling of compressed point in ECDH, where the x coordinate is invalid and therefore", - "a quadratic non-residue will be computed and (square root-ed) during decompression."); - } - - @Override - protected void runTests() throws Exception { - //iterate over default curve sizes - // for Fp - // - allocate, set custom curve, generate keypairs, -> export generated. - // - test ecdh with local and remote simply(no compression) - // - test local privkey, remote pubkey (compressed) - // - test local privkey, remote pubkey (hybrid) - // - test local privkey, remote pubkey (hybrid with wrong y) - // - test local privkey, remote pubkey (point at infinity) - if (cfg.primeField) { - runCompression(KeyPair.ALG_EC_FP); - } - // for F2m - // - allocate, set custom curve, generate keypairs, -> export generated. - // - test ecdh with local and remote simply(no compression) - // - test local privkey, remote pubkey (compressed) - // - test local privkey, remote pubkey (hybrid) - // - test local privkey, remote pubkey (hybrid with wrong y) - // - test local privkey, remote pubkey (point at infinity) - if (cfg.binaryField) { - runCompression(KeyPair.ALG_EC_F2M); - } - - // Now, do ECDH over SECG curves and give the implementation a compressed key that is not a quadratic residue in - // decompression. - runNonResidue(); - } - - private void runCompression(byte field) throws Exception { - short[] keySizes = field == KeyPair.ALG_EC_FP ? EC_Consts.FP_SIZES : EC_Consts.F2M_SIZES; - short domain = field == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; - - for (short keyLength : keySizes) { - String spec = keyLength + "b " + CardUtil.getKeyTypeString(field); - byte curveId = EC_Consts.getCurve(keyLength, field); - - Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), Result.ExpectedValue.SUCCESS)); - if (!allocateFirst.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for compression test on " + spec + ".", allocateFirst)); - continue; - } - - List<Test> compressionTests = new LinkedList<>(); - compressionTests.add(allocateFirst); - Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curveId, domain, null), Result.ExpectedValue.SUCCESS)); - Test genCustom = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), Result.ExpectedValue.SUCCESS)); - compressionTests.add(setCustom); - compressionTests.add(genCustom); - - Response.Export key = new Command.Export(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W).send(); - byte[] pubkey = key.getParameter(ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PUBLIC); - EC_Curve secgCurve = EC_Store.getInstance().getObject(EC_Curve.class, "secg", CardUtil.getCurveName(curveId)); - ECPoint pub; - try { - pub = ECUtil.fromX962(pubkey, secgCurve.toCurve()); - } catch (IllegalArgumentException iae) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "", compressionTests.toArray(new Test[0]))); - continue; - } - - List<Test> kaTests = new LinkedList<>(); - for (byte kaType : EC_Consts.KA_TYPES) { - List<Test> thisTests = new LinkedList<>(); - Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), Result.ExpectedValue.SUCCESS)); - if (allocate.ok()) { - Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), Result.ExpectedValue.SUCCESS)); - - thisTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement setup and basic test.", allocate, ka)); - if (ka.ok()) { - // tests of the good stuff - Test kaCompressed = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS, kaType), Result.ExpectedValue.SUCCESS); - Test kaHybrid = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS_HYBRID, kaType), Result.ExpectedValue.SUCCESS); - thisTests.add(CompoundTest.any(Result.ExpectedValue.SUCCESS, "Tests of compressed and hybrid form.", kaCompressed, kaHybrid)); - - // tests the bad stuff here - byte[] pubHybrid = ECUtil.toX962Hybrid(pub, keyLength); - pubHybrid[pubHybrid.length - 1] ^= 1; - byte[] pubHybridEncoded = ByteUtil.prependLength(pubHybrid); - Test kaBadHybrid = CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType, pubHybridEncoded), Result.ExpectedValue.FAILURE); - - byte[] pubInfinityEncoded = {0x01, 0x00}; - Test kaBadInfinity = CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType, pubInfinityEncoded), Result.ExpectedValue.FAILURE); - thisTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests of corrupted hybrid form and infinity.", kaBadHybrid, kaBadInfinity)); - } - kaTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyAgreement tests of " + CardUtil.getKATypeString(kaType) + ".", thisTests.toArray(new Test[0]))); - } - } - compressionTests.addAll(kaTests); - if (cfg.cleanup) { - compressionTests.add(CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY)); - } - - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Compression test of " + spec + ".", compressionTests.toArray(new Test[0]))); - } - } - - private void runNonResidue() { - Map<String, EC_Key.Public> otherKeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "misc"); - List<EC_Key.Public> compressionKeys = EC_Store.mapToPrefix(otherKeys.values()).get("compression"); - - for (EC_Key.Public key : compressionKeys) { - EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, key.getCurve()); - List<Test> tests = new LinkedList<>(); - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for non-residue test on " + curve.getBits() + "b " + curve.getId() + ".", allocate)); - continue; - } - tests.add(allocate); - tests.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS)); - tests.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS)); - byte[] pointData = ECUtil.toX962Compressed(key.getParam(EC_Consts.PARAMETER_W)); - byte[] pointDataEncoded = ByteUtil.prependLength(pointData); - tests.add(CommandTest.expect(new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pointDataEncoded), Result.ExpectedValue.FAILURE)); - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Non-residue test of " + curve.getId() + ".", tests.toArray(new Test[0]))); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java b/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java deleted file mode 100644 index 8814c37..0000000 --- a/src/cz/crcs/ectester/reader/test/CardDefaultSuite.java +++ /dev/null @@ -1,141 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import javacard.security.KeyPair; - -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; -import static cz.crcs.ectester.common.test.Result.Value; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardDefaultSuite extends CardTestSuite { - - public CardDefaultSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "default", null, "The default test suite tests basic support and performance of ECDH and ECDSA."); - } - - @Override - protected void runTests() throws Exception { - if (cfg.primeField) { - runDefault(KeyPair.ALG_EC_FP); - } - if (cfg.binaryField) { - runDefault(KeyPair.ALG_EC_F2M); - } - } - - private void runDefault(byte field) throws Exception { - short[] keySizes = field == KeyPair.ALG_EC_FP ? EC_Consts.FP_SIZES : EC_Consts.F2M_SIZES; - short domain = field == KeyPair.ALG_EC_FP ? EC_Consts.PARAMETERS_DOMAIN_FP : EC_Consts.PARAMETERS_DOMAIN_F2M; - for (short keyLength : keySizes) { - - List<Test> supportTests = new LinkedList<>(); - Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), ExpectedValue.SUCCESS)); - if (!allocateFirst.ok()) { - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + keyLength + "b " + CardUtil.getKeyTypeString(field) + ".", allocateFirst)); - continue; - } - supportTests.add(allocateFirst); - - Test genDefault = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.SUCCESS)); - Test allocateSecond = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, field), ExpectedValue.SUCCESS)); - Test setCustom = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.getCurve(keyLength, field), domain, null), ExpectedValue.SUCCESS)); - Test genCustom = runTest(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.SUCCESS)); - supportTests.add(genDefault); - supportTests.add(allocateSecond); - supportTests.add(setCustom); - supportTests.add(genCustom); - - List<Test> kaTests = new LinkedList<>(); - for (byte kaType : EC_Consts.KA_TYPES) { - Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), ExpectedValue.SUCCESS)); - if (allocate.ok()) { - Command ecdh = new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType); - Test ka = runTest(CommandTest.expect(ecdh, ExpectedValue.SUCCESS)); - Test kaCompressed = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_COMPRESS, kaType), ExpectedValue.SUCCESS)); - - String kaDesc = "Test of the " + CardUtil.getKATypeString(kaType) + " KeyAgreement."; - Function<Test[], Result> kaCallback = (tests) -> { - if (tests[1].ok() || tests[2].ok()) { - return new Result(Value.SUCCESS, "Some ECDH is supported."); - } else { - return new Result(Value.FAILURE, "ECDH failed."); - } - }; - - Test compound; - if (ka.ok()) { - Test perfTest = runTest(PerformanceTest.repeat(this.card, ecdh, 10)); - compound = runTest(CompoundTest.function(kaCallback, kaDesc, allocate, ka, kaCompressed, perfTest)); - } else { - compound = runTest(CompoundTest.function(kaCallback, kaDesc, allocate, ka, kaCompressed)); - } - - kaTests.add(compound); - } else { - runTest(allocate); - kaTests.add(allocate); - } - } - Test kaTest = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "KeyAgreement tests.", kaTests.toArray(new Test[0]))); - supportTests.add(kaTest); - - List<Test> signTests = new LinkedList<>(); - for (byte sigType : EC_Consts.SIG_TYPES) { - Test allocate = runTest(CommandTest.expect(new Command.AllocateSignature(this.card, sigType), ExpectedValue.SUCCESS)); - if (allocate.ok()) { - Command ecdsa = new Command.ECDSA(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, ECTesterApplet.EXPORT_FALSE, null); - Test expect = runTest(CommandTest.expect(ecdsa, ExpectedValue.SUCCESS)); - - String signDesc = "Test of the " + CardUtil.getSigTypeString(sigType) + " signature."; - - Random rand = new Random(); - byte[] sigData = new byte[64]; - rand.nextBytes(sigData); - - Test compound; - if (expect.ok()) { - Command ecdsaSign = new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, ECTesterApplet.EXPORT_TRUE, sigData); - PerformanceTest signTest = runTest(PerformanceTest.repeat(this.card, "Sign", ecdsaSign, 10)); - byte[] signature = signTest.getResponses()[0].getParam(0); - Command ecdsaVerify = new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_LOCAL, sigType, sigData, signature); - PerformanceTest verifyTest = runTest(PerformanceTest.repeat(this.card, "Verify", ecdsaVerify, 10)); - compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect, signTest, verifyTest)); - } else { - compound = runTest(CompoundTest.all(ExpectedValue.SUCCESS, signDesc, allocate, expect)); - } - signTests.add(compound); - } else { - signTests.add(allocate); - } - } - Test signTest = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "Signature tests.", signTests.toArray(new Test[0]))); - supportTests.add(signTest); - ExpectedValue[] testExpects = {ExpectedValue.SUCCESS, ExpectedValue.ANY, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS, ExpectedValue.SUCCESS}; - List<ExpectedValue> expects = Stream.of(testExpects).collect(Collectors.toList()); - if (cfg.cleanup) { - supportTests.add(CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY)); - expects.add(ExpectedValue.ANY); - } - - doTest(CompoundTest.mask(expects.toArray(new ExpectedValue[0]), "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(field) + " support.", supportTests.toArray(new Test[0]))); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java b/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java deleted file mode 100644 index f2e73b6..0000000 --- a/src/cz/crcs/ectester/reader/test/CardDegenerateSuite.java +++ /dev/null @@ -1,69 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardDegenerateSuite extends CardTestSuite { - - public CardDegenerateSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "degenerate", null, "The degenerate suite tests whether the card rejects points outside of the curve during ECDH.", - "The tested points lie on a part of the plane for which some Edwards, Hessian and Huff form addition formulas degenerate into exponentiation in the base finite field."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "degenerate"); - Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { - EC_Curve curve = e.getKey(); - List<EC_Key.Public> keys = e.getValue(); - - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getId() + ".", allocate)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); - - Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); - - List<Test> ecdhTests = new LinkedList<>(); - for (EC_Key.Public pub : keys) { - Test setPub = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve."); - Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with degenerate pubkey.", setPub, ecdh); - Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); - Test rawEcdh = CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on degenerate curve.", "Card incorrectly accepted point on degenerate curve."); - ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " degenerate key test.", objectEcdh, rawEcdh)); - //TODO: actually get the result of ECDH here, as well as export privkey and compare to exponentiation in Fp^*. - } - Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with degenerate public points.", ecdhTests.toArray(new Test[0])); - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", prepare, ecdh, cleanup)); - } else { - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Degenerate curve test of " + curve.getId() + ".", prepare, ecdh)); - } - - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java b/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java deleted file mode 100644 index 9257b3d..0000000 --- a/src/cz/crcs/ectester/reader/test/CardEdgeCasesSuite.java +++ /dev/null @@ -1,336 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_KAResult; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.ec.EC_Params; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.test.TestCallback; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; -import javacard.security.CryptoException; -import javacard.security.KeyPair; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.*; -import java.util.stream.Collectors; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardEdgeCasesSuite extends CardTestSuite { - public CardEdgeCasesSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "edge-cases", null, "The edge-cases test suite tests various inputs to ECDH which may cause an implementation to achieve a certain edge-case state during it.", - "Some of the data is from the google/Wycheproof project. Tests include CVE-2017-10176 and CVE-2017-8932.", - "Also tests values of the private key and public key that would trigger the OpenSSL modular multiplication bug on the P-256 curve.", - "Various edge private key values are also tested."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_KAResult> results = EC_Store.getInstance().getObjects(EC_KAResult.class, "wycheproof"); - Map<String, List<EC_KAResult>> groups = EC_Store.mapToPrefix(results.values()); - for (Map.Entry<String, List<EC_KAResult>> e : groups.entrySet()) { - String description = null; - switch (e.getKey()) { - case "addsub": - description = "Tests for addition-subtraction chains."; - break; - case "cve_2017_10176": - description = "Tests for CVE-2017-10176."; - break; - case "cve_2017_8932": - description = "Tests for CVE-2017-8932."; - break; - } - - List<Test> groupTests = new LinkedList<>(); - Map<EC_Curve, List<EC_KAResult>> curveList = EC_Store.mapResultToCurve(e.getValue()); - for (Map.Entry<EC_Curve, List<EC_KAResult>> c : curveList.entrySet()) { - EC_Curve curve = c.getKey(); - - List<Test> curveTests = new LinkedList<>(); - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test prepareCurve = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Prepare curve", allocate, set); - - List<EC_KAResult> values = c.getValue(); - for (EC_KAResult value : values) { - String id = value.getId(); - String privkeyId = value.getOneKey(); - String pubkeyId = value.getOtherKey(); - - EC_Key.Private privkey = EC_Store.getInstance().getObject(EC_Key.Private.class, privkeyId); - EC_Key.Public pubkey = EC_Store.getInstance().getObject(EC_Key.Public.class, pubkeyId); - - Test setPrivkey = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, privkey.getParams(), privkey.flatten()), Result.ExpectedValue.SUCCESS); - Test setPubkey = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pubkey.getParams(), pubkey.flatten()), Result.ExpectedValue.SUCCESS); - Test ecdhPreTest = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.SUCCESS); - Test ecdh = CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, value.getJavaCardKA()), new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable testable) { - Response.ECDH dh = (Response.ECDH) testable.getResponse(); - if (dh.getSW(0) == CryptoException.NO_SUCH_ALGORITHM) { - return new Result(Result.Value.SUCCESS, "ECDH algorithm unsupported."); - } - if (!dh.successful()) - return new Result(Result.Value.FAILURE, "ECDH was unsuccessful."); - if (!dh.hasSecret()) - return new Result(Result.Value.FAILURE, "ECDH response did not contain the derived secret."); - if (!ByteUtil.compareBytes(dh.getSecret(), 0, value.getData(0), 0, dh.secretLength())) { - int firstDiff = ByteUtil.diffBytes(dh.getSecret(), 0, value.getData(0), 0, dh.secretLength()); - System.err.println(ByteUtil.bytesToHex(dh.getSecret())); - System.err.println(ByteUtil.bytesToHex(value.getData(0))); - return new Result(Result.Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + firstDiff + "."); - } - return new Result(Result.Value.SUCCESS); - } - }); - - Test prepare = CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Prepare", setPrivkey, setPubkey); - Test ka = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do", ecdhPreTest, ecdh); - - Test one = CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Test " + id + ".", prepare, ka); - curveTests.add(one); - } - - if (cfg.cleanup) { - curveTests.add(CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY)); - } - - Test curveTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests", curveTests.toArray(new Test[0])); - groupTests.add(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Tests on " + curve.getId() + ".", prepareCurve, curveTest)); - } - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, description, groupTests.toArray(new Test[0]))); - } - - { - EC_KAResult openssl_bug = EC_Store.getInstance().getObject(EC_KAResult.class, "misc", "openssl-bug"); - EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, openssl_bug.getCurve()); - EC_Key.Private skey = EC_Store.getInstance().getObject(EC_Key.Private.class, openssl_bug.getOtherKey()); - EC_Key.Public pkey = EC_Store.getInstance().getObject(EC_Key.Public.class, openssl_bug.getOneKey()); - Test key = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_FP), Result.ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test setPrivate = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, skey.flatten(EC_Consts.PARAMETER_S)), Result.ExpectedValue.SUCCESS); - Test setPublic = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_W, pkey.flatten(EC_Consts.PARAMETER_W)), Result.ExpectedValue.SUCCESS); - Test ecdh = CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, openssl_bug.getJavaCardKA()), new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable testable) { - Response.ECDH dh = (Response.ECDH) testable.getResponse(); - if (!dh.successful()) - return new Result(Result.Value.FAILURE, "ECDH was unsuccessful."); - if (!dh.hasSecret()) - return new Result(Result.Value.FAILURE, "ECDH response did not contain the derived secret."); - if (ByteUtil.compareBytes(dh.getSecret(), 0, openssl_bug.getData(0), 0, dh.secretLength())) { - return new Result(Result.Value.FAILURE, "OpenSSL bug is present, derived secret matches example."); - } - return new Result(Result.Value.SUCCESS); - } - }); - - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Test OpenSSL modular reduction bug.", key, set, setPrivate, setPublic, ecdh)); - } - - Map<String, EC_Curve> curveMap = EC_Store.getInstance().getObjects(EC_Curve.class, "secg"); - List<EC_Curve> curves = curveMap.entrySet().stream().filter((e) -> e.getKey().endsWith("r1") && e.getValue().getField() == KeyPair.ALG_EC_FP).map(Map.Entry::getValue).collect(Collectors.toList()); - curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor128p2")); - curves.add(EC_Store.getInstance().getObject(EC_Curve.class, "cofactor/cofactor160p4")); - Random rand = new Random(); - for (EC_Curve curve : curves) { - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), KeyPair.ALG_EC_FP), Result.ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + curve.getId() + ".", key)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); - CommandTest export = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W), Result.ExpectedValue.SUCCESS); - Test setup = runTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyPair setup.", key, set, generate, export)); - - /* - byte[] pParam = curve.getParam(EC_Consts.PARAMETER_FP)[0]; - BigInteger p = new BigInteger(1, pParam); - byte[] wParam = ((Response.Export) export.getResponse()).getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W); - byte[] xValue = new byte[(wParam.length - 1) / 2]; - byte[] yValue = new byte[(wParam.length - 1) / 2]; - System.arraycopy(wParam, 1, xValue, 0, xValue.length); - System.arraycopy(wParam, (wParam.length / 2) + 1, yValue, 0, yValue.length); - BigInteger y = new BigInteger(1, yValue); - BigInteger negY = p.subtract(y); - byte[] newY = ECUtil.toByteArray(negY, curve.getBits()); - - EC_Params negYParams = new EC_Params(EC_Consts.PARAMETER_W, new byte[][]{xValue, newY}); - Test negYTest = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, negYParams.getParams(), negYParams.flatten()), "ECDH with pubkey negated.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); - */ - - Test zeroS = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, EC_Consts.TRANSFORMATION_ZERO), "ECDH with S = 0.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); - Test oneS = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, EC_Consts.TRANSFORMATION_ONE), "ECDH with S = 1.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); - - byte[] rParam = curve.getParam(EC_Consts.PARAMETER_R)[0]; - BigInteger R = new BigInteger(1, rParam); - BigInteger smaller = new BigInteger(curve.getBits(), rand).mod(R); - BigInteger diff = R.divide(BigInteger.valueOf(10)); - BigInteger randDiff = new BigInteger(diff.bitLength(), rand).mod(diff); - BigInteger larger = R.add(randDiff); - - BigInteger full = BigInteger.valueOf(1).shiftLeft(R.bitLength() - 1).subtract(BigInteger.ONE); - - BigInteger alternate = full; - for (int i = 0; i < R.bitLength(); i += 2) { - alternate = alternate.clearBit(i); - } - - BigInteger alternateOther = alternate.xor(full); - - EC_Params alternateParams = makeParams(alternate); - Test alternateS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, alternateParams.getParams(), alternateParams.flatten()), "ECDH with S = 101010101...01010.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - - EC_Params alternateOtherParams = makeParams(alternateOther); - Test alternateOtherS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, alternateOtherParams.getParams(), alternateOtherParams.flatten()), "ECDH with S = 010101010...10101.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - - EC_Params fullParams = makeParams(full); - Test fullS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, fullParams.getParams(), fullParams.flatten()), "ECDH with S = 111111111...11111 (but < r).", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - - EC_Params smallerParams = makeParams(smaller); - Test smallerS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, smallerParams.getParams(), smallerParams.flatten()), "ECDH with S < r.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - - EC_Params exactParams = makeParams(R); - Test exactS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, exactParams.getParams(), exactParams.flatten()), "ECDH with S = r.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); - - EC_Params largerParams = makeParams(larger); - Test largerS = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, largerParams.getParams(), largerParams.flatten()), "ECDH with S > r.", Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); - - BigInteger rm1 = R.subtract(BigInteger.ONE); - BigInteger rp1 = R.add(BigInteger.ONE); - - EC_Params rm1Params = makeParams(rm1); - Test rm1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, rm1Params.getParams(), rm1Params.flatten()), "ECDH with S = r - 1.", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - - EC_Params rp1Params = makeParams(rp1); - Test rp1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, rp1Params.getParams(), rp1Params.flatten()), "ECDH with S = r + 1.", Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); - - byte[] k = curve.getParam(EC_Consts.PARAMETER_K)[0]; - BigInteger K = new BigInteger(1, k); - BigInteger kr = K.multiply(R); - BigInteger krm1 = kr.subtract(BigInteger.ONE); - BigInteger krp1 = kr.add(BigInteger.ONE); - - Result.ExpectedValue kExpected = K.equals(BigInteger.ONE) ? Result.ExpectedValue.SUCCESS : Result.ExpectedValue.FAILURE; - - EC_Params krParams = makeParams(kr); - Test krS /*ONE!*/ = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krParams.getParams(), krParams.flatten()), "ECDH with S = k * r.", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); - - EC_Params krm1Params = makeParams(krm1); - Test krm1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krm1Params.getParams(), krm1Params.flatten()), "ECDH with S = (k * r) - 1.", kExpected, kExpected); - - EC_Params krp1Params = makeParams(krp1); - Test krp1S = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, krp1Params.getParams(), krp1Params.flatten()), "ECDH with S = (k * r) + 1.", Result.ExpectedValue.ANY, Result.ExpectedValue.ANY); - - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, zeroS, oneS, alternateS, alternateOtherS, fullS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S, cleanup)); - } else { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Tests with edge-case private key values over " + curve.getId() + ".", setup, zeroS, oneS, alternateS, alternateOtherS, fullS, smallerS, exactS, largerS, rm1S, rp1S, krS, krm1S, krp1S)); - } - } - - EC_Curve secp160r1 = EC_Store.getInstance().getObject(EC_Curve.class, "secg/secp160r1"); - byte[] pData = secp160r1.getParam(EC_Consts.PARAMETER_FP)[0]; - BigInteger p = new BigInteger(1, pData); - byte[] rData = secp160r1.getParam(EC_Consts.PARAMETER_R)[0]; - BigInteger r = new BigInteger(1, rData); - - BigInteger range = r.subtract(p); - BigInteger deviation = range.divide(BigInteger.valueOf(5)); - BigDecimal dev = new BigDecimal(deviation); - BigDecimal smallDev = new BigDecimal(10000); - int n = 10; - BigInteger[] rs = new BigInteger[n]; - BigInteger[] ps = new BigInteger[n]; - BigInteger[] zeros = new BigInteger[n]; - for (int i = 0; i < n; ++i) { - double sample; - do { - sample = rand.nextGaussian(); - } while (sample >= -1 && sample <= 1); - BigInteger where = dev.multiply(new BigDecimal(sample)).toBigInteger(); - rs[i] = where.add(r); - ps[i] = where.add(p); - zeros[i] = smallDev.multiply(new BigDecimal(sample)).toBigInteger().abs(); - } - Arrays.sort(rs); - Arrays.sort(ps); - Arrays.sort(zeros); - - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, secp160r1.getBits(), KeyPair.ALG_EC_FP), Result.ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.FAILURE, "No support for " + secp160r1.getBits() + "b secp160r1.", key)); - return; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, secp160r1.getParams(), secp160r1.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); - Test setup = CompoundTest.all(Result.ExpectedValue.SUCCESS, "KeyPair setup.", key, set, generate); - - Test[] zeroTests = new Test[n]; - int i = 0; - for (BigInteger nearZero : zeros) { - EC_Params params = makeParams(nearZero); - zeroTests[i++] = ecdhTestBoth(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearZero.toString(16), Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - } - Test zeroTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Near zero.", zeroTests); - - Test[] pTests = new Test[n]; - i = 0; - for (BigInteger nearP : ps) { - EC_Params params = makeParams(nearP); - pTests[i++] = ecdhTestBoth(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearP.toString(16) + (nearP.compareTo(p) > 0 ? " (>p)" : " (<=p)"), Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - } - Test pTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Near p.", pTests); - - Test[] rTests = new Test[n]; - i = 0; - for (BigInteger nearR : rs) { - EC_Params params = makeParams(nearR); - if (nearR.compareTo(r) >= 0) { - rTests[i++] = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearR.toString(16) + " (>=r)", Result.ExpectedValue.FAILURE, Result.ExpectedValue.FAILURE); - } else { - rTests[i++] = ecdhTestBoth(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, params.getParams(), params.flatten()), nearR.toString(16) + " (<r)", Result.ExpectedValue.SUCCESS, Result.ExpectedValue.SUCCESS); - } - } - Test rTest = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Near r.", rTests); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "Test private key values near zero, near p and near/larger than the order.", setup, zeroTest, pTest, rTest)); - } - - private Test ecdhTestBoth(Command setPriv, String desc, Result.ExpectedValue setExpect, Result.ExpectedValue ecdhExpect) { - Test set = CommandTest.expect(setPriv, setExpect); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ecdhExpect); - - return CompoundTest.all(Result.ExpectedValue.SUCCESS, desc, set, ecdh); - } - - private Test ecdhTest(Command setPriv, String desc, Result.ExpectedValue setExpect, Result.ExpectedValue ecdhExpect) { - Test set = CommandTest.expect(setPriv, setExpect); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ecdhExpect); - - return CompoundTest.any(Result.ExpectedValue.SUCCESS, desc, set, ecdh); - } - - private EC_Params makeParams(BigInteger s) { - return makeParams(ECUtil.toByteArray(s, s.bitLength())); - } - - private EC_Params makeParams(byte[] s) { - return new EC_Params(EC_Consts.PARAMETER_S, new byte[][]{s}); - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java b/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java deleted file mode 100644 index 5df379e..0000000 --- a/src/cz/crcs/ectester/reader/test/CardInvalidSuite.java +++ /dev/null @@ -1,72 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardInvalidSuite extends CardTestSuite { - - public CardInvalidSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "invalid", null, "The invalid curve suite tests whether the card rejects points outside of the curve during ECDH."); - } - - @Override - protected void runTests() throws Exception { - /* Set original curves (secg/nist/brainpool). Generate local. - * Try ECDH with invalid public keys of increasing order. - */ - Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "invalid"); - Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { - EC_Curve curve = e.getKey(); - List<EC_Key.Public> keys = e.getValue(); - - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getId() + ".", allocate)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), ExpectedValue.SUCCESS); - - Test prepare = CompoundTest.all(ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); - - List<Test> ecdhTests = new LinkedList<>(); - for (EC_Key.Public pub : keys) { - Test setPub = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE); - Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with invalid pubkey.", setPub, ecdh); - Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); - Test rawEcdh = CommandTest.expect(ecdhCommand, ExpectedValue.FAILURE, "Card correctly rejected point on invalid curve.", "Card incorrectly accepted point on invalid curve."); - ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " invalid key test.", objectEcdh, rawEcdh)); - } - Test ecdh = CompoundTest.all(ExpectedValue.SUCCESS, "Perform ECDH with invalid public points.", ecdhTests.toArray(new Test[0])); - - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", prepare, ecdh, cleanup)); - } else { - doTest(CompoundTest.greedyAllTry(ExpectedValue.SUCCESS, "Invalid curve test of " + curve.getId() + ".", prepare, ecdh)); - } - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java b/src/cz/crcs/ectester/reader/test/CardMiscSuite.java deleted file mode 100644 index dd49708..0000000 --- a/src/cz/crcs/ectester/reader/test/CardMiscSuite.java +++ /dev/null @@ -1,77 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardMiscSuite extends CardTestSuite { - - public CardMiscSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "miscellaneous", new String[]{"preset", "random"}, "Some miscellaneous tests, tries ECDH and ECDSA over supersingular curves, anomalous curves,", - "Barreto-Naehrig curves with small embedding degree and CM discriminant, MNT curves,", - "some Montgomery curves transformed to short Weierstrass form and Curve25519 transformed to short Weierstrass form."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_Curve> anCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "anomalous"); - Map<String, EC_Curve> ssCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "supersingular"); - Map<String, EC_Curve> bnCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "Barreto-Naehrig"); - Map<String, EC_Curve> mntCurves = EC_Store.getInstance().getObjects(EC_Curve.class, "MNT"); - List<EC_Curve> mCurves = new ArrayList<>(); - mCurves.add(EC_Store.getInstance().getObject(EC_Curve.class, "other", "M-221")); - mCurves.add(EC_Store.getInstance().getObject(EC_Curve.class, "other", "M-383")); - mCurves.add(EC_Store.getInstance().getObject(EC_Curve.class, "other", "M-511")); - EC_Curve curve25519 = EC_Store.getInstance().getObject(EC_Curve.class, "other", "Curve25519"); - - testCurves(anCurves.values(), "anomalous", Result.ExpectedValue.FAILURE); - testCurves(ssCurves.values(), "supersingular", Result.ExpectedValue.FAILURE); - testCurves(bnCurves.values(), "Barreto-Naehrig", Result.ExpectedValue.SUCCESS); - testCurves(mntCurves.values(), "MNT", Result.ExpectedValue.SUCCESS); - testCurves(mCurves, "Montgomery", Result.ExpectedValue.SUCCESS); - testCurve(curve25519, "Montgomery", Result.ExpectedValue.SUCCESS); - } - - private void testCurve(EC_Curve curve, String catName, Result.ExpectedValue expected) { - Test allocateFirst = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); - if (!allocateFirst.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + catName + " curve: " + curve.getId() + ".", allocateFirst)); - return; - } - - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = setupKeypairs(curve, Result.ExpectedValue.ANY, ECTesterApplet.KEYPAIR_BOTH); - Test ka = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), expected); - Test sig = CommandTest.expect(new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_FALSE, null), expected); - Test perform = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH and ECDSA.", ka, sig); - - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + "b " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform, cleanup)); - } else { - doTest(CompoundTest.greedyAll(Result.ExpectedValue.SUCCESS, "Tests over " + curve.getBits() + "b " + catName + " curve: " + curve.getId() + ".", allocateFirst, set, generate, perform)); - } - } - - private void testCurves(Collection<EC_Curve> curves, String catName, Result.ExpectedValue expected) { - for (EC_Curve curve : curves) { - testCurve(curve, catName, expected); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java b/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java deleted file mode 100644 index 0e4ca8e..0000000 --- a/src/cz/crcs/ectester/reader/test/CardSignatureSuite.java +++ /dev/null @@ -1,68 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.ec.EC_SigResult; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardSignatureSuite extends CardTestSuite { - public CardSignatureSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "signature", null, "The signature test suite tests verifying various malformed and well-formed but invalid ECDSA signatures."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_SigResult> results = EC_Store.getInstance().getObjects(EC_SigResult.class, "wrong"); - Map<String, List<EC_SigResult>> groups = EC_Store.mapToPrefix(results.values()); - - List<EC_SigResult> nok = groups.entrySet().stream().filter((e) -> e.getKey().equals("nok")).findFirst().get().getValue(); - - byte[] data = "Some stuff that is not the actual data".getBytes(); - for (EC_SigResult sig : nok) { - ecdsaTest(sig, Result.ExpectedValue.FAILURE, data); - } - - List<EC_SigResult> ok = groups.entrySet().stream().filter((e) -> e.getKey().equals("ok")).findFirst().get().getValue(); - for (EC_SigResult sig : ok) { - ecdsaTest(sig, Result.ExpectedValue.SUCCESS, null); - } - } - - private void ecdsaTest(EC_SigResult sig, Result.ExpectedValue expected, byte[] defaultData) { - EC_Key.Public pubkey = EC_Store.getInstance().getObject(EC_Key.Public.class, sig.getVerifyKey()); - - byte[] data = sig.getSigData(); - if (data == null) { - data = defaultData; - } - - EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, sig.getCurve()); - Test allocate = CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_LOCAL, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS); - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test setVerifyKey = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, pubkey.getParams(), pubkey.flatten()), Result.ExpectedValue.SUCCESS); - Test ecdsaVerify = CommandTest.expect(new Command.ECDSA_verify(this.card, ECTesterApplet.KEYPAIR_LOCAL, sig.getJavaCardSig(), data, sig.getData(0)), expected); - - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + ".", allocate, set, setVerifyKey, ecdsaVerify, cleanup)); - } else { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "ECDSA test of " + sig.getId() + ".", allocate, set, setVerifyKey, ecdsaVerify)); - } - - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardTestSuite.java b/src/cz/crcs/ectester/reader/test/CardTestSuite.java deleted file mode 100644 index fc60ae5..0000000 --- a/src/cz/crcs/ectester/reader/test/CardTestSuite.java +++ /dev/null @@ -1,94 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Params; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.test.TestSuite; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.Arrays; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public abstract class CardTestSuite extends TestSuite { - ECTesterReader.Config cfg; - CardMngr card; - String[] options; - - CardTestSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager, String name, String[] options, String... description) { - super(writer, name, description); - this.card = cardManager; - this.cfg = cfg; - this.options = options; - } - - public CardMngr getCard() { - return card; - } - - public ECTesterReader.Config getCfg() { - return cfg; - } - - public String[] getOptions() { - if (options != null) { - return options.clone(); - } else { - return options; - } - } - - public Test setupKeypairs(EC_Curve curve, Result.ExpectedValue expected, byte keyPair) { - if ((Arrays.asList(options).contains("preset") && cfg.testOptions.contains("preset")) || (Arrays.asList(options).contains("random") && cfg.testOptions.contains("random"))) { - Test setLocal = null; - if ((keyPair & ECTesterApplet.KEYPAIR_LOCAL) != 0) { - EC_Params priv; - if (cfg.testOptions.contains("preset")) { - priv = ECUtil.fixedRandomKey(curve); - } else { - priv = ECUtil.fullRandomKey(curve); - } - setLocal = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, priv.getParams(), priv.flatten()), expected); - } - Test setRemote = null; - if ((keyPair & ECTesterApplet.KEYPAIR_REMOTE) != 0) { - EC_Params pub; - if (cfg.testOptions.contains("preset")) { - pub = ECUtil.fixedRandomPoint(curve); - } else { - pub = ECUtil.fullRandomPoint(curve); - } - if (pub == null) { - setRemote = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_REMOTE), expected); - } else { - setRemote = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), expected); - } - } - - if (keyPair == ECTesterApplet.KEYPAIR_LOCAL) { - return setLocal; - } else if (keyPair == ECTesterApplet.KEYPAIR_REMOTE) { - return setRemote; - } else { - String desc; - if (cfg.testOptions.contains("preset")) { - desc = "Set semi-random parameters."; - } else { - desc = "Set fully-random parameters."; - } - return CompoundTest.all(expected, desc, setLocal, setRemote); - } - } else { - return CommandTest.expect(new Command.Generate(this.card, keyPair), expected); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java b/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java deleted file mode 100644 index d143852..0000000 --- a/src/cz/crcs/ectester/reader/test/CardTestVectorSuite.java +++ /dev/null @@ -1,235 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.*; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.test.TestCallback; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; -import javacard.security.KeyPair; - -import javax.crypto.KeyAgreement; -import java.io.IOException; -import java.math.BigInteger; -import java.security.*; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPrivateKeySpec; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.InvalidKeySpecException; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.function.BiFunction; -import java.util.stream.Collectors; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; -import static cz.crcs.ectester.common.test.Result.Value; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardTestVectorSuite extends CardTestSuite { - - public CardTestVectorSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "test-vectors", null, "The test-vectors suite contains a collection of test vectors which test basic ECDH correctness."); - } - - @Override - protected void runTests() throws Exception { - /* Set original curves (secg/nist/brainpool). Set keypairs from test vectors. - * Do ECDH both ways, export and verify that the result is correct. - */ - Map<String, EC_KAResult> results = EC_Store.getInstance().getObjects(EC_KAResult.class, "test"); - for (EC_KAResult result : results.values()) { - EC_Curve curve = EC_Store.getInstance().getObject(EC_Curve.class, result.getCurve()); - EC_Params onekey = EC_Store.getInstance().getObject(EC_Keypair.class, result.getOneKey()); - if (onekey == null) { - onekey = EC_Store.getInstance().getObject(EC_Key.Private.class, result.getOneKey()); - } - EC_Params otherkey = EC_Store.getInstance().getObject(EC_Keypair.class, result.getOtherKey()); - if (otherkey == null) { - otherkey = EC_Store.getInstance().getObject(EC_Key.Public.class, result.getOtherKey()); - } - if (onekey == null || otherkey == null) { - throw new IOException("Test vector keys couldn't be located."); - } - List<Test> testVector = new LinkedList<>(); - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate)); - continue; - } - - testVector.add(allocate); - testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS)); - testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.CURVE_external, EC_Consts.PARAMETER_S, onekey.flatten(EC_Consts.PARAMETER_S)), ExpectedValue.SUCCESS)); - testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, EC_Consts.PARAMETER_W, otherkey.flatten(EC_Consts.PARAMETER_W)), ExpectedValue.SUCCESS)); - testVector.add(CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, result.getJavaCardKA()), new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable testable) { - Response.ECDH dh = (Response.ECDH) testable.getResponse(); - if (!dh.successful()) - return new Result(Value.FAILURE, "ECDH was unsuccessful."); - if (!dh.hasSecret()) - return new Result(Value.FAILURE, "ECDH response did not contain the derived secret."); - if (!ByteUtil.compareBytes(dh.getSecret(), 0, result.getData(0), 0, dh.secretLength())) { - int firstDiff = ByteUtil.diffBytes(dh.getSecret(), 0, result.getData(0), 0, dh.secretLength()); - return new Result(Value.FAILURE, "ECDH derived secret does not match the test-vector, first difference was at byte " + firstDiff + "."); - } - return new Result(Value.SUCCESS); - } - })); - if (cfg.cleanup) { - testVector.add(CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY)); - } - doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Test vector " + result.getId() + ".", testVector.toArray(new Test[0]))); - } - - KeyAgreement ka; - Signature sig; - KeyFactory kf; - MessageDigest md; - try { - ka = KeyAgreement.getInstance("ECDH", "BC"); - sig = Signature.getInstance("ECDSAwithSHA1", "BC"); - kf = KeyFactory.getInstance("ECDH", "BC"); - md = MessageDigest.getInstance("SHA1", "BC"); - } catch (NoSuchAlgorithmException | NoSuchProviderException ex) { - return; - } - - List<EC_Curve> testCurves = new ArrayList<>(); - testCurves.addAll(EC_Store.getInstance().getObjects(EC_Curve.class, "secg").values().stream().filter((curve) -> curve.getField() == KeyPair.ALG_EC_FP).collect(Collectors.toList())); - testCurves.addAll(EC_Store.getInstance().getObjects(EC_Curve.class, "brainpool").values().stream().filter((curve) -> curve.getField() == KeyPair.ALG_EC_FP).collect(Collectors.toList())); - for (EC_Curve curve : testCurves) { - List<Test> testVector = new LinkedList<>(); - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()) + ".", allocate)); - continue; - } - testVector.add(allocate); - testVector.add(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.SUCCESS)); - testVector.add(CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.SUCCESS)); - CommandTest exportLocal = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.KEY_PUBLIC, EC_Consts.PARAMETER_W), ExpectedValue.ANY); - CommandTest exportRemote = CommandTest.expect(new Command.Export(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.KEY_PRIVATE, EC_Consts.PARAMETER_S), ExpectedValue.ANY); - testVector.add(exportLocal); - testVector.add(exportRemote); - BiFunction<Response.Export, Response.Export, Key[]> getKeys = (localData, remoteData) -> { - byte[] pkey = localData.getParameter(ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.PARAMETER_W); - byte[] skey = remoteData.getParameter(ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.PARAMETER_S); - ECParameterSpec spec = curve.toSpec(); - ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(new BigInteger(1, skey), spec); - ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(ECUtil.fromX962(pkey, curve.toCurve()), spec); - PrivateKey privKey; - PublicKey pubKey; - try { - privKey = kf.generatePrivate(privKeySpec); - pubKey = kf.generatePublic(pubKeySpec); - } catch (InvalidKeySpecException ex) { - return null; - } - return new Key[]{privKey, pubKey}; - }; - TestCallback<CommandTestable> kaCallback = new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable testable) { - Response.ECDH ecdhData = (Response.ECDH) testable.getResponse(); - if (!ecdhData.successful()) - return new Result(Value.FAILURE, "ECDH was unsuccessful."); - if (!ecdhData.hasSecret()) { - return new Result(Value.FAILURE, "ECDH response did not contain the derived secret."); - } - byte[] secret = ecdhData.getSecret(); - Response.Export localData = (Response.Export) exportLocal.getResponse(); - Response.Export remoteData = (Response.Export) exportRemote.getResponse(); - Key[] keys = getKeys.apply(localData, remoteData); - if (keys == null) { - return new Result(Value.SUCCESS, "Result could not be verified. keyData unavailable."); - } - PrivateKey privKey = (PrivateKey) keys[0]; - PublicKey pubKey = (PublicKey) keys[1]; - try { - ka.init(privKey); - ka.doPhase(pubKey, true); - byte[] derived = ka.generateSecret(); - int fieldSize = (curve.getBits() + 7) / 8; - if (derived.length < fieldSize) { - byte[] padded = new byte[fieldSize]; - System.arraycopy(derived, 0, padded, fieldSize - derived.length, derived.length); - derived = padded; - } - if (ecdhData.getType() == EC_Consts.KeyAgreement_ALG_EC_SVDP_DH || ecdhData.getType() == EC_Consts.KeyAgreement_ALG_EC_SVDP_DHC) { - derived = md.digest(derived); - } - if (secret.length != derived.length) { - if (secret.length < derived.length) { - return new Result(Value.FAILURE, String.format("Derived secret was shorter than expected: %d vs %d (expected).", secret.length, derived.length)); - } else { - return new Result(Value.FAILURE, String.format("Derived secret was longer than expected: %d vs %d (expected).", secret.length, derived.length)); - } - } - int diff = ByteUtil.diffBytes(derived, 0, secret, 0, secret.length); - if (diff == secret.length) { - return new Result(Value.SUCCESS, "Derived secret matched expected value."); - } else { - return new Result(Value.FAILURE, "Derived secret does not match expected value, first difference was at byte " + diff + "."); - } - } catch (InvalidKeyException ex) { - return new Result(Value.SUCCESS, "Result could not be verified. " + ex.getMessage()); - } - } - }; - Test ecdhTest = CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), kaCallback); - Test ecdhRawTest = CommandTest.function(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_TRUE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH_PLAIN), kaCallback); - byte[] data = new byte[32]; - TestCallback<CommandTestable> sigCallback = new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable testable) { - Response.ECDSA ecdsaData = (Response.ECDSA) testable.getResponse(); - if (!ecdsaData.successful()) - return new Result(Value.FAILURE, "ECDSA was unsuccessful."); - if (!ecdsaData.hasSignature()) { - return new Result(Value.FAILURE, "ECDSA response did not contain the signature."); - } - byte[] signature = ecdsaData.getSignature(); - Response.Export localData = (Response.Export) exportLocal.getResponse(); - Response.Export remoteData = (Response.Export) exportRemote.getResponse(); - Key[] keys = getKeys.apply(localData, remoteData); - if (keys == null) { - return new Result(Value.SUCCESS, "Result could not be verified. keyData unavailable."); - } - PublicKey pubKey = (PublicKey) keys[1]; - try { - sig.initVerify(pubKey); - sig.update(data); - if (sig.verify(signature)) { - return new Result(Value.SUCCESS, "Signature verified."); - } else { - return new Result(Value.FAILURE, "Signature failed to verify."); - } - } catch (InvalidKeyException | SignatureException ex) { - return new Result(Value.SUCCESS, "Result could not be verified. " + ex.getMessage()); - } - } - }; - Test ecdsaTest = CommandTest.function(new Command.ECDSA_sign(this.card, ECTesterApplet.KEYPAIR_LOCAL, EC_Consts.Signature_ALG_ECDSA_SHA, ECTesterApplet.EXPORT_TRUE, data), sigCallback); - testVector.add(CompoundTest.all(ExpectedValue.SUCCESS, "Test.", ecdhTest, ecdhRawTest, ecdsaTest)); - if (cfg.cleanup) { - testVector.add(CommandTest.expect(new Command.Cleanup(this.card), ExpectedValue.ANY)); - } - doTest(CompoundTest.greedyAll(ExpectedValue.SUCCESS, "Validation test on " + curve.getId() + ".", testVector.toArray(new Test[0]))); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java b/src/cz/crcs/ectester/reader/test/CardTwistSuite.java deleted file mode 100644 index a6bca6c..0000000 --- a/src/cz/crcs/ectester/reader/test/CardTwistSuite.java +++ /dev/null @@ -1,67 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Key; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; - -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardTwistSuite extends CardTestSuite { - public CardTwistSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "twist", null, "The twist test suite tests whether the card correctly rejects points on the quadratic twist of the curve during ECDH."); - } - - @Override - protected void runTests() throws Exception { - Map<String, EC_Key.Public> pubkeys = EC_Store.getInstance().getObjects(EC_Key.Public.class, "twist"); - Map<EC_Curve, List<EC_Key.Public>> curveList = EC_Store.mapKeyToCurve(pubkeys.values()); - for (Map.Entry<EC_Curve, List<EC_Key.Public>> e : curveList.entrySet()) { - EC_Curve curve = e.getKey(); - List<EC_Key.Public> keys = e.getValue(); - - Test allocate = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), Result.ExpectedValue.SUCCESS)); - if (!allocate.ok()) { - doTest(CompoundTest.all(Result.ExpectedValue.SUCCESS, "No support for " + curve.getId() + ".", allocate)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), Result.ExpectedValue.SUCCESS); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_LOCAL), Result.ExpectedValue.SUCCESS); - - Test prepare = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Prepare and generate keypair on " + curve.getId() + ".", allocate, set, generate); - - List<Test> ecdhTests = new LinkedList<>(); - for (EC_Key.Public pub : keys) { - Test setPub = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_REMOTE, EC_Consts.CURVE_external, pub.getParams(), pub.flatten()), Result.ExpectedValue.FAILURE); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), Result.ExpectedValue.FAILURE, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."); - Test objectEcdh = CompoundTest.any(Result.ExpectedValue.SUCCESS, CardUtil.getKATypeString(EC_Consts.KeyAgreement_ALG_EC_SVDP_DH) + " test with twist pubkey.", setPub, ecdh); - Command ecdhCommand = new Command.ECDH_direct(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH, pub.flatten()); - Test rawEcdh = CommandTest.expect(ecdhCommand, Result.ExpectedValue.FAILURE, "Card correctly rejected point on twist.", "Card incorrectly accepted point on twist."); - ecdhTests.add(CompoundTest.all(Result.ExpectedValue.SUCCESS, pub.getId() + " twist key test.", objectEcdh, rawEcdh)); - } - Test ecdh = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Perform ECDH with public points on twist.", ecdhTests.toArray(new Test[0])); - - Test tests = CompoundTest.all(Result.ExpectedValue.SUCCESS, "Do tests.", ecdh); - if (cfg.cleanup) { - Test cleanup = CommandTest.expect(new Command.Cleanup(this.card), Result.ExpectedValue.ANY); - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", prepare, tests, cleanup)); - } else { - doTest(CompoundTest.greedyAllTry(Result.ExpectedValue.SUCCESS, "Twist test of " + curve.getId() + ".", prepare, tests)); - } - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CardWrongSuite.java b/src/cz/crcs/ectester/reader/test/CardWrongSuite.java deleted file mode 100644 index 13a3f8b..0000000 --- a/src/cz/crcs/ectester/reader/test/CardWrongSuite.java +++ /dev/null @@ -1,232 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.applet.EC_Consts; -import cz.crcs.ectester.common.ec.EC_Curve; -import cz.crcs.ectester.common.ec.EC_Params; -import cz.crcs.ectester.common.output.TestWriter; -import cz.crcs.ectester.common.test.CompoundTest; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.Test; -import cz.crcs.ectester.common.util.ByteUtil; -import cz.crcs.ectester.common.util.CardUtil; -import cz.crcs.ectester.common.util.ECUtil; -import cz.crcs.ectester.data.EC_Store; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.ECTesterReader; -import cz.crcs.ectester.reader.command.Command; -import javacard.security.KeyPair; - -import java.math.BigInteger; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import static cz.crcs.ectester.common.test.Result.ExpectedValue; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CardWrongSuite extends CardTestSuite { - - public CardWrongSuite(TestWriter writer, ECTesterReader.Config cfg, CardMngr cardManager) { - super(writer, cfg, cardManager, "wrong", new String[]{"preset", "random"}, "The wrong curve suite tests whether the card rejects domain parameters which are not curves."); - } - - @Override - protected void runTests() throws Exception { - /* Just do the default run on the wrong curves. - * These should generally fail, the curves aren't curves. - */ - Map<String, EC_Curve> curves = EC_Store.getInstance().getObjects(EC_Curve.class, "wrong"); - for (Map.Entry<String, EC_Curve> e : curves.entrySet()) { - EC_Curve curve = e.getValue(); - List<Test> tests = new LinkedList<>(); - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, curve.getBits(), curve.getField()), ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), key)); - continue; - } - tests.add(key); - Test set = runTest(CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, curve.getParams(), curve.flatten()), ExpectedValue.FAILURE)); - Test generate = runTest(setupKeypairs(curve, ExpectedValue.SUCCESS, ECTesterApplet.KEYPAIR_BOTH)); - Test setup = runTest(CompoundTest.any(ExpectedValue.SUCCESS, "Set wrong curve and generate keypairs.", set, generate)); - tests.add(setup); - - for (byte kaType : EC_Consts.KA_TYPES) { - Test allocate = runTest(CommandTest.expect(new Command.AllocateKeyAgreement(this.card, kaType), ExpectedValue.SUCCESS)); - if (allocate.ok()) { - Test ka = runTest(CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, kaType), ExpectedValue.FAILURE)); - Test kaTest = runTest(CompoundTest.all(ExpectedValue.SUCCESS, "Allocate and perform KA.", allocate, ka)); - tests.add(kaTest); - } - } - doTest(CompoundTest.function((tsts) -> { - for (int i = 0; i < tsts.length; ++i) { - if (i != 1 && !tsts[i].ok()) { - return new Result(Result.Value.FAILURE, "Some tests did not have the expected result."); - } - } - return new Result(Result.Value.SUCCESS, "All tests had the expected result."); - }, "Wrong curve test of " + curve.getBits() + "b " + CardUtil.getKeyTypeString(curve.getField()), tests.toArray(new Test[0]))); - } - /* - * Do some interesting tests with corrupting the custom curves. - * For prime field: - * - p = 0 - * - p = 1 - * - p is a square of a prime - * - p is a composite q * s with q, s primes - * - TODO: p divides discriminant - */ - Random r = new Random(); - for (short keyLength : EC_Consts.FP_SIZES) { - byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_FP); - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_FP), ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_FP.", key)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_FP, null), ExpectedValue.SUCCESS); - Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set); - - Test prime0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ZERO), "Set p = 0.", "ECDH with p = 0."); - Test prime1 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_FP, EC_Consts.TRANSFORMATION_ONE), "Set p = 1.", "ECDH with p = 1."); - - short keyHalf = (short) (keyLength / 2); - BigInteger prime = new BigInteger(keyHalf, 50, r); - BigInteger primePow = prime.pow(2); - byte[] primePowBytes = ECUtil.toByteArray(primePow, keyLength); - EC_Params primePowData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{primePowBytes}); - Test primePower = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, primePowData.getParams(), primePowData.flatten()), "Set p = square of a prime.", "ECDH with p = q^2."); - - BigInteger q = new BigInteger(keyHalf, r); - BigInteger s = new BigInteger(keyHalf, r); - BigInteger compositeValue = q.multiply(s); - byte[] compositeBytes = ECUtil.toByteArray(compositeValue, keyLength); - EC_Params compositeData = new EC_Params(EC_Consts.PARAMETER_FP, new byte[][]{compositeBytes}); - Test composite = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, compositeData.getParams(), compositeData.flatten()), "Set p = product of two primes.", "ECDH with p = q * s."); - - Test wrongPrime = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted prime parameter.", prime0, prime1, primePower, composite); - - Test resetSetup = CompoundTest.all(ExpectedValue.SUCCESS, "Reset keypair.", set.clone()); - - Test randomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, (short) (EC_Consts.TRANSFORMATION_FULLRANDOM | EC_Consts.TRANSFORMATION_04_MASK)), "Set G = random non-point/point-like.", "ECDH with non-point G."); - Test fullRandomG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_FULLRANDOM), "Set G = random data.", "ECDH with G = random data."); - Test zeroG = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_G, EC_Consts.TRANSFORMATION_INFINITY), "Set G = inifnity.", "ECDH with G = infinity."); - Test wrongG = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted G parameter.", randomG, fullRandomG, zeroG); - - byte[] originalR = new byte[((keyLength + 7) / 8) + 1]; - short origRlen = EC_Consts.getCurveParameter(curve, EC_Consts.PARAMETER_R, originalR, (short) 0); - if (origRlen != originalR.length) { - byte[] copyR = new byte[origRlen]; - System.arraycopy(originalR, 0, copyR, 0, origRlen); - originalR = copyR; - } - BigInteger originalBigR = new BigInteger(1, originalR); - - Test zeroR = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, EC_Consts.PARAMETER_R, EC_Consts.TRANSFORMATION_ZERO), "Set R = 0.", "ECDH with R = 0."); - Test oneR = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, EC_Consts.PARAMETER_R, EC_Consts.TRANSFORMATION_ONE), "Set R = 1.", "ECDH with R = 1."); - - BigInteger prevPrimeR; - do { - prevPrimeR = BigInteger.probablePrime(originalBigR.bitLength() - 1, r); - } while (prevPrimeR.compareTo(originalBigR) >= 0); - byte[] prevRBytes = ECUtil.toByteArray(prevPrimeR, keyLength); - EC_Params prevRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{prevRBytes}); - Test prevprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, prevRData.getParams(), prevRData.flatten()), "Set R = some prime (but [r]G != infinity) smaller than original R.", "ECDH with wrong R, prevprime."); - - BigInteger nextPrimeR = originalBigR.nextProbablePrime(); - byte[] nextRBytes = ECUtil.toByteArray(nextPrimeR, keyLength); - EC_Params nextRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nextRBytes}); - Test nextprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nextRData.getParams(), nextRData.flatten()), "Set R = some prime (but [r]G != infinity) larger than original R.", "ECDH with wrong R, nextprime."); - - byte[] nonprimeRBytes = nextRBytes.clone(); - nonprimeRBytes[nonprimeRBytes.length - 1] ^= 1; - EC_Params nonprimeWrongRData = new EC_Params(EC_Consts.PARAMETER_R, new byte[][]{nonprimeRBytes}); - Test nonprimeWrongR = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, nonprimeWrongRData.getParams(), nonprimeWrongRData.flatten()), "Set R = some composite (but [r]G != infinity).", "ECDH with wrong R, composite."); - - Test wrongR = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted R parameter.", zeroR, oneR, prevprimeWrongR, nextprimeWrongR, nonprimeWrongR); - - byte[] kRaw = new byte[]{(byte) 0xff}; - EC_Params kData = new EC_Params(EC_Consts.PARAMETER_K, new byte[][]{kRaw}); - Test bigK = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, kData.getParams(), kData.flatten()), "", ""); - - byte[] kZero = new byte[]{(byte) 0}; - EC_Params kZeroData = new EC_Params(EC_Consts.PARAMETER_K, new byte[][]{kZero}); - Test zeroK = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, kZeroData.getParams(), kZeroData.flatten()), "", ""); - - Test wrongK = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted K parameter.", bigK, zeroK); - - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_FP), setup, wrongPrime, resetSetup, wrongG, resetSetup.clone(), wrongR, resetSetup.clone(), wrongK, resetSetup.clone())); - } - - /* - * For binary field: - * - e1, e2 or e3 is larger than m. - * - e1 = e2 = e3 = 0 - */ - for (short keyLength : EC_Consts.F2M_SIZES) { - byte curve = EC_Consts.getCurve(keyLength, KeyPair.ALG_EC_F2M); - Test key = runTest(CommandTest.expect(new Command.Allocate(this.card, ECTesterApplet.KEYPAIR_BOTH, keyLength, KeyPair.ALG_EC_F2M), ExpectedValue.SUCCESS)); - if (!key.ok()) { - doTest(CompoundTest.all(ExpectedValue.FAILURE, "No support for " + keyLength + "b ALG_EC_F2M.", key)); - continue; - } - Test set = CommandTest.expect(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, curve, EC_Consts.PARAMETERS_DOMAIN_F2M, null), ExpectedValue.SUCCESS); - Test setup = CompoundTest.all(ExpectedValue.SUCCESS, "KeyPair setup.", key, set); - - Test coeff0 = ecdhTest(new Command.Transform(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.KEY_BOTH, EC_Consts.PARAMETER_F2M, EC_Consts.TRANSFORMATION_ZERO), "Set e1 = e2 = e3 = 0.", "ECDH with wrong field polynomial: x^" + keyLength); - - short e1 = (short) (2 * keyLength); - short e2 = (short) (3 * keyLength); - short e3 = (short) (4 * keyLength); - byte[][] coeffBytes = new byte[][]{ - ByteUtil.shortToBytes(keyLength), - ByteUtil.shortToBytes(e1), - ByteUtil.shortToBytes(e2), - ByteUtil.shortToBytes(e3)}; - EC_Params coeffParams = new EC_Params(EC_Consts.PARAMETER_F2M, coeffBytes); - Test coeffLarger = ecdhTest(new Command.Set(this.card, ECTesterApplet.KEYPAIR_BOTH, EC_Consts.CURVE_external, coeffParams.getParams(), coeffParams.flatten()), "Set e1=" + e1 + ", e2=" + e2 + ", e3=" + e3, "ECDH with wrong field poly, powers larger than " + keyLength); - - Test wrong = CompoundTest.all(ExpectedValue.SUCCESS, "Tests with corrupted field polynomial parameter.", coeff0, coeffLarger); - doTest(CompoundTest.all(ExpectedValue.SUCCESS, "Tests of " + keyLength + "b " + CardUtil.getKeyTypeString(KeyPair.ALG_EC_F2M), setup, wrong)); - } - - /* - * TODO: tests for both Fp and F2m: - * - generator not on curve, - * - generator not on proper subgroup of curve(as specified by order/cofactor), - * - wrong order, - * - wrong cofactor. - */ - } - - private Test ecdhTest(Command setupCmd, String prepareDesc, String fullDesc) { - Test setup = CommandTest.expect(setupCmd, ExpectedValue.FAILURE); - Test generate = CommandTest.expect(new Command.Generate(this.card, ECTesterApplet.KEYPAIR_BOTH), ExpectedValue.FAILURE); - Test preparePhase = CompoundTest.any(ExpectedValue.SUCCESS, prepareDesc, setup, generate); - Test allocateECDH = CommandTest.expect(new Command.AllocateKeyAgreement(this.card, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.SUCCESS); - Test ecdh = CommandTest.expect(new Command.ECDH(this.card, ECTesterApplet.KEYPAIR_LOCAL, ECTesterApplet.KEYPAIR_REMOTE, ECTesterApplet.EXPORT_FALSE, EC_Consts.TRANSFORMATION_NONE, EC_Consts.KeyAgreement_ALG_EC_SVDP_DH), ExpectedValue.FAILURE); - - - return CompoundTest.function((tests) -> { - if (preparePhase.ok() | !allocateECDH.ok() | ecdh.ok()) { - return new Result(Result.Value.SUCCESS, "All tests had the expected result."); - } else { - return new Result(Result.Value.FAILURE, "Some tests did not have the expected result."); - } - }, (tests) -> { - preparePhase.run(); - if (preparePhase.ok()) { - return; - } - allocateECDH.run(); - if (!allocateECDH.ok()) { - return; - } - ecdh.run(); - }, fullDesc, preparePhase, allocateECDH, ecdh); - } -} diff --git a/src/cz/crcs/ectester/reader/test/CommandTest.java b/src/cz/crcs/ectester/reader/test/CommandTest.java deleted file mode 100644 index b05d3e4..0000000 --- a/src/cz/crcs/ectester/reader/test/CommandTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.SimpleTest; -import cz.crcs.ectester.common.test.TestCallback; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; - -import java.util.Arrays; - -/** - * A simple test that runs one Command to get and evaluate one Response - * to get a Result and compare it with the expected one. - * - * @author Jan Jancar johny@neuromancer.sk - */ -public class CommandTest extends SimpleTest<CommandTestable> { - private CommandTest(CommandTestable command, TestCallback<CommandTestable> callback) { - super(command, callback); - } - - public static CommandTest function(CommandTestable command, TestCallback<CommandTestable> callback) { - return new CommandTest(command, callback); - } - - public static CommandTest function(Command command, TestCallback<CommandTestable> callback) { - return function(new CommandTestable(command), callback); - } - - public static CommandTest expect(CommandTestable command, Result.ExpectedValue expected, String ok, String nok) { - return new CommandTest(command, new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable commandTestable) { - Result.Value resultValue = Result.Value.fromExpected(expected, commandTestable.ok(), commandTestable.error()); - return new Result(resultValue, commandTestable.error() ? commandTestable.errorCause() : (resultValue.ok() ? ok : nok)); - } - }); - } - - public static CommandTest expect(Command command, Result.ExpectedValue expectedValue, String ok, String nok) { - return expect(new CommandTestable(command), expectedValue, ok, nok); - } - - public static CommandTest expect(CommandTestable command, Result.ExpectedValue expected) { - return expect(command, expected, null, null); - } - - public static CommandTest expect(Command command, Result.ExpectedValue expectedValue) { - return expect(command, expectedValue, null, null); - } - - public static CommandTest expectSW(CommandTestable command, short... expectedSWS) { - return new CommandTest(command, new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable commandTestable) { - if (Arrays.equals(commandTestable.getResponse().getSWs(), expectedSWS)) { - return new Result(Result.Value.SUCCESS); - } else { - return new Result(Result.Value.FAILURE); - } - } - }); - } - - public static CommandTest expectSW(Command command, short... expectedSWS) { - return expectSW(new CommandTestable(command), expectedSWS); - } - - public Command getCommand() { - return testable.getCommand(); - } - - public Response getResponse() { - return testable.getResponse(); - } - - @Override - public String getDescription() { - if (hasRun) { - return testable.getResponse().getDescription(); - } else { - return testable.getCommand().getDescription(); - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/CommandTestable.java b/src/cz/crcs/ectester/reader/test/CommandTestable.java deleted file mode 100644 index f670534..0000000 --- a/src/cz/crcs/ectester/reader/test/CommandTestable.java +++ /dev/null @@ -1,44 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.common.test.BaseTestable; -import cz.crcs.ectester.common.test.TestException; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; - -import javax.smartcardio.CardException; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class CommandTestable extends BaseTestable { - private Command command; - private Response response; - - public CommandTestable(Command command) { - this.command = command; - } - - public Command getCommand() { - return command; - } - - public Response getResponse() { - return response; - } - - @Override - public void run() { - try { - response = command.send(); - } catch (CardException e) { - throw new TestException(e); - } - - hasRun = true; - if (response.error()) { - error = true; - } else if (response.successful()) { - ok = true; - } - } -} diff --git a/src/cz/crcs/ectester/reader/test/PerformanceTest.java b/src/cz/crcs/ectester/reader/test/PerformanceTest.java deleted file mode 100644 index f9cba46..0000000 --- a/src/cz/crcs/ectester/reader/test/PerformanceTest.java +++ /dev/null @@ -1,141 +0,0 @@ -package cz.crcs.ectester.reader.test; - -import cz.crcs.ectester.applet.ECTesterApplet; -import cz.crcs.ectester.common.test.Result; -import cz.crcs.ectester.common.test.SimpleTest; -import cz.crcs.ectester.common.test.TestCallback; -import cz.crcs.ectester.common.test.TestException; -import cz.crcs.ectester.reader.CardMngr; -import cz.crcs.ectester.reader.command.Command; -import cz.crcs.ectester.reader.response.Response; - -import javax.smartcardio.CardException; -import java.util.Arrays; - -/** - * @author Jan Jancar johny@neuromancer.sk - */ -public class PerformanceTest extends SimpleTest<CommandTestable> { - private CardMngr cardManager; - private long[] times; - private long[] reducedTimes; - private Response[] responses; - private long mean; - private long median; - private long mode; - private int count; - private String desc; - - private PerformanceTest(CardMngr cardManager, CommandTestable testable, int count, String desc) { - super(testable, new TestCallback<CommandTestable>() { - @Override - public Result apply(CommandTestable testable) { - return new Result(Result.Value.SUCCESS); - } - }); - this.cardManager = cardManager; - this.count = count; - this.desc = desc; - } - - public static PerformanceTest repeat(CardMngr cardManager, Command cmd, int count) { - return new PerformanceTest(cardManager, new CommandTestable(cmd), count, null); - } - - public static PerformanceTest repeat(CardMngr cardManager, String desc, Command cmd, int count) { - return new PerformanceTest(cardManager, new CommandTestable(cmd), count, desc); - } - - @Override - public String getDescription() { - String rest = String.format("Mean = %d ns, Median = %d ns, Mode = %d ns", mean, median, mode); - return (desc == null ? rest : desc + " (" + rest + ")"); - } - - @Override - protected void runSelf() { - long baseTime; - try { - new Command.SetDryRunMode(cardManager, ECTesterApplet.MODE_DRY_RUN).send(); - testable.run(); - baseTime = testable.getResponse().getDuration(); - testable.reset(); - testable.run(); - baseTime += testable.getResponse().getDuration(); - testable.reset(); - baseTime /= 2; - new Command.SetDryRunMode(cardManager, ECTesterApplet.MODE_NORMAL).send(); - } catch (CardException ce) { - throw new TestException(ce); - } - - times = new long[count]; - reducedTimes = new long[count]; - responses = new Response[count]; - for (int i = 0; i < count; ++i) { - testable.run(); - responses[i] = testable.getResponse(); - times[i] = responses[i].getDuration(); - reducedTimes[i] = times[i] - baseTime; - testable.reset(); - } - - mean = Arrays.stream(reducedTimes).sum() / count; - - long[] sorted = reducedTimes.clone(); - Arrays.sort(sorted); - if (count % 2 == 0) { - median = (sorted[(count / 2) - 1] + sorted[count / 2]) / 2; - } else { - median = sorted[count / 2]; - } - - long max_occurences = 0; - int i = 0; - while (i < count) { - long current_value = sorted[i]; - long current_occurences = 0; - while (i < count && sorted[i] == current_value) { - i++; - current_occurences++; - } - if (current_occurences > max_occurences) { - max_occurences = current_occurences; - mode = current_value; - } - } - result = callback.apply(testable); - } - - public long getCount() { - return count; - } - - public Command getCommand() { - return testable.getCommand(); - } - - public Response[] getResponses() { - return responses; - } - - public long[] getTimes() { - return times; - } - - public long[] getReducedTimes() { - return reducedTimes; - } - - public long getMean() { - return mean; - } - - public long getMedian() { - return median; - } - - public long getMode() { - return mode; - } -} |
