I'm trying to implement two way authentication flow for java card applet. Following is my approach.
Create EC (Eliptic curve) key pair for offcard applications.
Store the public key of the offcard application in the java card.
Sign input data from offcard application private key.
Verify it using offcard application public key stored in the java card applet.
I'm struggling at step two. All others seems trivial. I need to find a way to encode the public key created outside to card into byte array and then transfer that byte array to java card applet and reconstruct the public key and store it in the persistent memory.
Any hint on this.
Create an APDU with the following command data:
a short with the key size (the size of the order N)
send all the parameters except G (the base point) and W (the public key) and H as statically sized octet string (or byte array, if you are used to Java)
strip initial byte set to 00 if present
left padded with zero's bytes until you get the key size
send the G and W as uncompressed points
one byte 04
followed by both coordinates, sized using the method above
length is 2 times key size in bytes, plus one for the 04 indicator
optionally send the cofactor H as byte (but it's always 01 anyways)
use the set... methods to set the key
And presto, one EC key for you.
You can of course also parse a PKCS#8 EC key or use length indicators for each and every field, but this method is probably the most compact one.
To Achieve this you have to create a Javacard applet which....something like below
class MyApplet extends javacard.framework.Applet
{
// ...
public void process(APDU apdu)
{
// ...
byte[] buffer = apdu.getBuffer();
//Other stuff
}
}
To reach in public void process(APDU apdu) method you should select your applet with its AID after that every command will start reaching to this method.
You can create your own proprietary APDU to send "offcard application private key" and can get that here
byte[] buffer = apdu.getBuffer(); and then you can store it in a persistent array of your applet.
Related
Can we convert a member function of one class to that of another?
Using the Palisade library, I wanted to encrypt a private key using another key. However, the 'Encrypt' function in PKE takes variables of class 'Plaintext', and 'LPPublicKey'.
Also, is it possible to interact with elements of different cryptosystems, e.g. use symmetric key encryption of BinFHE to encrypt 'Plaintext' of PKE.
Recently I'm reading code of bouncycastle(java), I noticed that when using EdDSA, we are using org.bouncycastle.asn1.x509.SubjectPublicKeyInfo#getPublicKeyData to get publicKey in org.bouncycastle.jcajce.provider.asymmetric.edec.BCEdDSAPublicKey#populateFromPubKeyInfo. But when using RSA we are using org.bouncycastle.asn1.x509.SubjectPublicKeyInfo#parsePublicKey in org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey#populateFromPublicKeyInfo.
The comment of parsePublicKey is for when the public key is an encoded object - if the bitstring can't be decoded this routine throws an IOException. and getPublicKeyData's is for when the public key is raw bits..
I am confused that how can we decide which method to use? Is this written in EdDSA spec or somewhere? I googled around and found nothing.
Edit:
Following is the info I collected, corret me if I'm wrong.
Both EdRsa publicKey and RSA publicKey is ASN.1 encoded,the use of org.bouncycastle.asn1.x509.SubjectPublicKeyInfo#getPublicKeyData is simply because EdRsa publicKey only contains one component (a simple byte array) while rsa key contains two component(modules and publicExp).
Almost all private key is pkcs#8 encoded, after all it's named "Private-Key Information Syntax Standard". But rsa privateKey can also encoded in pkcs#1 which cames before pkc#8, and those two formats can be converted back and force.
RFC 5280 specifies that X.509 public keys be encoded in a SubjectPublicKeyInfo ASN.1 SEQUENCE. This has two parts: the first ('algorithm') is an AlgorithmIdentifier which tells you what algorithm the key is for, and the second ('subjectPublicKey') is an ASN.1 BIT STRING whose interpretation is algorithm-dependent.
In the case of EdDSA, its use in X.509 was specified in RFC 8410. That RFC provides the OBJECT IDENTIFIER to use in the 'algorithm' for Ed25519/Ed448 and retains the public key format specified in the original EdDSA RFC - RFC 8032 i.e. a byte string, so that's what goes in the 'subjectPublicKey'.
My question is whether it is possible to lock an applet from within the code of the applet itself as a countermeasure to detected manipulations from within the code.
The obvious choice is to use GPSystem.lockCard(); and it works, however I wonder if it is possible to only lock the applet. Also I can lock the applet itself from an authenticated session of the associated security domain. But is it possible from the applet code itself. It seems, given the GPSystem.setCardContentState(); method used with GPSystem.APPLICATION_LOCKED, so I also tested that but it does not work.
Rereading the description of the GP Card specification 2.2 PDF:
The OPEN shall reject any transition request from the Life Cycle State LOCKED;
In my Eclipse, the JavaDoc says:
The OPEN shall reject any transition request to the Life Cycle State LOCKED
What's going on here?
It's interesting to see how this mechanism evolved from GlobalPlatform Card specification 2.1.1 to 2.2.1 (still the same in 2.3):
In GP 2.1.1, only the card issuer (off-card entity) or the OPEN (as a result of "exceptions") is allowed to initiate locking of an application:
The Card Issuer has a mechanism to disable the continued execution status of an on-card Application. This mechanism may be invoked from within the OPEN based on exceptions handled by the OPEN or from the use of externally invoked commands. The Card Issuer is the only entity that may initiate the locking of an Application.
The method GPSystem.setCardContentState() is clearly defined to allow only state changes to application specific life-cycle states (values between 0x07 and 0x7F with the lowest 3 bits set). Since the constant for APPLICATION_LOCKED in later specifications is 0x80 setting this state is not allowed. This is also made clear in the notes to this method:
The OPEN shall reject any transition request to the Life Cycle States INSTALLED or LOCKED.
Consequently, trying to set the application state to locked from within the application itself must fail on a card implementing GP 2.1.1.
UPDATE (2016-05-20): I tested this on a few NXP JCOP cards (that are claimed to comply to GP 2.1.1) and setting values that have the upper bit set or any of the lower 3 bits cleared indeed fails.
This changed in GP 2.2. Now, an application is allowed to lock itself:
The card has a mechanism to disable and subsequently re-enable the continued execution status of an on-card
Application. This mechanism may be invoked from within the OPEN based on exceptions handled by the OPEN or
from the use of externally invoked commands. An Application with Global Lock privilege, the Application itself or
a directly or indirectly associated Security Domain are the only entities that may initiate the locking of an
Application.
The GP Card specification does not require an application to hold any specific permission to lock itself.
Unfortunately, the API specification for the method GPSystem.setCardContentState() is still not quite clear. First, the description of the method still states that only values between 0x07 and 0x7F with the lowest 3 bits set must be allowed:
This method sets the Application specific Life Cycle State of the current applet context. Application specific Life Cycle States range from 0x07 to 0x7F as long as the 3 low order bits are set.
Second, there are deviating notes in the API documentation thats part of appendix A of the GP Card specification 2.2 document and the JavaDoc in the API export files. While the notes in the specification were changed to:
The OPEN shall reject any transition request to the Life Cycle State INSTALLED;
The OPEN shall reject any transition request from the Life Cycle State LOCKED;
The notes in the API export files (GPSystem.java and JavaDoc) remained the same as in GP 2.1.1.
Consequently, if this method was implemented according to the specification, it should still reject setting the application life-cycle state to APPLICATION_LOCKED.
UPDATE (2016-05-20): I tested this on a NXP J3D081 (JCOP v2.4.2 R2) card (that is claimed to comply to GP 2.2). Setting values that have the upper bit set or any of the lower 3 bits cleared, unfortunately, fails.
However, there is also the method GPRegistryEntry.setState(). The documentation of this method states that:
A transition request to Life Cycle state other than APPLICATION_LOCKED and APPLICATION_UNLOCKED shall be accepted only if the invoking Application corresponds to this GPRegistryEntry;
An Application shall be able to lock and shall not be able to unlock itself;
Thus, it would be interesting to see if the following worked on the same card where using setCardContentState() failed:
GPSystem.getRegistryEntry(null).setState(GPSystem.APPLICATION_LOCKED);
UPDATE (2016-05-20): I tested this on a NXP J3D081 (JCOP v2.4.2 R2) card (that is claimed to comply to GP 2.2). Unfortunately, this fails as well. Btw. it does not seem to make a difference if null or JCSystem.getAID() is used as parameter for getRegistryEntry().
UPDATE (2016-06-14): According to Paul Bastian, an NXP representative has confirmed that applications cannot set themselves to locked state on JCOP v2.4.x cards.
UPDATE (2016-06-06): I tested this on a Infineon SLE97CNFX card (that is claimed to comply to GP 2.2.1) and it worked. I could successfully set the state to locked by using APPLICATION_LOCKED (0x80). The state is then set to previous_state | 0x80. Trying to set other state values that have the upper bit set (e.g. 0x8F) does not work (just as I expected).
In GP 2.2.1, the documentation of the method GPSystem.setCardContentState() was changed (again). The change note clearly indicates that the method was updated to now allow an application to lock itself (export file version 1.5. maps to GP 2.2.1):
export file version 1.5: this method now allows the application associated with the current applet context to lock itself.
The method definition was changed to:
This method allows the application associated with the current applet context to change its state to an application specific life cycle state or to lock itself. An application cannot unlock itself using this method.
The value range for the state parameter passed to the method now explicitly includes the value of APPLICATION_LOCKED:
bState - an application specific life cycle state (0x07 to 0x7F with 3 low order bits set), or APPLICATION_LOCKED (0x80).
Consequently, cards implementing GP 2.2.1 or higher should eventually allow applications to change their own life-cycle state to locked using the method GPSystem.setCardContentState().
UPDATE (2016-06-06): I tested this on a Infineon SLE97CNFX card (that is claimed to comply to GP 2.2.1 (or is it 2.3?)) and it worked. I could successfully set the state to locked by using APPLICATION_LOCKED (0x80). The state is then set to previous_state | 0x80. Trying to set other state values that have the upper bit set (e.g. 0x8F) does not work (just as I expected).
An alternative solution
What you could do to overcome your problem without being able to set the application life-cycle to state APPLICATION_LOCKED, is to use application-specific life-cycle states:
public class LockableApplet extends Applet {
[... applet installation / instantiation code ...]
private static final byte APPLICATION_STATE_UNLOCKED = (byte)0x07;
private static final byte APPLICATION_STATE_LOCKED = (byte)0x7F;
public boolean select() {
if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) {
return false;
}
return true;
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
if (GPSystem.getCardContentState() == APPLICATION_STATE_LOCKED) {
ISOException.throwIt(ISO7816.SW_SECURITY_STATUS_NOT_SATISFIED);
}
[... applet logic code ...]
}
}
Upon detecting a problem that should cause your application to be locked, you could lock the applet with the following call:
GPSystem.setCardContentState(APPLICATION_STATE_LOCKED);
You could later unlock the application again using a SET STATUS command through the security domain.
(Buyer beware: It seems this way simply does not work -- see comments)
(In context of GlobalPlatform Card Specification 2.2.1)
You must obey the Application Life Cycle State rules depicted in figure 5-2 (the arrow marked '5' applies here).
The correct way should be:
GPSystem.setCardContentState((byte)(GPSystem.getCardContentState() | GPSystem.APPLICATION_LOCKED));
or
GPSystem.getRegistryEntry(JCSystem.getAID()).setState((byte)(GPSystem.getCardContentState() | GPSystem.APPLICATION_LOCKED))
The 0x80 life cycle state is invalid for an application. See table 11-4 ( at least the b1 and b2 bits must be set, the b3 bit probably as well).
EDIT>
(I confess to write this answer based solely on the remembrance of fact that OPEN keeps the original state from which the entity was locked)
I am quite curious about this so I did some tests using the following applet (excerpt):
public void process(APDU apdu) {
byte[] buffer = apdu.getBuffer();
if(selectingApplet()) {
return;
}
short claIns = Util.getShort(buffer, ISO7816.OFFSET_CLA);
switch(claIns) {
case (short) 0x8007:
buffer[0]=GPSystem.getCardContentState();
if(buffer[0]==buffer[ISO7816.OFFSET_P1]) {
if(GPSystem.setCardContentState(buffer[ISO7816.OFFSET_P2])) {
buffer[1]=0x01;
} else {
buffer[1]=0x00;
}
} else {
buffer[1]=(byte)0xFF;
}
buffer[2]=GPSystem.getCardContentState();
apdu.setOutgoingAndSend((short)0, (short)3);
return;
default: {
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
return;
}
}
}
And the following APDUs:
8007070F03 // To test transition into Application Specific State
80070F8F03 // To test my theory
80070F8003 // To test the GPSystem.APPLICATION_LOCKED constant directly
The results for my set of cards (Gemalto, Morpho, JCOP -- unfortunately all of them are GP 2.1.1) are in line with Michael Roland's great answer and GP specs -- the application's attempt to block itself is refused.
Received response APDUs for all GP 2.1.1 cards:
8007070F03 -> 07010F9000 // Succeeded in transition from `07` to `0F`
80070F8F03 -> 0F000F9000 // Failed transition from `0F` to `8F`
80070F8003 -> 0F000F9000 // Failed transition from `0F` to `80`
Just a note: This tool is quite useful to determine the implemented GP version as it parses the Card Recognition Data.
Yes. It is common and intended operation of a GlobalPlatform application. You must install your application with the right privilege (gp -install -privs CardLock) and the code to do it is:
GPSystem.setCardContentState(GPSystem.APPLICATION_LOCKED);
You can later unlock the application with
gp -unlock-applet <aid>
There is no compliance to GP core spec per se. A product is GP compliant to a GP configuration. GP configuration are not free of charge. JCOP 2.4.x products are compliant to GP 2.2.x 'Mapping Guidelines of Existing GP 2.1.1 Implementation on v2.2.1' configuration. As the name suggests, this configuration is for backward compatibility mapping. Basically JCOP 2.4.x products are GP 2.1.1 compliant products only (with a couple features from GP 2.2.x). Global Lock privilege is optional for applets.
Yes, it is quite simple: use a private static boolean flag and check it in the beginning of the process(APDU apdu) method:
public class MiniApplet extends Applet {
public static void install(byte[] bArray, short bOffset, byte bLength) {
new MiniApplet();
}
protected MiniApplet() {
register();
}
private static final short SW_APPLET_IS_LOCKED = (short) 0x9199; //any error SW
private static boolean appletLocked = false; //static -> faster access, this flag is checked each call! "private" modifier is VERY important!
public void process(APDU apdu) {
if (selectingApplet()) {
return; //it is a good practice not to throw any exceptions on SELECT command
}
if (appletLocked) {
ISOException.throwIt(SW_APPLET_IS_LOCKED);
}
if (attackDetected()) { //implement your attack detection
appletLocked = true;
}
}
}
With regards to implementing the IDataProtector interface, both of the interfaces methods, Protect and Unprotect both receive a byte array as a parameter.
What is actually in this byte array? Is it encrypted data? What format is it in? I have not been able to find any documentation related to this other than indicating it is user data.
Well it can be whatever you want. For exaple if you are using SecureDataFormat<AuthenticationTicket> there is
public string Protect(TData data)
{
return this._encoder.Encode(this._protector.Protect(this._serializer.Serialize(data)));
}
So as you can see the IDataProtector.Protect is used on serialized object. In this case AuthenticationTicket
I have a midlet which has got a static variable. I need to keep the record of all the instances created in this variable. but it does not work like static variable. my code segments look like this. I am running this midlet on sun wireless toolkit 2.5.5. I can create many objects of same midlet from that toolkit but still my counter shows only 1.
public class SMS extends MIDlet implements CommandListener {
private Display display;
private TextField userID, password ;
public static int counter ;
public SMS() {
userID = new TextField("LoginID:", "", 10, TextField.ANY);
password = new TextField("Password:", "", 10, TextField.PASSWORD);
counter++;
}
public void startApp() {
display = Display.getDisplay(this);
loginForm.append(userID);
loginForm.append(password);
loginForm.addCommand(cancel);
loginForm.addCommand(login);
loginForm.setCommandListener(this);
display.setCurrent(loginForm);
public void commandAction(Command c, Displayable d) {
String label = c.getLabel();
System.out.println("Total Instances"+counter);
everytime, counter shows only 1 object created.
The only system I've seen that allows static variables to remain between 'invocations' of an application is Android. I've never once seen a J2ME device that maintains static data between invocations of a MIDlet. However, MIDlets within a MIDlet suite can share static data, as described here, while at least one of them is running.
If you want to maintain data between invocations of a MIDlet, you need to use the Record Store APIs in javax.microedition.rms, which provide access to a persistent store.
Your MIDlet is only instantiated once. Kind of.
The MIDP runtime will probably not allow you to launch the same MIDlet twice as long as it is already running.
If you exit the MIDlet, counter goes back to 0 because it is still a in-RAM value and the Java Virtual Machine process is terminated.
On some Nokia series40 phones, the JVM process is never terminated so you could use this to show how many times the MIDlet was created since the last time the phone was switched on.
Static variables are stored in a Class object in the JVM memory. You need to understand class loading (and the usual lack of support for class unloading in J2ME) to figure out what you can store in static variable.
I would suggest moving counter++; to startApp() as it could be called everytime the MIDlet is brought to the foreground.
That would also allow you to store counter in an RMS record for additional accuracy.