Javacard applet self-closing

My question is whether it is possible to block the applet from the code of the applet itself as a countermeasure to detect manipulations inside the code.

The obvious choice is to use GPSystem.lockCard(); , and it works, however I wonder if it’s only possible to block the applet. I can also block the applet itself from an authenticated session of the associated security domain. But is this possible from the applet code itself. It seems given the GPSystem.setCardContentState(); method GPSystem.setCardContentState(); used with GPSystem.APPLICATION_LOCKED , so I also checked this, but it does not work.

Rereading the description of the GP card 2.2 PDF specification:

OPEN must reject any request for a transition from the LOCKED lifecycle state;

In my Eclipse, JavaDoc says:

OPEN rejects any LOCKED lifecycle transition request

What's going on here?

+7
security lifecycle smartcard javacard globalplatform
source share
5 answers

It is interesting to see how this mechanism evolved from the specification of the GlobalPlatform Card 2.1.1 platform to 2.2.1 (in the same 2.3):

  • In GP 2.1.1, it is allowed to initiate application blocking only to the card issuer (non-corporate entity) or OPEN (as a result of "exceptions"):

    The card issuer has a mechanism to disable the continuation status of the application on the card. This mechanism can be called from OPEN based on exceptions handled by OPEN or due to the use of commands called from outside. The card issuer is the only entity that can initiate an application lock.

    The GPSystem.setCardContentState() method is clearly defined to allow only state changes for specific application life cycles (values ​​between 0x07 and 0x7F with a minimum set of 3 bits). Since the constant for APPLICATION_LOCKED in later 0x80 specifications, setting this state is not allowed. This is also clearly visible in the notes to this method:

    • OPEN must reject any request to transition to an INSTALLED or LOCKED lifecycle state.

    Therefore, an attempt to set the application state for blocking from the application itself should fail on a card that implements GP 2.1.1.

    UPDATE (2016-05-20): I tested this on several NXP JCOP cards (which are said to comply with GP 2.1.1) and set values ​​that have the upper bit or any of the 3 bits cleared, really don't working.

  • This has changed in GP 2.2. Now the application can block itself:

    The card has a mechanism for disabling and then enabling the status of the continuation of work on the card Application. This mechanism can be called from OPEN based on exceptions handled by OPEN or from using commands called from outside. An application with the Global Lock privilege, the application itself or the security domain directly or indirectly associated with it are the only objects that can initiate an Application lock.

    The GP Card specification does not require the application to retain any specific rights to lock itself.

    Unfortunately, the API specification for the GPSystem.setCardContentState() method is still not entirely clear. First, the method description still claims that only values ​​between 0x07 and 0x7F are allowed with a minimum set of 3 bits:

    This method sets the specific application lifecycle state for the current applet context. The specific life conditions of the life cycle vary from 0x07 to 0x7F if the three least significant bits are set.

    Secondly, there are distinguishing notes in the API documentation that are part of Appendix A of the GP Card 2.2 specification document and JavaDoc in the API export files. Although the notes in the specification have been changed to:

    • OPEN must reject any request to transition to the INSTALLED lifecycle state;
    • OPEN must reject any request for a transition from the LOCKED lifecycle state;

    The notes in the API export files (GPSystem.java and JavaDoc) remained the same as in GP 2.1.1.

    Therefore, if this method was implemented in accordance with the specification, it should still reject the application lifecycle setting to APPLICATION_LOCKED .

    UPDATE (2016-05-20): I tested this on the NXP card J3D081 (JCOP v2.4.2 R2) (which is claimed to comply with GP 2.2). Unfortunately, it is not possible to set the values ​​that have the upper bit or any of the 3 bits reset, unfortunately.

    However, there is also the GPRegistryEntry.setState() method. The documentation for this method states that:

    • A transition request to a lifecycle state other than APPLICATION_LOCKED and APPLICATION_UNLOCKED is only accepted if the calling application matches this GPRegistryEntry;
    • The application must be able to block and will 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 the NXP card J3D081 (JCOP v2.4.2 R2) (which is claimed to comply with GP 2.2). Unfortunately, this also fails. Btw. it doesn’t matter if null or JCSystem.getAID() used as the parameter for JCSystem.getAID() .

    UPDATE (2016-06-14): According to Paul Bastian , an NXP spokesperson confirmed that applications cannot set themselves blocked on JCOP v2.4.x cards.

    UPDATE (2016-06-06): I tested this on an Infineon SLE97CNFX card (which allegedly complies with GP 2.2.1) and it worked. I could successfully lock the state using APPLICATION_LOCKED (0x80). Then the state is set to previous_state | 0x80 previous_state | 0x80 . Trying to set other status values ​​that have a high bit (e.g. 0x8F) does not work (as expected).

  • In GP 2.2.1, the documentation for the GPSystem.setCardContentState() method was changed (again). The change notice clearly states that the method has been updated so far so that the application can block itself (export the file version 1.5. Maps in GP 2.2.1):

    • export file version 1.5: this method now allows the application associated with the current applet context to block itself.

    The definition of the method has been changed to:

    This method allows the application associated with the current context of the applet to change its state to a specific state of the application's life cycle or block itself . The application cannot unlock itself using this method.

    The range of values ​​for the state parameter passed to the method now explicitly includes the value APPLICATION_LOCKED :

    bState - application life cycle state (from 0x07 to 0x7F with three sets of low order bits) or APPLICATION_LOCKED (0x80).

    Consequently, cards that implement GP 2.2.1 or higher should ultimately allow applications to change their lifecycle status to lock using the GPSystem.setCardContentState() method.

    UPDATE (2016-06-06): I tested this on an Infineon SLE97CNFX card (which allegedly matches GP 2.2.1 (or is it 2.3?)) And it worked. I could successfully lock the state using APPLICATION_LOCKED (0x80). Then the state is set to previous_state | 0x80 previous_state | 0x80 . Trying to set other status values ​​that have a high bit (e.g. 0x8F) does not work (as expected).

