user1740595
user1740595

Reputation: 61

ISO 7816 APDU for Smart Card using javax.smartcardio

I've already used javax.smartcardio to read serial number from smart card without much effort. However now I'm assigned to create MF on blank card (without which serial number can't be read).I'm creating APDU command for that as per ISO 7816 guidelines,but unable to create proper APDU command because my hex values are getting converted to wrong bytes.

import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import javax.smartcardio.TerminalFactory;

class SmartCardAPIs {

    public int Create_MF() throws CardException{

        //--Variable declaration
        int result=0;
        Card card=null;     
        byte[] responseData=null;
        ResponseAPDU answer=null;
        String SW1=null;
        String SW2=null;
        int cla,  ins,  p1,  p2;
        byte[] data=null;
        //---------------------------------------------

        //--1--Establish connection with the smart card
        TerminalFactory factory = TerminalFactory.getDefault();
        List<CardTerminal> terminals = factory.terminals().list();
        // Use the first terminal
        CardTerminal terminal = terminals.get(0);
        // Connect with the card
        card = terminal.connect("*");
        CardChannel channel = card.getBasicChannel();           
        //---------------------------------------------

        //--2--Create MF 
        cla=0x00;
        ins=0xE0;
        p1=0x00;
        p2=0x00;
        data = new byte[] {
            (byte) 0x21,
            (byte) 0x62,
            (byte) 0x1F,
            (byte) 0x82, // **** Getting converted to -126 ****
            --
            --
            --
        };          
        answer = channel.transmit(new CommandAPDU(cla,  ins,  p1,  p2, data));
        responseData= answer.getBytes();

        if(responseData!=null)
        {
            if(responseData.length==2)
            {
                SW1=String.format("%02X ", (responseData[0])).trim();
                SW2=String.format("%02X ", (responseData[1])).trim();
            }
        }       
    }
}

I've 2 problems

1: data in command APDU is taking a byte which is wrong(marked as *).

2: SW1 and SW2 are returning as 6A 80 which means parameter in data field are incorrect(I guess because of negative value while casting int in hex format to byte,but can not help much as I'm forced to do it).

The partial APDU command which I've placed here is part of full command which I've been supplied ,and the command is 100% OK and tested as I've been successful in creating MF in blank card using smart card tools with the command.I want to do the same in java now.

I assume that problem lies with the way this APDU is being getting created,may be negative value problem(I'm not very expert with java APDU stuffs although I 've created Applet to read serial number from card).

Upvotes: 1

Views: 5970

Answers (3)

Maryadi Poipo
Maryadi Poipo

Reputation: 1478

I have tried this command :

..

..

private static final byte[] Select_App = {(byte)0x00,(byte)0xA4,(byte)0x04,(byte)0x00,(byte)0x04,(byte)0x50,(byte)0x54,(byte)0x4B,(byte)0x65};

.. ..

and they worked fine, I got the right respons from the card. But I tried that command on android. So I think that byte casting is right we don't need to convert anything

Well, about java.smartcardio.*; I have the same problem with you, I can't send any command using that librari. But someone said that I have to use some java wrapper to send some commands. Umm... I'm still working on it btw... :-)

Upvotes: 0

Mayur Laniya
Mayur Laniya

Reputation: 49

You need to convert byte to hex properly by following Methods.

Integer class = StringUtil.parseHex("your class as string");

Class StringUtil


public class StringUtil {
public static Integer parseHex(String iStr) {
    int mask = 255;
    if (iStr.length() > 2)
        mask = 65535;
    try {
        return Integer.valueOf(Integer.parseInt(iStr, 16) & mask);
    } catch (Exception ex) {
    }
    return null;
}

Upvotes: -1

guidot
guidot

Reputation: 5333

Since you say, you have a working command at hand and surely double-checked its java representation: how sure are you, that the command did not execute successfully in a preceeding attempt? (Obviously only one MF is allowed.) Problem is, that the reported error code contradicts the "correct APDU known" assumption and this is the only resolution I can think of. The java code looks correct, as far as it is given.

Other idea: The command data field of an ISO Create File should start with something like 0x6X for FCI. Possibly your 0x21 is the length of the whole template (supposed to be sent as LC), which java constructs itself from the length of the byte array, so try leaving it out. The fact, that the 3rd byte is 0x1F, meaning 0x21 minus tag and length, supports that hypothesis.

Upvotes: 2

Related Questions