10

I have a java card and i write a small code to send APDU to java card. here when i am sending Init_Update command , m getting 0x6985 like:-

CMD -> 80 50 00 00 08 11 22 33 44 55 66 77 88
RES <- 6985

But when I am sending this command with other tool , it is giving required result like:-

Transmit: 80 50 00 00 08    []
  11 22 33 44 55 66 77 88                            ."3DUfw.
Card answered: 61 1C

My java code is working good for other java card I have. Could anybody tell me what can be cause of this different behavior..

// full java code


     public static void main(String[] args) {
            // TODO code application logic here
            try
            {

        factory = TerminalFactory.getDefault();
                    terminals = factory.terminals().list(); 
                terminal = terminals.get(0);
                card = terminal.connect("*");
                    channel =card.getBasicChannel();

                    CommandAPDU cmdAPDU;
                     ResponseAPDU response;
                    byte[] select_isd = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,
                                         (byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 };
                    cmdAPDU = new CommandAPDU(select_isd);
                     response = channel.transmit(cmdAPDU);
                    byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,
                                          (byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };
                     cmdAPDU = new CommandAPDU(INIT_UPDATE);
                     response = channel.transmit(cmdAPDU);
 }
        catch( Exception ex)
        {

        }
    }

Other tool log is look like:-

Card opened
12 bytes ATR received:
3B 68 00 00 00 73 C8 40 00 00 90 00

Transmit: 00 A4 04 00 08    [SELECT FILE]
  A0 00 00 00 03 00 00 00                            ........
Card answered: 61 12

Transmit: 00 C0 00 00 12    [GET RESPONSE]
Card answered: 90 00
  6F 10 84 08 A0 00 00 00 03 00 00 00 A5 04 9F 65    o..............e
  01 FF                                              ..

Transmit: 80 50 00 00 08    []
  11 22 33 44 55 66 77 88                            ."3DUfw.
Card answered: 61 1C

But when i run my java code I am getting 6985 for INIT_UPDATE command.

Please let me know if require any other information for my side..

==newly added=== I tried to run my script in JCOP shell, my script is like:-

/mode trace=on
/terminal 
/atr
/send 80CAA08D05
/send 802E000014B555C94B0B2368B4840201808502032288020060
/send 80D8000000
/atr
/send 80500000081122334455667788

and it give me required result. Same i tried to implement in java , my new java code is look like:- =====New Updated JAVA Code===

factory = TerminalFactory.getDefault();
         terminals = factory.terminals().list(); 
         terminal = terminals.get(0);

         card = terminal.connect("*");
         channel =card.getBasicChannel();

         CommandAPDU cmdAPDU;
         ResponseAPDU response;
         byte[] x = { (byte) 0x80, (byte) 0xCA, (byte) 0xA0,(byte) 0x8D,(byte)0x05};
         byte[] y = {    remove command for security reasons};
         byte[] z = {     (byte) 0x80, (byte) 0xD8, (byte) 0x00, (byte) 0x00, (byte) 0x00}; // it set default key


           cmdAPDU = new CommandAPDU(x);
         response = channel.transmit(cmdAPDU);
                System.out.println(response.toString());

                  cmdAPDU = new CommandAPDU(y);
         response = channel.transmit(cmdAPDU);
                System.out.println(response.toString());

                           cmdAPDU = new CommandAPDU(z);
         response = channel.transmit(cmdAPDU);
                System.out.println(response.toString());

                   card.disconnect(true);
                    card = terminal.connect("*");
                   channel =card.getBasicChannel();


         byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };

         cmdAPDU = new CommandAPDU(INIT_UPDATE);
        response = channel.transmit(cmdAPDU);
