Showing posts with label SimCard. Show all posts
Showing posts with label SimCard. Show all posts

21 Oct 2012

JavaCard STK usage example: One Time Password


Today I'd like to show you one of the ways of JavaCard STK applet usage. In the world of information systems a good authentication procedure is one of the most important topics. And one of the most reliable ways to do it is two factor authentication usage. The most known two factor authentication is One Time Password (OTP).

OTP - is a password which is valid only for one authentication session. Password validity could be also limited in time. The advantage of One Time Password is inability to
use the same password twice. Hence if password is intercepted somehow it will be useless.

The aim of this post is not to give you all pros and cons of OTP. I'll let my reader dig it on his own :) Instead I want to show you how OTP could be implemented in JavaCard STK applet.

The main problem of OTP for end-users is inability to keep in mind all One Time Passwords therefore we need some additional device to generate it on the fly - JavaCard STK applet.

Let's have a look how we can do it. First of all we will implement 2 menu items for Init key and Get next password as:

/**
 * Constructor of the applet
 */
public otp() {
    // Get the reference of the applet ToolkitRegistry object
    reg = ToolkitRegistry.getEntry ();

    menuGetNextPasswd = new byte[] { (byte) 'G', (byte) 'e', (byte) 't',
            (byte) ' ', (byte) 'n', (byte) 'e', (byte) 'x', (byte) 't',
            (byte) ' ', (byte) 'p', (byte) 'a', (byte) 's', (byte) 's',
            (byte) 'w', (byte) 'o', (byte) 'r', (byte) 'd' };
    menuInitKey = new byte[] { (byte) 'I', (byte) 'n', (byte) 'i',
            (byte) 't', (byte) ' ', (byte) 'k', (byte) 'e', (byte) 'y' };
    // Define the applet Menu Entry
    idMenuGetNextPasswd = reg
            .initMenuEntry (menuGetNextPasswd, (short) 0,
                            (short) menuGetNextPasswd.length,
                            PRO_CMD_SELECT_ITEM, false, (byte) 0, (short) 0);
    idMenuInitKey = reg
            .initMenuEntry (menuInitKey, (short) 0,
                            (short) menuInitKey.length, (byte) 0, false,
                            (byte) 0, (short) 0);

    // during instantiation of the applet key isn't initialized yet
    isKeyInitialized = false;
    // fixing key length to 20 bytes
    key = new byte[KEY_LENGTH];

    tmpBuf = new byte[KEY_LENGTH_ASCII];
}

Then we have to implement processToolkit() method to treat menu items selections:


public void processToolkit(byte event) {
    EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler ();

    // Manage the request following the MENU SELECTION event type
    if (event == EVENT_MENU_SELECTION) {
        // Get the selected item
        byte selectedItemId = envHdlr.getItemIdentifier ();

        // Perform the required service following the menuGetNextPasswd
        // selected item
        if (selectedItemId == idMenuGetNextPasswd) {
            getNextPasswd ();
        }

        // Perform the required service following the menuInitKey selected
        // item
        if (selectedItemId == idMenuInitKey) {
            initKey ();
        }
    }
}

The initKey() method will request initial key which will be used for next password calculation. The method getNextPasswd() could be implemented in the following way:


/**
 * Manage the menuGetNextPasswd selection
 */
private void getNextPasswd() {
    if (isKeyInitialized) {
        try {
            hash = MessageDigest.getInstance (MessageDigest.ALG_SHA, true);
            hash.doFinal (key, (short) 0, (short) key.length
                         , tmpBuf, (short) 0);
            Util.arrayCopyNonAtomic (tmpBuf, (short) 0, key, (short) 0,
                                     (short) key.length);
            displayHexBuffer (key, (short) key.length);
        } catch (CryptoException e) {
        }
    } else {
        displayText(msgKeyNotInited);
    }
    return;
}

After password generation we need to verify it somehow on the server side. Let's implement authentication server simulator. I'll show you only proof-of-concept implementation, a simple GUI application wich requires password and verifies it. It looks like this:



I've used Clojure for it:


(def md (MessageDigest/getInstance "SHA-1"))

