Skip to content

Commit 991c048

Browse files
authored
Merge pull request #269 from crocs-muni/devel
Version 1.8.2 release
2 parents 1bcd0cc + 65adb74 commit 991c048

27 files changed

+584
-404
lines changed
1.15 MB
Binary file not shown.

AlgTest_JClient/src/algtestjclient/AlgTestJClient.java

Lines changed: 148 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ may be distributed under the terms of the GNU General Public License (GPL),
4040
import java.util.logging.Level;
4141
import java.util.logging.Logger;
4242
import java.util.regex.PatternSyntaxException;
43+
import java.util.HashMap;
44+
import java.util.Map;
4345
import javax.smartcardio.ATR;
4446
import javax.smartcardio.Card;
4547
import javax.smartcardio.CardException;
@@ -51,12 +53,24 @@ may be distributed under the terms of the GNU General Public License (GPL),
5153
* @author petr
5254
*/
5355
public class AlgTestJClient {
56+
/**
57+
* Version 1.8.2 (17.11.2024)
58+
* - Update to match applet version with delayed allocation by default
59+
* - Add detailed info for submitting results at beginning
60+
* - Add testing of ECC 640b keys
61+
* - Fix display of help info
62+
* - Add always send Le=256 to support certain cards (like Gemalto) expecting it
63+
* - Add sanity check for returned algtest buffer
64+
* - Improved used and fixed issues with CLI parameters
65+
* - Fix missing JCSystem.MEMORY_TYPE_TRANSIENT_DESELECT in results
66+
*/
67+
public final static String ALGTEST_JCLIENT_VERSION = "1.8.2";
5468
/**
5569
* Version 1.8.1 (27.10.2021)
5670
* + Add better CLI control, interactive and non-interactive mode
5771
* + Fixed incorrect names for measurements
5872
*/
59-
public final static String ALGTEST_JCLIENT_VERSION = "1.8.1";
73+
//public final static String ALGTEST_JCLIENT_VERSION = "1.8.1";
6074
/**
6175
* Version 1.8.0 (19.12.2020)
6276
* + testing of modular Cipher and Signature .getInstance variants
@@ -165,72 +179,115 @@ public class AlgTestJClient {
165179
* + initial version of AlgTestJClient, clone of AlgTestCppClient
166180
*/
167181
//public final static String ALGTEST_JCLIENT_VERSION_1_0 = "1.0";
168-
169-
182+
170183
public final static int STAT_OK = 0;
171184

172185
// Unique start time in milisconds
173186
static long m_appStartTime = 0;
187+
188+
static Map<String, Map<String, String>> allResultsMap = new HashMap<>();
189+
174190

175191
/**
176192
* @param args the command line arguments
177193
*/
178194

179195
static DirtyLogger m_SystemOutLogger = null;
180196
public static void main(String[] args) throws IOException, Exception {
197+
Map<String, String> tempInfo = new HashMap<>();
198+
181199
Args cmdArgs = new Args();
182200
if (args.length > 0) {
183201
// cli version of tool
184202
JCommander.newBuilder()
185203
.addObject(cmdArgs)
186204
.build()
187205
.parse(args);
188-
206+
189207
if (!cmdArgs.baseOutPath.isEmpty()) {
190208
char lastChar = cmdArgs.baseOutPath.charAt(cmdArgs.baseOutPath.length() - 1);
191209
if ((lastChar != '\\') && (lastChar != '/')) {
192210
cmdArgs.baseOutPath = cmdArgs.baseOutPath + "/"; // adding '/' if not present
193211
}
194212
}
195213
}
214+
System.out.print("Command line arguments: ");
215+
for (int i = 0; i < args.length; i++) {
216+
System.out.print(args[i] + " ");
217+
}
218+
System.out.println();
196219

197220
String logFileName = String.format(cmdArgs.baseOutPath + "ALGTEST_log_%s.log", AlgTestJClient.getStartTime());
198221
FileOutputStream systemOutLogger = new FileOutputStream(logFileName);
222+
tempInfo.put("out_file_name", logFileName);
223+
allResultsMap.put("main", tempInfo);
199224
m_SystemOutLogger = new DirtyLogger(systemOutLogger, true);
200225

201226
m_SystemOutLogger.println("\n----------------------------------------------------------------------- ");
202227
m_SystemOutLogger.println("JCAlgTest " + ALGTEST_JCLIENT_VERSION + " - comprehensive tool for JavaCard smart card testing.");
203-
m_SystemOutLogger.println("Visit jcalgtest.org for results from 100+ cards. CRoCS lab 2007-2021.");
228+
m_SystemOutLogger.println("Visit jcalgtest.org for results from 100+ cards. CRoCS lab 2007-2024.");
204229
m_SystemOutLogger.println("Please check if you use the latest version at\n https://github.com/crocs-muni/JCAlgTest/releases/latest.");
205230
m_SystemOutLogger.println("Type 'java -jar jcalgtestclient --help' to display help and available commands.");
206231
m_SystemOutLogger.println("-----------------------------------------------------------------------\n");
207232

208233
CardTerminal selectedTerminal = null;
209234
PerformanceTesting testingPerformance = new PerformanceTesting(m_SystemOutLogger);
210235
m_SystemOutLogger.println("NOTE: JCAlgTest applet (AlgTest.cap) must be already installed on tested card.");
236+
m_SystemOutLogger.println(" java -jar gp.jar --install AlgTest_***_jc***.cap");
211237
m_SystemOutLogger.println("The results are stored in CSV files. Use JCAlgProcess for HTML conversion.");
212238
m_SystemOutLogger.println();
213239

214240
if (cmdArgs.help) {
215-
JCommander.newBuilder().addObject(cmdArgs).build().usage();
241+
JCommander.newBuilder().addObject(cmdArgs).build().usage();
242+
return;
216243
}
217-
218-
if (args.length > 0) {
219-
m_SystemOutLogger.println("Running in non-interactive mode. Run without any parameter to enter interactive mode. Run 'java -jar AlgTestJClient.jar -help' to obtain list of supported arguments.");
244+
245+
// If selftest is enabled, then prepare testing session with simulator, execute and check for results
246+
if (cmdArgs.selftest) {
247+
cmdArgs.simulator = true;
248+
cmdArgs.fresh = true;
249+
cmdArgs.cardName = Args.SELFTEST_CARD_NAME;
250+
cmdArgs.operations.clear();
251+
cmdArgs.operations.add(Args.OP_ALG_SUPPORT_EXTENDED);
252+
cmdArgs.operations.add(Args.OP_ALG_ECC_PERFORMANCE);
253+
cmdArgs.operations.add(Args.OP_ALG_FINGERPRINT);
254+
cmdArgs.operations.add(Args.OP_ALG_PERFORMANCE_STATIC);
255+
cmdArgs.operations.add(Args.OP_ALG_PERFORMANCE_VARIABLE);
256+
}
257+
258+
printSendRequest();
259+
if (cmdArgs.operations.size() > 0) {
260+
m_SystemOutLogger.println("Running in non-interactive mode. Run without any parameter to enter interactive mode. Run 'java -jar AlgTestJClient.jar --help' to obtain list of supported arguments.");
220261
for (String operation : cmdArgs.operations) {
221262
if (operation.compareTo(Args.OP_ALG_SUPPORT_BASIC) == 0 ||
222263
operation.compareTo(Args.OP_ALG_SUPPORT_EXTENDED) == 0) {
223264
selectedTerminal = selectTargetReader(cmdArgs);
224265
if (selectedTerminal != null) {
225266
SingleModeTest singleTest = new SingleModeTest(m_SystemOutLogger);
226-
singleTest.TestSingleAlg(operation, cmdArgs, selectedTerminal);
267+
Map<String, String> testResults = singleTest.TestSingleAlg(operation, cmdArgs, selectedTerminal);
268+
allResultsMap.put(operation, testResults);
227269
}
228270
}
229271
else if (operation.compareTo(Args.OP_ALG_PERFORMANCE_STATIC) == 0 ||
230272
operation.compareTo(Args.OP_ALG_PERFORMANCE_VARIABLE) == 0) {
231273
selectedTerminal = selectTargetReader(cmdArgs);
232274
if (selectedTerminal != null) {
233-
testingPerformance.testPerformance(false, operation, selectedTerminal, cmdArgs);
275+
Map<String, String> testResults = testingPerformance.testPerformance(false, operation, selectedTerminal, cmdArgs);
276+
allResultsMap.put(operation, testResults);
277+
}
278+
}
279+
else if (operation.compareTo(Args.OP_ALG_ECC_PERFORMANCE) == 0) {
280+
selectedTerminal = selectTargetReader(cmdArgs);
281+
if (selectedTerminal != null) {
282+
Map<String, String> testResults = testingPerformance.testECCPerformance(args, true, selectedTerminal, cmdArgs);
283+
allResultsMap.put(operation, testResults);
284+
}
285+
}
286+
else if (operation.compareTo(Args.OP_ALG_FINGERPRINT) == 0) {
287+
selectedTerminal = selectTargetReader(cmdArgs);
288+
if (selectedTerminal != null) {
289+
Map<String, String> testResults = testingPerformance.testPerformanceFingerprint(args, selectedTerminal, cmdArgs);
290+
allResultsMap.put(operation, testResults);
234291
}
235292
}
236293
else {
@@ -241,7 +298,7 @@ else if (operation.compareTo(Args.OP_ALG_PERFORMANCE_STATIC) == 0 ||
241298
}
242299
else {
243300
// Interactive mode of tool
244-
m_SystemOutLogger.println("Running in interactive mode. Run 'java -jar AlgTestJClient.jar -help' to obtain list of supported arguments.");
301+
m_SystemOutLogger.println("Running in interactive mode. Run 'java -jar AlgTestJClient.jar --help' to obtain list of supported arguments.");
245302
m_SystemOutLogger.println("CHOOSE test you want to run:");
246303
m_SystemOutLogger.println("1 -> SUPPORTED ALGORITHMS\n List all supported JC API algorithms (2-10 minutes)\n" +
247304
"2 -> PERFORMANCE TEST\n Test all JC API methods with 256B data length (1-3 hours)\n" +
@@ -297,6 +354,10 @@ else if (operation.compareTo(Args.OP_ALG_PERFORMANCE_STATIC) == 0 ||
297354
}
298355
}
299356
printSendRequest();
357+
358+
if (cmdArgs.selftest) {
359+
checkSelfTestResults(allResultsMap);
360+
}
300361
}
301362

302363
static long getStartTime() {
@@ -312,8 +373,9 @@ static void printSendRequest() {
312373
System.out.println("available to all JavaCard enthusiasts at http://jcalgtest.org.");
313374
System.out.println("The results are important even if a card of same type is already in database.");
314375
System.out.println("Send *.log and *.csv files from the current directory to <petr@svenda.com>.");
315-
System.out.println("Thank you very much!");
316-
System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*");
376+
System.out.println("ESPECIALLY if testing fails, please let us know so we can fix it for you and others.");
377+
System.out.println("Thank you very much.");
378+
System.out.println("-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\n");
317379
}
318380

319381
static void performKeyHarvest(Args cmdArgs) throws CardException {
@@ -444,8 +506,10 @@ static CardTerminal selectTargetReader(Args cmdArgs) {
444506
m_SystemOutLogger.println("\nAvailable readers:");
445507
for (CardTerminal terminal : terminalList) {
446508
Card card;
509+
String protocol = System.getenv().getOrDefault("ALGTEST_PROTO", "*");
447510
try {
448-
card = terminal.connect("*");
511+
card = terminal.connect(protocol);
512+
//card = terminal.connect("*");
449513
ATR atr = card.getATR();
450514
m_SystemOutLogger.println(String.format("%d : [*] %s - %s", terminalIndex, terminal.getName(), CardMngr.bytesToHex(atr.getBytes())));
451515
terminalIndex++;
@@ -470,4 +534,73 @@ static CardTerminal selectTargetReader(Args cmdArgs) {
470534
}
471535
}
472536

537+
private static boolean checkFileExistence(String fileName) {
538+
File file = new File(fileName);
539+
if (file.exists()) {
540+
m_SystemOutLogger.println(String.format(" OK: the file '%s' exists.", fileName));
541+
} else {
542+
m_SystemOutLogger.println(String.format(" ERROR: the file '%s' does not exist.", fileName));
543+
}
544+
return file.exists();
545+
}
546+
547+
private static boolean checkExpectedValue(Map<String, Map<String, String>> allResults, String op, String key, String expectedValue) {
548+
if (allResults.get(op).get(key).equalsIgnoreCase(expectedValue)){
549+
m_SystemOutLogger.println(String.format(" OK: %s->%s = %s matches.", op, key, expectedValue));
550+
} else {
551+
m_SystemOutLogger.println(String.format(" ERROR: %s->%s = %s mismatch (expected=%s).", op, key, allResults.get(op).get(key), expectedValue));
552+
}
553+
return allResults.get(op).get(key).equalsIgnoreCase(expectedValue);
554+
}
555+
556+
public static boolean checkSelfTestResults(Map<String, Map<String, String>> allResults) {
557+
boolean bSelftestSuccess = true;
558+
// Print all collected info keys
559+
m_SystemOutLogger.println("###### SELFTEST ####################################");
560+
m_SystemOutLogger.println("All collected selftest results:");
561+
for (String operation : allResults.keySet()) {
562+
m_SystemOutLogger.println(String.format(" %s:", operation));
563+
Map<String, String> oneOpResults = allResults.get(operation);
564+
for (String key : oneOpResults.keySet()) {
565+
m_SystemOutLogger.println(String.format(" %s = %s", key, oneOpResults.get(key)));
566+
}
567+
}
568+
569+
// Check existence of output files for separate operations
570+
m_SystemOutLogger.println("\nSelftest tests finished, now checking results...");
571+
for (String op : allResults.keySet()) {
572+
m_SystemOutLogger.println(String.format(" Checking operation '%s':", op));
573+
// Always check existence of output file
574+
if (!checkFileExistence(allResults.get(op).get("out_file_name"))) { bSelftestSuccess = false; }
575+
// Check selected values for selected results
576+
if (op.equals(Args.OP_ALG_PERFORMANCE_STATIC)) {
577+
if (!checkExpectedValue(allResults, op, "NO_SUCH_ALGORITHM", "290")) { bSelftestSuccess = false; }
578+
if (!checkExpectedValue(allResults, op, "CANT_BE_MEASURED", "204")) { bSelftestSuccess = false; }
579+
if (!checkExpectedValue(allResults, op, "ILLEGAL_VALUE", "66")) { bSelftestSuccess = false; }
580+
if (!checkExpectedValue(allResults, op, "errors_observed", "560")) { bSelftestSuccess = false; }
581+
}
582+
if (op.equals(Args.OP_ALG_PERFORMANCE_VARIABLE)) {
583+
if (!checkExpectedValue(allResults, op, "NO_SUCH_ALGORITHM", "145")) { bSelftestSuccess = false; }
584+
if (!checkExpectedValue(allResults, op, "CANT_BE_MEASURED", "327")) { bSelftestSuccess = false; }
585+
if (!checkExpectedValue(allResults, op, "ILLEGAL_VALUE", "35")) { bSelftestSuccess = false; }
586+
if (!checkExpectedValue(allResults, op, "errors_observed", "507")) { bSelftestSuccess = false; }
587+
}
588+
if (op.equals(Args.OP_ALG_FINGERPRINT)) {
589+
if (!checkExpectedValue(allResults, op, "NO_SUCH_ALGORITHM", "1")) { bSelftestSuccess = false; }
590+
if (!checkExpectedValue(allResults, op, "CANT_BE_MEASURED", "18")) { bSelftestSuccess = false; }
591+
if (!checkExpectedValue(allResults, op, "ILLEGAL_VALUE", "8")) { bSelftestSuccess = false; }
592+
if (!checkExpectedValue(allResults, op, "errors_observed", "27")) { bSelftestSuccess = false; }
593+
}
594+
if (op.equals(Args.OP_ALG_ECC_PERFORMANCE)) {
595+
if (!checkExpectedValue(allResults, op, "errors_observed", "0")) { bSelftestSuccess = false; }
596+
}
597+
}
598+
if (!bSelftestSuccess) {
599+
m_SystemOutLogger.println("ERROR: some test(s) failed");
600+
}
601+
m_SystemOutLogger.println("###### END SELFTEST ####################################");
602+
603+
return bSelftestSuccess;
604+
}
605+
473606
}

AlgTest_JClient/src/algtestjclient/Args.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,20 @@
99
* @author Petr Svenda
1010
*/
1111
public class Args {
12+
// If extending, do not forget to add into @Parameter(names = below
1213
public static final String OP_ALG_SUPPORT_BASIC = "ALG_SUPPORT_BASIC"; // Test of basic algorithmic support
1314
public static final String OP_ALG_SUPPORT_EXTENDED = "ALG_SUPPORT_EXTENDED"; // Test of basic + extended algorithmic support
1415
public static final String OP_ALG_PERFORMANCE_STATIC = "ALG_PERFORMANCE_STATIC"; // Test of performance on static data length
1516
public static final String OP_ALG_PERFORMANCE_VARIABLE = "ALG_PERFORMANCE_VARIABLE"; // Test of performance with variable data lengths
17+
public static final String OP_ALG_ECC_PERFORMANCE = "ALG_ECC_PERFORMANCE"; // Test of performance of ECC operations
18+
public static final String OP_ALG_FINGERPRINT = "ALG_FINGERPRINT"; // Test only selected operations
19+
public static final String SELFTEST_CARD_NAME = "simul-selftest"; // Name of the simulated card using during
1620

1721
@Parameter
1822
public List<String> parameters = new ArrayList<>();
1923

20-
@Parameter(names = { "-op"}, description = "Operation(s) to execute (ALG_SUPPORT_SIMPLE | ALG_SUPPORT_ALL)")
24+
@Parameter(names = { "-op"}, description = "Operation(s) to execute (" + OP_ALG_SUPPORT_BASIC + " | " + OP_ALG_SUPPORT_EXTENDED
25+
+ " | " + OP_ALG_PERFORMANCE_STATIC + " | " + OP_ALG_PERFORMANCE_VARIABLE + ")")
2126
public List<String> operations = new ArrayList<>();
2227

2328
@Parameter(names = "-cardname", description = "Name of the tested card")
@@ -34,4 +39,8 @@ public class Args {
3439

3540
@Parameter(names = "-fresh", description = "Force generating new complete measurements")
3641
public boolean fresh = false;
42+
43+
@Parameter(names = "-selftest", description = "Executes selftesting using simulator as target.")
44+
public boolean selftest = false;
45+
3746
}

0 commit comments

Comments
 (0)