Arjun
  • 3,491
  • 4
  • 25
  • 47
  • 2
    have you selected ISD before sending initialize update?Or send ATR before sending initialize update. – Anurag Sharma Apr 27 '15 at 07:43
  • Please add this part of your code, if possible. – Ebrahim Ghasemi Apr 27 '15 at 07:57
  • 611C means there are 0x1C = 28 bytes to read. You should respond to 61XX with GET RESPONSE command (00 C0 00 00 XX) to get your response data. – vojta Apr 27 '15 at 16:51
  • @anurag I tried to call ISD before Init-update, it was fine in other tool but in java code ISD is responding with 0x6112 but unit update still giving 0x6985.what is send atr? – Arjun Apr 28 '15 at 06:22
  • @Abraham code edited, please check. – Arjun Apr 28 '15 at 06:29
  • I think there is only two scenario! 1- Two reader connected to the computer and this two tools target two different card! 2- Your reader is both contact and contact-less and also your card is a Hybrid card (Dual-interface with two different chip inside). One interface is in Locked life cycle state and the other is not locked! Your program target one interface and the other tool target other interface!! :)) I know these are really rare situations! – Ebrahim Ghasemi Apr 28 '15 at 08:04
  • 1
    @abraham My card is dual interface card but my reader is contact only and i am testing my java code with contact scenario.... – Arjun Apr 28 '15 at 09:36
  • I would suggest that you show us more code and, in particular what other commdns you send in your code/are sent by that tool you are using. – Michael Roland Apr 29 '15 at 15:26
  • @MichaelRoland I updated the full code which I am using. Please check. – Arjun Apr 30 '15 at 09:32
  • @rohitamitpathak What `response` do you get for the `select_isd` command when executing **your code**? – Michael Roland May 01 '15 at 09:41
  • @MichaelRoland it is returning 9000 with other FCI data. – Arjun May 05 '15 at 07:07
  • @rohitamitpathak Just a wild guess, but you might want to try to add an additional (byte) 0x00 (i.e. an Le field) at the end of your INIT_UPDATE command. – Michael Roland May 05 '15 at 15:20
  • @MichaelRoland I tried it but result is same. – Arjun May 06 '15 at 05:26
  • @Abraham I fired some set of command from jcshell and implement same in java code you can check. JCshell gives good response while java code still giving me 6985 when INIT_UPDATE fire. Oh sorry I forget to remove this from jcshell script. Please remove it or make it xxxxxxx – Arjun May 08 '15 at 07:24
  • @rohitamitpathak I couldn't edit my comment, so I remove it. thanks for your response. – Ebrahim Ghasemi May 08 '15 at 08:17
  • @rohitamitpathak Do you mean that _New Updated JAVA Cod_ still doesn't work fine?!! – Ebrahim Ghasemi May 08 '15 at 08:19
  • yes i am still getting 0x6985 when sending command via java code, jcsh not giving 6985 – Arjun May 08 '15 at 12:10

5 Answers5

7

6985 means conditions of use not satisfied. As you didn't use any keys up till now it it probably means that the card is locked or terminated.


611C is an status word used for APDU's send over T=0. T=0 doesn't handle both command and response (aka "ISO case 4") in the same APDU, so a GET RESPONSE is required for ISO case 4 commands. Either the first application handles this out of sight (as Java Card itself does) - combining the two APDU's - or it creates a T=1 connection instead of a T=0 connection.

It has little to do with the 6985 status word because you would expect this warning to be produced before the business logic of the INITIALIZE UPDATE command is processed - the command is only processed if output can be produced.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Actually my card is not locked because it is giving 611C in other tool, you are right , javax.smartcard.io handle get response internally, so we don't need to worry about. I am worried why my java code returning 6985 with this card. – Arjun Apr 29 '15 at 05:32
  • @Maarten Bodewes: Sorry to disagree: 69 85 means **conditions of use not satisfied** while *security.conditions not satisfied* is represented by 69 82. – guidot Apr 29 '15 at 08:49
  • @guidit Thanks, substantially edited answer. There were quite a few things wrong with it but the gist of the answer stays the same. – Maarten Bodewes Apr 29 '15 at 09:49
  • @Maarten : Sorry to disagree : Initialized Update command never give 6985, if the Card is Terminated or Locked. Rather as per specification Mapping Guideline GP v2.1.1 on v2.2.1 under section 6.5.5 : If the Card is Terminated then a response of '6D00' is returned. And as per GP2.2.1 specification : Initialized Update command works with Card Life Cycle State (CLCS) Locked, because if you moved CLCS from Secure to Locked via Secure session (SCP02) and then moving CLCS back to Secured state (from Locked state) you need to establish secure session via InitUpdate and External Authenticate commands. – Bhanu May 05 '15 at 17:10
4
  1. For SW '6985'

As per the specification Mapping Guideline of Existing GP v2.1.1 Implementation on v2.2.1 : under section 6.5.2

" If a secure channel is currently active on a logical channel other than the logical channel on which this command (Initialize Update command) was issued, a response of '6985' is returned."

Kindly cross check with this behavior in the case when Initialize Update command fails with 6985.

  1. For SW '611C'

If the information is too long for a single response data field, then the card shall return the beginning of the information followed by SW1-SW2 set to '61XX'. Then a subsequent GET RESPONSE provides 'XX' bytes of information. The process may be repeated until the card sends SW1-SW2 set to '9000'.

Here in this case you need to send GET RESPONSE command with P3 as 1C and CARD will return 1C bytes of data.

Bhanu
  • 663
  • 5
  • 13
  • How we handle secure channel kind of things, we Just sending 80 50 00 00 08 11 22 33 44 55 66 77 88???? – Arjun May 06 '15 at 05:27
  • @Rohit : 80 50 00 00 08 11 22 33 44 55 66 77 88 is nothing but Initialized Update command which with the help of External Authenticate command is used to initiate Secure Session (SCP02 session). Initialized Update command can give 6985 because of some reasons, in which one of them I explained above i.e. if logical channels are supported and secure session is active on a security domain in one logical channel then if you try to initiate secure session (via sending Initialized Update command) on same security domain in other logical channel then Initialized Update command will give 6985. – Bhanu May 07 '15 at 19:47
  • Check whether secure session is currently active on same security domain (on which you are sending Initialized update command) in some other logical channel. Better close all other logical channel (if possible) via Mange channel command (see Global platform specification) and then check your scenario. – Bhanu May 07 '15 at 19:49
  • Some other reasons due to which Initialized Update command can give 6985 are : 1- If SCP02 key set is not present on security domain (on which Initialized Update command is issued). SCP02 key sets are from 20 to 2F. Kindly check this whether key set is present or not. 2- If Security domain (in which Initialized Update command is issued) do not has SCP capability (please refer UICC configuration specification for this, and see Tag '81' in SD installation parameter), kindly cross check the SCP capability also. – Bhanu May 07 '15 at 19:54
  • I found the cod is quite simple, getting basic channel and transmit INIT_update on same channel. I am sorry but what more you want me to do is not clear. For your information, I tried this with Jcop shell script, my script is like /mode trace=on /terminal /atr /send 80CAA08D05 /send 802E000014xxxxxxxxxx... /send 80D8000000 /atr #INITUPDATE /send 80500000081122334455667788 it is working fine and giving 61xx – Arjun May 08 '15 at 05:37
0

You can use the BusHound to catch some APDUs,then compare and analyse the differences between the two tools during sending commands.

andy007
  • 248
  • 1
  • 10
  • I tried but not find a place to send my command like :- 80 50 00 00 08 11 22 33 44 55 66 77 88 – Arjun Apr 29 '15 at 12:42
0

May I ask you to try this program also?

 public static void main(String[] args) {
     try{
         factory = TerminalFactory.getDefault();
         terminals = factory.terminals().list(); 
         terminal = terminals.get(0);

         card = terminal.connect("*");
         channel =card.getBasicChannel();

         CommandAPDU cmdAPDU1;
         CommandAPDU cmdAPDU2;
         ResponseAPDU response1;
         ResponseAPDU response2;

         byte[] select_isd = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 };
         byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };

         cmdAPDU1 = new CommandAPDU(select_isd);
         cmdAPDU2 = new CommandAPDU(INIT_UPDATE);
         response1 = channel.transmit(cmdAPDU1);
         response2 = channel.transmit(cmdAPDU2);
         }
     catch( Exception ex)
     {

     }
}

I'm afraid if the new CommandAPDU between transmit methods, reset the connection between the card and the reader.

Update:

If the above program return the same error, please try this one also :

public static void main(String[] args) {
     try{
         factory = TerminalFactory.getDefault();
         terminals = factory.terminals().list(); 
         terminal = terminals.get(0);

         card = terminal.connect("*");
         channel =card.getBasicChannel();

         CommandAPDU cmdAPDU;
         ResponseAPDU response;


         byte[] select_isd = {(byte) 0x00,(byte) 0xA4,(byte) 0x04,(byte) 0x00,(byte) 0x08,(byte) 0xA0,(byte) 0x00,(byte) 0x00,(byte) 0x00,(byte) 0x03,(byte) 0x00,(byte) 0x00,(byte) 0x00 };
         byte[] get_response={(byte)0x00,(byte)0xC0 ,(byte)0x00 ,(byte)0x00 ,(byte)0x12};
         byte[] INIT_UPDATE = {(byte) 0x80,(byte) 0x50,(byte) 0x00,(byte) 0x00,(byte) 0x08,(byte) 0x11,(byte) 0x22,(byte) 0x33,(byte) 0x44,(byte) 0x55,(byte) 0x66,(byte) 0x77,(byte) 0x88 };

         cmdAPDU = new CommandAPDU(select_isd);
         response = channel.transmit(cmdAPDU);

         cmdAPDU = new CommandAPDU(get_response);
         response = channel.transmit(cmdAPDU);

         cmdAPDU = new CommandAPDU(INIT_UPDATE);
         response = channel.transmit(cmdAPDU);

         }
     catch( Exception ex)
     {

     }
}

