Using APDUs

You can connect to an applet on the UICC Security Element (SE) to exchange Application Protocol Data Units (APDUs). There are two ways to do this.

The resources acquired through these methods are system resources. You must release them when you close your application.

Connect to UICC SE to exchange APDUs

Using this method, you do not need to explicitly open a session to the reader in order to create a connection.

  1. Call nfc_se_open_logical_channel_direct() to open a connection to the applet. A session is created if one is not already available.
  2. Call nfc_se_channel_transmit_apdu() to send APDU data.
  3. Call nfc_se_channel_get_transmit_data() to retrieve the response data from the call above.
  4. Repeat the previous two steps as required.
  5. Call nfc_se_channel_close_channel() to close the channel.
  6. Call nfc_se_channel_close_session() to close the session.

The following sample code illustrates the steps above.

Not applicable

Not applicable

nfc_channel_type_t channelType = NFC_CHANNEL_TYPE_SE_UICC;
            
uint8_t aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x63, 0x50, 
                  0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 };
uint32_t aid_len = sizeof(aid);
uint8_t select_file_apdu[] = { 0x00, 0xA4, 0x00, 0x0C, 0x02, 0x50, 0x31 };
uint32_t apdu_len = sizeof(select_file_apdu);
uint8_t* result;
            
fcp_type_t fcpResponseType = OPEN_NO_FCP_INFO;
uint32_t hSEChannel;
uint32_t hSESession;
int32_t responseLen;
uint32_t exchangeResponseLen;
uint32_t nReceiveAPDUBufferSize;
uint32_t i; // loop variable
            
if( NFC_RESULT_SUCCESS != 
        nfc_se_open_logical_channel_direct(channelType, 
                                           aid, 
                                           aid_len, 
                                           fcpResponseType, 
                                           &hSESession,
                                           &hSEChannel, 
                                           &responseLen)) {
    // Handle error as we were not able 
    // to open the connection
    ...
    
}
         
if (NFC_RESULT_SUCCESS != 
        nfc_se_channel_transmit_apdu(hSEChannel, 
                                     select_file_apdu, 
                                     apdu_len, 
                                     &exchangeResponseLen)) {
    // Handle error
    ...
    
}
            
nReceiveAPDUBufferSize = exchangeResponseLen;
result = (uint8_t*) malloc(sizeof(uint8_t) * 
                           exchangeResponseLen);
if (NFC_RESULT_SUCCESS == 
        nfc_se_channel_get_transmit_data(hSEChannel, 
                                 &result[0], 
                                 &nReceiveAPDUBufferSize)) {
    //Print the response
    for (i = 0; i < nReceiveAPDUBufferSize - 1; i++) {
        printf("0x%.2x, ", result[i]);
    }
    printf("0x%.2x }\n", result[nReceiveAPDUBufferSize - 1]);
}
// Free up the memory allocated
free(result);
            
// Close the channel
if (NFC_RESULT_SUCCESS != 
        nfc_se_channel_close_channel(hSEChannel)) {
    // Handle error
    ...
    
}
    
// Close the session  
if (NFC_RESULT_SUCCESS != 
        nfc_se_session_close_session(hSESession)) {
    // Handle error
    ...
    
}

Connect to UICC SE by explicitly opening a session

Alternatively, you can connect to an applet on the UICC SE by explicitly opening a session to the reader and creating a connection using that session.

  1. Retrieve a session for the SE using the following steps:
    1. Call nfc_se_service_get_num_readers() to get the number of available readers in the NFC system.
    2. Call nfc_se_service_get_readers() to retrieve the handles to the readers.
    3. Iterate through the readers you retrieved in the previous step and use nfc_se_reader_get_name() to find the handle to the intended SE. The UICC SE starts with the string "SIM".
    4. Call nfc_se_reader_open_session() to open a session to the reader you just found.
  2. Open a connection and exchange APDUs with a Java Card applet using the following steps:
    1. Call nfc_se_session_open_logical_channel(), providing the session obtained in step 1.
    2. Call nfc_se_channel_get_transmit_data() to read any data received before starting any APDU exchanges.
    3. Call nfc_se_channel_transmit_apdu() to send an APDU and get the size of the response returned.
    4. Call nfc_se_channel_get_transmit_data() to retrieve the data resulting from the function you just called.
    5. Repeat the previous two steps as required.
  3. Call nfc_se_channel_close_channel() to close the channel.

The following sample code illustrates how to connect to the UICC SE to exchange an APDU.

Not applicable

Not applicable

// variables for handles
uint32_t hSEService;
uint32_t seChannel;
uint32_t uiccSeReaderID = 0;

