Open sigalor opened 5 years ago
@sigalor I've never used the cref utility. Note that the sendHello task calls global platform pro with the following parameters (see logs) :
gp -d -a 00A404000A01020304050607080901 -a 0040000000
so you can test with global platform pro if you need to tweak parameters
Note that I have just updated the lib to work with the most recent version of global platform pro. Use 1.5.6 and add global platform pro dependency in build.gradle
:
apply plugin: 'javacard'
dependencies {
compile 'com.github.martinpaljak:globalplatformpro:18.09.14'
}
javacard {
....
}
@bertrandmartel Thanks a lot for your answer! So, I investigated further on this myself and found out the following. There are two methods of simulating a Java Card application.
First, the one I thought of initially using the cref
utility. It seems like it emulates the actual EEPROM, i.e. one somehow needs to write actual bytecode onto that 64K file. For that, the maskgen
utility is needed. Although there is no maskgen.bat
in the current JCDK 3.0.5u3, it's still there as com.sun.javacard.jcasm.mask.Main
in lib/tools.jar
. I found this class name, because maskgen.bat
still existed in JCDK 2.1.x, so I was able to extract it from there.
Yet, there is a problem: Maskgen needs a config file. I am really confused by this, as the documentation states that some "mapping to native functions" is supposed to happen. Additionally, I am not able to find the mentioned cref_mask.cfg
example file in any version of the JCDK or anywhere on the internet. Thus, the error Error: Entry PACKAGE_TABLE and/or PACKAGE_CONTEXT_TABLE missing from the configuration file.
output by Maskgen persists for now.
I think Maskgen is supposed to create a .c
file, according to this sketchy forum question (shoutout to Google Translate!). The .c
file is then passed to a smart card chip C compiler to eventually generate the binary code of the smart card chip. I have absolutely no idea where to find such a C compiler... Someone in that forum eventually wrote that some source code related to that needs to be licensed from Sun for millions of oceans (Taiwan dollars) (wtf?), so I decided to try to find another solution for now.
Then, I stumbled over a Q&A with a Java Card engineer from Oracle. She even wrote a book about Java Card. Although, because that article is from 2000, she is taking about JCDK 2.1.1 in it, I could still extract some useful information from it.
For this method, you need the Java Card Workstation Development Environment (JCWDE). Apparently, it has been dropped from JCDK 3.x releases, but version 2.2.2 still has it. The following JAR files are needed to execute it (they're all part of the lib
directory of that older version): apduio.jar
, api.jar
and jcwde.jar
. I just copied these files into the lib
directory of the newer 3.0.5u3 version.
To make invocation easier, I then wrote a small BASH script I put into jcdk-3.0.5u3/bin/jcwde.sh
:
#!/bin/bash
JCDK_ROOT=$(dirname "$0")/..
L=$JCDK_ROOT/lib/v2.2.2
CLASS_DIR=$1
shift
java -Djc.home=$JCDK_ROOT -classpath $L/jcwde.jar:$L/apduio.jar:$L/api.jar:$CLASS_DIR com.sun.javacard.jcwde.Main "$@"
Note that in the following, the environment variable JC_HOME
references my jcdk-3.0.5u3
directory.
Next, as a temporary solution, I created a file called jcwde.app
in a directory which also had the build.gradle
usable with this repository in it. That file contains the className
and aid
(with 0x prefixed to every byte), taken straight from an applet
definition in build.gradle
, concatenated with a space character. An example would be:
com.sun.jcclassic.samples.wallet.Wallet 0xA0:0x00:0x00:0x00:0x62:0x03:0x01:0x0C:0x06:0x01
Next, one needs to run the JCWDE with a command like the following. If it succeeds it outputs jcwde is listening for T=1 Apdu's on TCP/IP port 9.025.
and keeps running. Note that the project needs to have been compiled before for this, i.e. .class
files need to exist for your Java source files.
$JC_HOME/bin/jcwde.sh ./build/classes/java/main -p 9025 jcwde.app
We're almost done. There's just one more file to create: the list of APDU bytes to send. I just called it inputdata
and put it into the same directory as build.gradle
. For the Wallet demo app provided by Oracle, it could contain the following text (note the semicolons at the end of every row of bytes!):
output on;
powerup;
// create wallet applet
// 0x80 0xB8 0x00 0x00 0x14 0x0a 0xa0 0x0 0x0 0x0 0x62 0x3 0x1 0xc 0x6 0x1 0x08 0x0 0x0 0x05 0x01 0x02 0x03 0x04 0x05 0x7F;
// select Wallet
0x00 0xA4 0x04 0x00 0x0a 0xa0 0x0 0x0 0x0 0x62 0x3 0x1 0xc 0x6 0x1 0x7F;
// 90 00 = SW_NO_ERROR
// verify user pin
0x80 0x20 0x00 0x00 0x05 0x01 0x02 0x03 0x04 0x05 0x7F;
// 90 00 = SW_NO_ERROR
// get wallet balance
0x80 0x50 0x00 0x00 0x00 0x02;
// 0x00 0x00 0x00 0x00 0x90 0x00 = Balance = 0 and SW_ON_ERROR
powerdown;
Note that the initial powerup;
is absolutely crucial. If you omit it, ApduTool complains because Card is not initialized
. I commented out the create wallet applet message here, as everything seems to work without it equally well. The final powerdown;
is optional, but at least for me, the JDWDE terminates with java.lang.NullPointerException
after all APDU messages have been sent if I omit it; when I keep it in, it terminates gracefully.
So finally, the ApduTool command, which should be rather trivial; it just sends all data from inputfile
and outputs the responses (apdutool.sh
is just a quick wrapper I wrote around com.sun.javacard.apdutool.Main
in lib/tools.jar
).
$JC_HOME/bin/apdutool.sh -nobanner -noatr -p 9025 inputdata
Coming to an end, I hope you can forgive me for this wall of text. My main motivation of writing this down was that I couldn't find any real condensed information on this, as everyone developing with the JCDK seems to use the Eclipse plugin provided by Oracle.
As you can see, this entire process really isn't elegant, especially because of the JAR files needed from an older JCDK release. That's why I'd really appreciate if these instructions would be added to the repository. One could be able to specify whether to use GlobalPlatform or this type of simulator in the applet
section of build.gradle
. Additionally, the output of ApduTool could be parsed, so script
sections in build.gradle
could also contain the expected output, which would greatly ease unit test-based development.
Sadly, my knowledge in Gradle development is practically non-existent, so I won't be able to make any meaningful source code contributions to this repository. Thus, I am looking forward to its further development!
nice digging ! why not using jcardsim like in javacard-tutorial repo. This javacard plugin makes it easy to use it in a test sourceSet like this.
My personal advice if you come from Eclipse & are new to gradle :
build.gradle
You can build a new project from one of these module to start. In the test folder keep TestSuite
& JavaCardTest
to begin and add your own tests class extending JavaCardTest
. Update the TestSuite
with your own classes :
@RunWith(Suite.class)
@SuiteClasses({PasswordEntryTest.class, PasswordManagerTest.class}) <=== change this
public class TestSuite
Then you can start to develop while testing your applet(s) sending your own APDU and checking for the result etc...
Other project examples you can check :
I developped all projects above without physical card with only the tests using Jcardsim and tested on physical cards afterwards
When you have access to physical smartcard, in IntelIJ check the gradle tasks :
This plugin includes default tasks like installJavacard, listJavacard which are wrapping global platform pro and you can create yours using the scripts fields (check https://github.com/bertrandmartel/javacard-gradle-plugin#usage)
Note that if you use some external Javacard library like org.globalplatform, you would need to mock all those calls for instance here
Hi everyone!
First, thanks so much for this astonishing and incredibly useful repository! I recently started getting into JavaCard/SIM development, and without open source projects like this, I would definitely be completely lost.
Currently, I am trying out the examples from your
javacard-tutorial
repository. The CAP file generation and everything else before it runs perfectly fine, but, as I don't have a physical smart card and reader yet, I'd like to try it out on a simulator. The JavaCard Development Kit by Oracle comes with thecref
utility; that should be the simulator, right? Sadly, it comes as a Windows EXE file only, so one will need to usewine
to execute it on Mac/Linux (I tried it and it works).Still, it seems like currently, the Gradle plugin cannot use it yet. When I try something like
gradle sendHello
in the other repository, I get an error message like:And, well, the message The Smart card resource manager is not running. is a fairly clear indication of what's going on. So, does anyone know how I can use the simulator here?
Regarding my system setup: I'm using Ubuntu 16.04 with OpenJDK 1.8.0_181. My JavaCard Development Kit version is 3.0.5u3.