Eagerly waiting for your response.

Update-2:

I think trying a Python script is useful to find out what is the problem. Can you try this also:

>>> from smartcard.System import readers
>>> from smartcard.util import toHexString
>>>
>>> r=readers()
#if you have more than one reader or a dual interface reader, put the right index in the below line instead of `0`
>>> connection = r[0].createConnection()
>>> connection.connect()
>>>
>>> SELECT = [0xA0, 0xA4, 0x04, 0x00, 0x08 , 0xA0 , 0x00 , 0x00 , 0x00 , 0x03 , 0x00 , 0x00 , 0x00 ]
>>> GET_RESPONSE = [ 0x00, 0xC0, 0x00, 0x00, 0x12]
>>> INIT_UPDATE= [0x80, 0x50, 0x00, 0x00, 0x08, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]
>>>
>>> data, sw1, sw2 = connection.transmit( SELECT)
>>> print "%s %x %x" % (data, sw1, sw2)
>>>
#if the sw1 and sw2 of above command is not `0x6112`, don't send GET_RESPOSE command.
>>> data, sw1, sw2 = connection.transmit( GET_RESPONSE)
>>> print "%s %x %x" % (data, sw1, sw2)    
>>>
>>> data, sw1, sw2 = connection.transmit( INIT_UPDATE)
>>> print "%s %x %x" % (data, sw1, sw2)

Note that the above script is for Python 2.7 and you must istall PySCard also

Ebrahim Ghasemi
  • 5,850
  • 10
  • 52
  • 113
  • thanks for suggestion. but your first example returning ResponseAPDU: 20 bytes, SW=9000 ResponseAPDU: 2 bytes, SW=6985 and second example returning ResponseAPDU: 20 bytes, SW=9000 ResponseAPDU: 2 bytes, SW=6f00 ResponseAPDU: 2 bytes, SW=6985 – Arjun May 07 '15 at 04:49
  • It's totally strange behaviour. I dont know why it is happening. – Arjun May 07 '15 at 04:53
  • @rohitamitpathak May I ask you to try the Python script that I added to my asnwer in **Updae-2** section also? – Ebrahim Ghasemi May 07 '15 at 13:58
  • I tried this with Jcop shell script, my script is like /mode trace=on /terminal /atr /send 80CAA08D05 /send 802E000014xxxxxxxxxx... /send 80D8000000 /atr #INITUPDATE /send 80500000081122334455667788 it is working fine and giving 61xx – Arjun May 08 '15 at 05:39
0

The problem is that is mandatory an EXTERNAL UPDATE command immediately after of INITIAL UPDATE. If you receive a 61nn response and send the C0 command to retrieve the remainder data from INITIAL UPDATE, the EXTERNAL AUTH command fails indicating that an "access condition not satisfied" [6982]; then, you have al least two possible alternatives to fix this:

  1. Connect your Reader in T=1 protocol mode

lResult=SCardConnect( *pphContext, tszReaderName, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1,//<--FORCE TO SCARD_PROTOCOL_T1, pphCard, &dwActiveProtocol) )); //<--VERIFY THAT THIS VALUE IS SETTED TO 2 Adjust your engine APDU sender to use T1 protocol to receive the information on the response avoiding the use of the getResp command

{00 C0 00 00 nn}
  1. (I assumed that's OK, I'm still working in this) If you want to use T0 protocol, you must resend two times the INITIAL UPDATE command, the first time is for to obtain the data from the response using a C0 command. The second try will re-establish the secure channel lost to use the C0 Apdu command. Here, is possible that you need some mechanism to manage channel command to close additional channels (see https://globalplatform.org/wp-content/uploads/2018/06/GPC_Specification-2.2.1.pdf paragraph 11.7), because you could receive a 6985 as response and you smartcard appears unabled to execute INITIAL UPDATE with no error.
totem_motorist
  • 161
  • 1
  • 4