// variables for retrieving the Readers, holders of 
// possible secure elements
uint32_t numberOfReaders = 0;
uint32_t *phReaders = NULL;
static int DEF_LEN = 10;
char readerName[DEF_LEN];
uint32_t len = 10;

//variables for opening and exchanging data
fcp_type_t fcpResponseType;
int32_t openResponseLen;
uint32_t exchangeResponseLen;
uint32_t nReceiveAPDUBufferSize;
uint8_t* result;

uint8_t aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x63, 0x50, 
                  0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 };
uint32_t aid_len = sizeof(aid);
uint8_t select_file_apdu[] = { 0x00, 0xA4, 0x00, 0x0C,
                               0x02, 0x50, 0x31 };
uint32_t apdu_len = sizeof(select_file_apdu);

// loop variable
uint32_t i;

// Find readers we have access to
if( NFC_RESULT_SUCCESS !=  
        nfc_se_service_get_num_readers(&numberOfReaders) ) {
    // Handle error - this is a system error 
    // and the app cannot continue.
    ...
    
}

// Allocate space for the readers
phReaders = (uint32_t*)malloc (sizeof(uint32_t) * 
                               numberOfReaders);

// Get the handles for the readers
if( NFC_RESULT_SUCCESS !=  
        nfc_se_service_get_readers(phReaders, 
                                   &numberOfReaders) ){
    // Handle error - this is a system error and the
    // app cannot continue.
    ...
    
}

// Iterate through the readers to find the SIM reader
for( i = 0; i < numberOfReaders; i++ ) {
    len = 10;
    if( NFC_RESULT_SUCCESS !=  
            nfc_se_reader_get_name(phReaders[i], 
                                   readerName, 
                                   &len) ){
        // Handle error - this is a system error and 
        // the app cannot continue.
    }

    if( ( len == 3 ) && (strcmp(readerName, "SIM") == 0) ) {
        uiccSeReaderID = phReaders[i];
        break;
    }
}

// Deallocate the array for holding the readers
free(phReaders);

// Open a session with the SIM Reader
// Note: You may hold onto this session for the lifetime 
// of you application.
if( NFC_RESULT_SUCCESS !=  
        nfc_se_reader_open_session( uiccSeReaderID, 
                                    &hSESession ) ) {
    // Handle error - this is a system error and 
    // the app cannot continue.
    ...
    
}

// Open a channel to AID A000000063504B43532D3135
fcpResponseType = OPEN_NO_FCP_INFO;
openResponseLen = 0;
if( NFC_RESULT_SUCCESS !=  
       nfc_se_session_open_logical_channel( hSESession, 
                                       aid, 
                                       aid_len, 
                                       fcpResponseType, 
                                       &seChannel, 
                                       &openResponseLen )) {
    // Handle error
    ...
    
 else {
     result = (uint8_t*)malloc (sizeof(uint8_t) * 
                                openResponseLen);
     //get the response of the open call
     nReceiveAPDUBufferSize = openResponseLen;

     if( NFC_RESULT_SUCCESS !=  
             nfc_se_channel_get_transmit_data(seChannel, 
                                &result[0], 
                                &nReceiveAPDUBufferSize)) {
         // Handle error
         ...
         
     }

     // the result of the open should be 90 00
     if((nReceiveAPDUBufferSize < 2) ||
          ((0x90 != result[nReceiveAPDUBufferSize - 2]) 
          && (0x00 != result[nReceiveAPDUBufferSize - 1]))) {
         // Handle error
         ...
         
     }
     free(result);
}

if( NFC_RESULT_SUCCESS != 
        nfc_se_channel_transmit_apdu( seChannel, 
                                      select_file_apdu, 7, 
                                      &exchangeResponseLen ) ) {
    // Handle error
    ...
    
}

nReceiveAPDUBufferSize = exchangeResponseLen;
result = (uint8_t*)malloc (sizeof(uint8_t) * 
                           exchangeResponseLen);

if( NFC_RESULT_SUCCESS == 
        nfc_se_channel_get_transmit_data( seChannel, 
                                  &result[0],
                                  &nReceiveAPDUBufferSize ) ) {

    //Print the response
    for( i = 0; i < nReceiveAPDUBufferSize - 1; i ++ ) {
        printf( "0x%.2x, ", result[i] );
    }
    printf("0x%.2x }\n", result[nReceiveAPDUBufferSize - 1]);
}

// Free up the memory allocated
free( result );

// Close the channel
if( NFC_RESULT_SUCCESS != 
        nfc_se_channel_close_channel( seChannel ) ) {
    // Handle error
    ...
    
}
        

Last modified: 2015-05-07



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus