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).