(defn ascii2hex [ascii-str]
  (map #(Integer/parseInt % 16) (map #(apply str %) (partition 2 ascii-str))))

(defn bytes2hexStr [bytes]
  (apply str
         (map #(.toUpperCase %)
              (map #(format "%02x" %)
                   (map #(bit-and 0xFF %) (seq bytes))))))

(defn get-next-password [key-str]
  (. md reset)
  (bytes2hexStr
   (seq
    (. md digest
       (into-array Byte/TYPE
                   (map #(.byteValue %)
                        (ascii2hex key-str)))))))

The full source code of the applet and authentication server simulator could be found on my GitHub page.

Peace on you! :)


14 Sept 2012

MIFARE password calculator (Clojure edition)

Wow! I didn't updated my blog almost a year already. I have to fix it. :)
After switched to Macbook at home I decided to review my development tools and also programming languages. As an exercise I redeveloped my MIFARE password calculator in Clojure. Now you don't need dotNET framework to run it. Just download standalone version of JAR file and run it as:
java -jar <jarfilename>
I hope it will be more useful.
You can download it from GitHub.
New posts on different topics are coming soon. Stay tuned! ;)

Update: Add links to previous posts on the same topic:

22 Apr 2011

Unusual usage of exceptions in JavaCard development (Updated)

If you are reading this blog most probably you already know that development of JavaCard applets has own specificities. Sometimes we need to save few bytes to fit applet to card memory and speed of applet is always important. In this post I’d like to show you unusual usage of exceptions to optimize speed and size of the applet.
Let’s imagine you need to read transparent file on the card but you don’t know its size in advance. Usual practice is analyzing response to select and extracting size information. In our test case we have to read PLMNSel file which contains Mobile Network Code and Mobile Country Code. Each PLMN information length is 3 bytes. Afterwards we can do something with this information but I skip it to show you the main idea. Let's have a look to the code:

package testappletwithbuffer;

import sim.access.*;
import javacard.framework.*;

public class TestAppletWithBuffer extends javacard.framework.Applet {
    
    private SIMView gsmFile;
    private byte[] plmn;
    private byte[] response;
    
    protected TestAppletWithBuffer() {
        gsmFile = SIMSystem.getTheSIMView ();
        plmn = new byte[3];
        response = new byte[15];
    }

    public static void install(byte[] bArray, short bOffset, byte bLength){
        TestAppletWithBuffer refApplet = new TestAppletWithBuffer();
        refApplet.register(bArray, (short) (bOffset + 1), (byte) bArray[bOffset]);
        refApplet.readPLMNSel();
    }

    public void process(APDU apdu) throws ISOException {
          // ignore the applet select command dispatched to the process
        if (selectingApplet()) {
            return;
        }
    }
    
    public void readPLMNSel() {
        gsmFile.select ((short) SIMView.FID_DF_GSM);
        gsmFile.select ((short) SIMView.FID_EF_PLMNSEL
                        , response
                        , (short) 0
                        , (short) response.length);
        short fileOffset = 0;
        short fileLength = Util.makeShort(response[2], response[3]);
        
        // reads the PLMN information to plmn buffer
        for (fileOffset = 0; fileOffset < fileLength; fileOffset += plmn.length) {
            gsmFile.readBinary (fileOffset
                                , plmn
                                , (short) 0
                                , (short) plmn.length);
        }

    }
}

Let me show you how we can optimize this applet:

package testappletwithexception;

import sim.access.*;
import javacard.framework.*;

public class TestAppletWithException extends javacard.framework.Applet {

    private SIMView gsmFile;
    private byte[] plmn;

    public TestAppletWithException() {
        gsmFile = SIMSystem.getTheSIMView();
        plmn = new byte[3];
    }

    public static void install(byte[] bArray, short bOffset, byte bLength) {
        TestAppletWithException refApplet = new TestAppletWithException();
        refApplet.register(bArray, (short) (bOffset + 1), (byte) bArray[bOffset]);
        refApplet.readPLMNSel();
    }

    public void process(APDU apdu) {
        // ignore the applet select command dispatched to the process
        if (selectingApplet()) {
            return;
        }
    }
    
    public void readPLMNSel() {
        short fileOffset = 0;
        gsmFile.select ((short) SIMView.FID_DF_GSM);
        gsmFile.select ((short) SIMView.FID_EF_PLMNSEL);
        
        try {
            // reads the PLMN information to plmn buffer
            for (fileOffset = 0; fileOffset < (short) 0xFFFF; fileOffset += plmn.length) {
                gsmFile.readBinary(fileOffset
                                   , plmn
                                   , (short) 0
                                   , (short) plmn.length);   
            }
        } catch (SIMViewException e) {
            // normal case
        }
    }
}

Such kind of usage of exception could be weird to regular Java developers. But compare generated bytecodes:

Applet with exception Applet with buffer
.method public readPLMNSel()V 8 {
    .stack 5;
    .locals 1;

    L0:  sconst_0;
         sstore_1;
         getfield_a_this 0;  // ref gsmFile
      sspush 32544;
         invokeinterface 2 10 7; // SIMView
         getfield_a_this 0;  // ref gsmFile
         sspush 28464;
         invokeinterface 2 10 7; // SIMView
    L1:  sconst_0;
         sstore_1;
         goto L3;
    L2:  getfield_a_this 0; // ref gsmFile
         sload_1;
         getfield_a_this 1; // ref plmn
         sconst_0;
         getfield_a_this 1; // ref plmn
         arraylength;
         invokeinterface 5 10 9; // SIMView
         pop;
         sload_1;
         getfield_a_this 1; // ref plmn
         arraylength;
         sadd;
         sstore_1;
    L3:  sload_1;
         sconst_m1;
         if_scmplt L2;
    L4:  goto L6;
    L5:  pop;
    L6:  return;
    .exceptionTable {
         // start_block end_block
         // handler_block catch_type_index
         L1 L4 L5 9;
    }
}
.method public readPLMNSel()V 8 {
    .stack 5;
    .locals 2;

    L0:  getfield_a_this 0;  // ref gsmFile
         sspush 32544;
         invokeinterface 2 10 7; // SIMView
         getfield_a_this 0;  // ref gsmFile
         sspush 28464;
         getfield_a_this 2;  // ref response
         sconst_0;
         getfield_a_this 2;  // ref response
         arraylength;
         invokeinterface 5 10 6; // SIMView
         pop;
         sconst_0;
         sstore_1;
         getfield_a_this 2;  // ref response
         sconst_2;
         baload;
         getfield_a_this 2;  // ref response
         sconst_3;
         baload;
         invokestatic 11;  // makeShort
         sstore_2;
         sconst_0;
         sstore_1;
         goto L2;
    L1:  getfield_a_this 0;  // ref gsmFile
         sload_1;
         getfield_a_this 1;  // ref plmn
         sconst_0;
         getfield_a_this 1;  // ref plmn
         arraylength;
         invokeinterface 5 10 9; // SIMView
         pop;
         sload_1;
         getfield_a_this 1;  // ref plmn
         arraylength;
         sadd;
         sstore_1;
    L2:  sload_1;
         sload_2;
         if_scmplt L1;
    L3:  return;
}

As you can see exception bytecode shorter and (here you have to trust me :)) it will work faster.

In given example bytecode size isn’t noticeably less but if you have more complex logic of verification it could make sense. If you compile to above two applets and compare size of IJC files it will be 339 and 363 bytes accordingly. So you will save 24 bytes and will win a little on speed.

Update:
After publishing post I figured out how to more optimize the version with exception. Actually we don't need to check anything at all and if we will replace for loop with while like below we will win even more on the size and speed:

while(true) {
    gsmFile.readBinary(fileOffset
                       , plmn
                       , (short) 0
                       , (short) plmn.length);
    fileOffset += plmn.length;
}

And bytecode in this case will be very short:

.method public readPLMNSel()V 8 {
    .stack 5;
    .locals 1;

    L0:  sconst_0;
         sstore_1;
         getfield_a_this 0;  // ref gsmFile
         sspush 32544;
         invokeinterface 2 10 7;  // sim/access/SIMView
         getfield_a_this 0;       // ref gsmFile
         sspush 28464;
         invokeinterface 2 10 7;  // sim/access/SIMView
    L1:  getfield_a_this 0;       // ref gsmFile
         sload_1;
         getfield_a_this 1;       // ref plmn
         sconst_0;
         getfield_a_this 1;       // ref plmn
         arraylength;
         invokeinterface 5 10 9;  // sim/access/SIMView
         pop;
         sload_1;
         getfield_a_this 1;       // ref plmn
         arraylength;
         sadd;
         sstore_1;
         goto L1;
    L2:  pop;
         return;
    .exceptionTable {
        // start_block end_block handler_block catch_type_index
        L1 L2 L2 9;
    }
}
So there is no limit for perfection :)
Update 2:
I've decided do not leave you with the statement "just trust me" concerning the speed. Let me explain why it is faster:
  • There is no implicit garbage collection on JavaCard. You have to call it explicitly hence no need to unwind stack during exception
  • Exceptions are not fully object as in terms of "big" Java. Usually it is just error code from native layer
As matter of fact usage of exceptions is cheap in JavaCard

5 Apr 2011

What is Smart Card Web Server (SCWS)?

Smart Card Web Server is web server application which works in the SIM Card. It allows HTTP/1.0 and HTTP/1.1 connection between mobile phone and SIM card. It could enrich visualizations of content by using xHTML, javascript and flash animations.
As any web server SCWS is not only performing static content but also capable to serve dynamic content using SCWS servlets. Let's have a look to generic architecture of SCWS:



All parts of SCWS at the present time have been standardized by Open Mobile Alliance (OMA) and ETSI:

Smart Card Web Server:
  • OMA-TS-Smartcard_Web_Server-V1_1-20090512-A
  • Covers the technical specificities of a HTTP server in a SIM card plus the new Remote Management architecture and protocol
  • 1.1 Approved by OMA in 2008
BIP TCP Server:
  • Standardised bearer (TS 102 223 Rel-7) for ISO (APDU) interface minor modification to BIP/TCP Client (Rel-99)
USB-IC ("IP in UICC"):
  • High speed interface (HSI) based on USB: TS 102 600
  • Direct TCP/IP connectivity, locally or remotely: TS 102 483, on top of USB
SCWS Servlet API:
  • TS 102 588 Rel-7
SCWS supports Basic Authentication by default. SCWS Servlet API allows developing any type of application. Some examples:
  • Home screen personalization based on operator design
  • Blogging application which could work even offline and upload posts when it will be online
  • Operator portal which will replace ancient STK menu application
  • etc

8 Mar 2011

Utility for calculation MIFARE Password

The ones who read my post about how to calculate MIFARE password found it very tough to calculate manually. Hence I've developed tool to automate it. The full source codes are available in github. If you don't care about source code, executable file is also there. You need .Net 4.0 and F# runtime to run it.

14 Jan 2011

Advanced JavaCard debugging. (The story of one debug)

Sometimes ago I've written the post about JavaCard applets debugging techniques. In the current post I'd like to narrate story from real life. Actually this post is translation of post in my Russian blog.
Well, the problem which I've encountered was the SIM Toolkit (STK) applet with a couple of menu entries. On the real card when you select one of menu entry applet silently exits instead of sending SMS. Checking source code of the applet was not helped. So the only way to debug was loading applet to Software Simulator.
Ok, if no other way, I've compiled the most similar configuration of simulator to real card, created file system, loaded applet. I’ve connected Mobile Phone Simulator to OS Simulator and start browsing menu. When I’ve selected menu item which doesn’t work JCRE log has the following:
// Byte code dump, some part has skipped
CAP[1] - 0x4aac11: SAND
CAP[1] - 0x4aac12: SADD
CAP[1] - 0x4aac13: S2B
CAP[1] - 0x4aac14: BASTORE
CAP[1] - 0x4aac15: ALOAD_0
CAP[1] - 0x4aac16: SCONST_5
CAP[1] - 0x4aac17: SCONST_0
CAP[1] - 0x4aac18: INVOKESTATIC [0x1c 0x24]
LIB[7] - 0x4987eb: SCONST_5
LIB[7] - 0x4987ec: SLOAD_0
LIB[7] - 0x4987ed: INVOKESTATIC [0x1c 0x17]
Calling nativeMethod[51] - javacard/security/CryptoException/algorithmCheck(BS)V
0x498802: RETURN - returns: V0x0
LIB[7] - 0x4987f0: NEW [0x1c 0x18]
total number of effective EEPROM writing = 0xbc
total number of requested atomic update = 0x1e6
number EEPROM writing saved thanks NVL = 0x4f6
Exception: VM; SystemException; reason: 5
< INVALID exceptions java.lang for >INTP Exception jump to dispatch loop
total number of effective EEPROM writing = 0xbc
total number of requested atomic update = 0x1e6
number EEPROM writing saved thanks NVL = 0x4f6
By checking the source code of JCRE of the OS I’ve found that “reason 5” is No Resources. Checking available volatile and non volatile memory, it seems there is enough memory. From the dump I couldn’t figure out what was wrong. So no clue!
Next step to analyze applet bytecode. Fortunately Gemalto Developer Suite has utility called “Cap File Utility”. I dumped applet and searched the exact consequence of commands from dump of JCRE. After a while I found in the applet dump the following:
method_info[8] // @04b4= {
    // Some part skipped
    /*0f31*/ sand
    /*0f32*/ sadd
    /*0f33*/ s2b
    /*0f34*/ bastore
    /*0f35*/ L124: aload_0
    /*0f36*/ sconst_5
    /*0f37*/ sconst_0
    /*0f38*/ invokestatic 57
    /*0f3b*/ putfield_a 26
    /*0f3d*/ getfield_a_this 26
    /*0f3f*/ getfield_a_this 23
    /*0f41*/ sload 10
}

Pay attention to /*0f38*/ invokestatic 57. It is last call from the applet before switching to system libraries. So, it has to be something wrong with this call. But how to find what exactly it is calling. Here we have to check Component_Pool from the dump:
.Constant_Pool {
    // some part skipped
    /* 00e4, 57 */CONSTANT_StaticMethodRef : external: 0x84,0x1,0x0
    // some part skipped
}
So here it is – static method 57. It is referencing to external package. By checking ImportComponent I’ve found the right one. Here I have to mention that 0x84,0x1,0x00 means:
  • 0x84 – is 5th package in ImportComponent section due to numbering starts from 0x80
  • 0x1 – is the class number
  • 0x0 is method number
Here extract from applet dump:
.ImportComponent = {
    // some part skipped, it is 5th package due to 1st one has reference 0x80
    package_info = {
        minor_version : 2
        major_version : 1
        AID_length : 7
        AID : a0.00.00.00.62.02.01
    }
    // some part skipped }
Now we know what is AID of the imported package: a0.00.00.00.62.02.01. It is standard package javacardx.security. To figure out what is class 1 and method 0 we have to dump javacrdx.security.exp file. Below is extract from dump:
class_info { // javacardx/crypto/Cipher
    u1 token : 1 <== Class identification number
    u2 access_flags : 10000000001b
    u2 name_index : 57
    u2 export_supers_count : 1
    // some parts skipped
    export_methods {
        method_info { // getInstance
            u1 token : 0 <== Method identification number
            u2 access_flags : 11001b
            u2 name_index : 42
            u2 descriptor_index : 43
        }
    // some parts skipped
}
So now we know which method raises exception. It is getInstance() method of Cipher class. In the source code of the applet getInstance() method has called as follows:


myCipher = Cipher.getInstance( Cipher.ALG_DES_ECB_NOPAD, false );


According to specification JavaCard API:
getInstance
public static final Cipher getInstance(byte algorithm,
boolean externalAccess)
throws CryptoException
Creates a Cipher object instance of the selected algorithm.
Parameters:
algorithm - the desired Cipher algorithm. Valid codes listed in ALG_ .. constants above, for example, ALG_DES_CBC_NOPAD.
externalAccess - true indicates that the instance will be shared among multiple applet instances and that the Cipher instance will also be accessed (via a Shareable interface) when the owner of the Cipher instance is not the currently selected applet. If true the implementation must not allocate CLEAR_ON_DESELECT transient space for internal data.
Returns:
the Cipher object instance of the requested algorithm
Throws:
CryptoException - with the following reason codes:
  • CryptoException.NO_SUCH_ALGORITHM if the requested algorithm is not supported or shared access mode is not supported.

Et Voila! Issue is in externalAccess. We have to set it true, as STK applets are not explicitly selected applets by SELECT APPLICATION. They are triggered by SIM Toolkit Events.
So, changing to true externalAccess parameter has solved issue.

10 Dec 2010

How to access to MIFARE memory

To be able to read/write to/from MIFARE memory there is javacardx.external package specified in JavaCard 2.2.2 standard.
It specifies MemoryAccess interface and Memory class.
First we have to get object of MemoryAccess object like:

oMemAccess = Memory.getMemoryAccessInstance(Memory.MEMORY_TYPE_MIFARE
                                          , null
                                          , (short)0);


Memory.getMemoryAccessInstance() method has the following parameters:
  • memoryType - the desired external memory subsystem. Could be MEMORY_TYPE_MIFARE or MEMORY_TYPE_EXTENDED_STORE.
  • memorySize - the array containing the desired size in bytes, if applicable, in the external memory subsystem. This parameter is ignored for MIFARE memory type.
  • memorySizeOffset - the offset within the memorySize array where the 32 bit memory size number in bytes is specified. This parameter is ignored.
As you can see from above parameters list we need only specify memory type to get access MIFARE memory.
Then to write data to we can use MemoryAccess.writeData() method like:

oMemAccess.writeData(
             dataToWrite                     // the source data byte array
           , (short) 0                       // the byte offset in data buffer
           , (short) dataToWrite.length      // the length of data
           , thisCardPwdArray                // the byte array containing the 
                                             // key (password)
           , (short)0                        // the byte offset into the key 
                                             // array where the key data begins
           , (short) thisCardPwdArray.length // the length in bytes of key
           , (short) (blocknum / 4)          // sector number
           , blocknum)                       // block number

I'd like to mention one point about sector and block numbers. There are 2 type of addressing mode:

  • Absolute mode where block number accepts values 0..63 and sector number will be ignored.
  • Relative mode where block number accepts values 0..4 and sector number must be correctly set according to MIFARE memory layout.
To read data there is the method MemoryAccess.readData():


oMemAccess.readData(
               readBuf                         // destination buffer
             , (short) 0                       // offset in destination buffer
             , thisCardPwdArray                // key (password) array
             , (short)0                        // offset in key array
             , (short) thisCardPwdArray.length // key length
             , (short)secnum                   // sector number
             , (short)blocknum                 // block number
             , DATA_LEN)                       // number of bytes to read


All parameters have the same meaning as in writeData() method.


One additional remark: if the password to access MIFARE memory is incorrect there is no retry mechanism. You have to start from the beginning. The reason why it has implemented like that is absence of key counter like in PIN key.

3 Dec 2010

Usage of dynamic/diversified data during applet installation

In this post I'd like to talk a little about usage of dynamic/diversified data in install() method of JavaCard applet.

But first let me explain what is dynamic/diversified data is. It is pretty simple. If you are reading some file during applet installation and this file content is different from one card to another you are using dynamic data. As an example of such kind of data could be ICCID or IMSI of the card. The diversified data is the kind of data in the file where you have some master key and for each card you have some generation mechanism which will guarantee uniqueness of each card.

Okay, I do hope it is clear what is dynamic/diversified data is. Now back to the subject of this post. The main message of it is:

 Do not use any dynamic/diversified data during your applet installation! 


Now let me explain why. Most of the (if not all) SmartCard manufacturers are not using regular APDU commands to personalize each card as it is time consuming. Just imagine how much time it will take to produce card by creation of each file with CREATE FILE APDU and then to update its content by UPDATE BINARY/UPDATE RECORD APDU commands if your speed limited with PPS. As each command involves SmartCard Operating System to treat it, to verify all security conditions, to perform required operation. When you have to produce millions of cards per day it is unacceptable. This is why the card production process was splitted to 2 stages:
  • Master card creation 
  • Daughter card creation 
What each stage means.
Master card was created only once for each type of the SmartCard profile and for its creation regular APDU commands were used. Afterwards by special mechanism all dynamic parts which are specific for each card were determined and separated from static part and card memory dumped.

Then for daughter card creation (these is actually cards which will be produced in larges amount) this memory dump is used i.e. instead of sending each APDU command one by one and pushing OS to treat them, production writes directly to card memory. And then the small part which is unique for the each card will be  personalized by regular APDU. That is much faster.

And if you use dynamic data during applet installation it will force your applet installation command to move to dynamic part which is slowing down production process. Moreover it is quite difficult to recognize if your applet is really using dynamic data. If it is just reads it to store inside the applet, the automatic mechanism of detection may not trigger, because memory will be the same. It means if by automatic mechanism your applet is considered as static, your applet will get incorrect data as static part is located before dynamic part.

So, what is the solution if you really need to use dynamic data? Implement it other way round:
  • Post process personalization of the applet by special commands 
  • Get necessary information in runtime 
  • etc. 
Which way is right depends on your applet design and functionality.

22 Nov 2010

How mobile phone and SIM card setup connection or why sometime mobile phone rejects SIM Card?

A little bit theory
First of all SIM Card is particular application of SmartCard usage hence low level part specified by series of ISO7816 standards. ISO7816-3 standard specifies the following procedure to initiate interaction between card and Interface Device:
  1. Cold Reset (RST)
  2. SIM Card answers ATR (Answer-to-Reset)
  3. PPS negotiation
  4. Data exchange
Let's review each point one by one:
Cold Reset
Cold Reset is sending electrical reset signal to contact C2:

Above picture is showing SIM Card with USB interface which specifies additional contacts like C4, C8, C6 which are not part of ISO standard.
Answer-to-Reset (ATR)
To reset signal SIM card answers sequence of bytes and it’s structure is the following:

The aim of the ATR is declaring to the mobile phone card capabilities.The connection parameters supported by card has been specified in TA1:
TA1 encodes the indicated value of the clock rate conversion integer (Fi), the indicated value of the baud rate adjustment integer (Di) and the maximum value of the frequency supported by the card (f(max.)).
PPS negotiation
For exchanging information, the card and the handset shall agree on transmission protocol and values of transmission parameters. This process called PPS (Protocol and Parameters Selection) negotiation. After that all information exchange has to follow agreed parameters.
All these parameters based on the nominal duration of one moment of the electrical circuit I/O is named “elementary time unit” and denoted etu:


The delay between the leading edges of two consecutive characters shall be at least 12 etu, i.e. the duration of one character, (10±0,2) etu, followed by a guardtime (GT).
The following figure describes it graphically:


Let’s take an example of ATR : 3B9E96801FC78031E073FE211B66D0007A008000FA
Here TA1 byte is 96. Below the trace taken using ContactLAB tracer between mobile phone and SIM Card:
PPS2
As you can see as the result of PPS negotiation mobile phone and card have agreed to the value 96 and frequency is f = 3.84 MHz.
Based on these values we can determine F and D values from the tables provided in ISO7816-3 standard:
Table 7 — Fi and f (max.)
Bits 8 to 5 0000 0001 0010 0011 0100 0101 0110 0111
Fi 372 372 558 744 1116 1488 1860 RFU
f (max.) MHz 4 5 6 8 12 16 20 -

Bits 8 to 5 1000 1001 1010 1011 1100 1101 1110 1111
Fi RFU 512 768 1024 1536 2048 RFU RFU
f (max.) MHz - 5 7,5 10 15 20 - -
Table 8 — Di
Bits 4 to 1 0000 0001 0010 0011 0100 0101 0110 0111
Di RFU 1 2 4 8 16 32 64
Bits 4 to 1 1000 1001 1010 1011 1100 1101 1110 1111
Di 12 20 RFU RFU RFU RFU RFU RFU
As our PPS is 96 we have to split it to MSB and LSB:
  • 9 = b1001 –> Fi = 512 (from the Table 7)
  • 6 = b0110 –> Di = 32 (from the Table 8)
Based on above information we can calculate etu for our case:
image
The minimum delay between two characters has to be 12 etu i.e.:
image
Mobile phone rejects SIM Card
Time to time you have messages like “Insert SIM Card” or “SIM Card failures” even in case of SIM Card is working on another handset. After we knows the theory we can analyze the reasons. Of course it requires some tracer equipment which is able to show precise timing of signals. Personally I am using Micropross or ContactLAB tracers depending on which one is available in my team right now. :)
The principle is pretty easy. You have to check timings of signals in two directions: Mobile phone –> SIM Card and SIM Card –> Mobile phone.
Let’s take an example:
Mobile phone –> SIM Card
Below the trace for APDU in direction Mobile phone –> SIM Card:
Mobile-Card
As you remember “The delay between the leading edges of two consecutive characters shall be at least 12 etu”. In our case 12 etu is 50.04 µS. Now pay attention to the time between 2 cursors (red and blue one). It is 55.150 µS i.e. everything is working well.
You can analyze the response of the card in the same manner and check time. If it is less than 12 etu it means issue on card side which is not respecting ISO standard and vice versa if timing is wrong from mobile phone to the SIM Card issue is in mobile phone.
Et Voila!