Alternative solution

What you can do to overcome your problem, without being able to set the application life cycle to the APPLICATION_LOCKED state, is to use the application 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 ...] } } 

If you find a problem that should lead to blocking your application, you can block the applet with the following call:

 GPSystem.setCardContentState(APPLICATION_STATE_LOCKED); 

You can later unlock the application again using the SET STATUS command through the security domain.

+7
source share

(Buyer beware: this method just doesn't seem to work - see comments)

(In the context of the global platform 2.1.1 map specification)

You must abide by the application life cycle state rules shown in Figure 5-2 (the arrow marked “5” is used here).

The right way:

 GPSystem.setCardContentState((byte)(GPSystem.getCardContentState() | GPSystem.APPLICATION_LOCKED)); 

or

 GPSystem.getRegistryEntry(JCSystem.getAID()).setState((byte)(GPSystem.getCardCo‌​ntentState() | GPSystem.APPLICATION_LOCKED)) 

The 0x80 lifecycle state is not valid for the application. See Table 11-4 (at least bits b1 and b2 should be set, possibly bit b3 ).

EDIT>

(I admit that I wrote this answer based solely on the memory that OPEN retains the original state from which the object was locked)

This is very interesting for me, 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) correspond to Michael Roland's excellent answer and GP specifications - an application attempt to block itself refuses.

Received APDU responses for all GP 2.1.1 boards:

 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 very useful for determining the implemented version of the GP when it analyzes the card recognition data.

+5
source share

Doesn't match the GP core specification at all. The product complies with the GP corresponding to the configuration of the GP. GP configuration is not free. JCOP 2.4.x products are compatible with GP 2.2.x "Guidelines for mapping implementation of the existing version of GP 2.1.1 in version 2.2.2." As the name suggests, this configuration is for backward compatibility mapping. Basically, JCOP 2.4.x products are products compatible only with GP 2.1.1 (with a couple of functions from GP 2.2.x). Global privilege lock is optional for applets.

+3
source share

Yes, it's pretty simple: use the private static boolean flag and check it at the beginning of the process(APDU apdu) method process(APDU apdu) :

 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; } } } 
+2
source share

Yes. This is the usual and intended operation of the GlobalPlatform application. You must install the application with the correct privilege (gp -install -privs CardLock), and the code for this:

 GPSystem.setCardContentState(GPSystem.APPLICATION_LOCKED); 

You can later unlock the application using

 gp -unlock-applet <aid> 
+2
source share

All Articles