This discussion is archived
5 Replies Latest reply: Nov 12, 2012 4:03 PM by safarmer RSS

my first application result

965207 Newbie
Currently Being Moderated
Hii every body ,,
I am new to smart card application development,, I tried to build my first application which is simple
the application send a student mark through APDU command and wait a result from an applet which is pass or fail
but the message which come to me is (n) which is strange... could you told me why it is come like that.


Here is my andorid activity
[
package sadi.example.studenttest;


import android.app.Activity;
import android.os.Bundle;
import android.smartcard.CardException;
import android.smartcard.ICardChannel;
import android.smartcard.SmartcardClient;
import android.smartcard.SmartcardClient.ISmartcardConnectionListener;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

public class StudentActivity extends Activity {

     /** The AID of the HelloSmartcard applet on the smart card. */
     private static final byte[] APPLET_AID = new byte[] { (byte) 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, (byte) 0x08, 0x09, 0x00, 0x00 };
               
     /** Smartcard API handle. */
     SmartcardClient smartcard;

     /** GUI elements on the screen. */
     TextView textview = null;
     ScrollView scrollview = null;
     EditText editText = null;
     Button button = null;

     
     /**
     * Connection listener object to be called when the
     * service is successfully connected or disconnected.
     * After <code>serviceConnected</code> was called,
     * <code>SmartcardClient</code> object is valid.
     */
     ISmartcardConnectionListener connectionListener = new ISmartcardConnectionListener() {
          public void serviceConnected() {
               /** Enable the button to allow access to the smart card. */
               logText("Smart card service connected\n");
               button.setEnabled(true);
          }

          public void serviceDisconnected() {
               /** Disable the button to omit smart card access. */
               logText("Smart card service disconnected\n");
               button.setEnabled(false);
               
               /** Paranoia mode on: reconnect if the service was killed. */
               connectToService();
          }
     };

     /**
     * Internal helper method to log messages in the textview
     * and scroll to the bottom.
     */
     private void logText(String message) {
          scrollview.post(new Runnable() {
               public void run() {
                    scrollview.fullScroll(ScrollView.FOCUS_DOWN);
               }

          });
          textview.append(message);
     }

     /**
     * Internal helper method to convert a <code>byte[]</code>
     * to a <code>String</code>.
     */
     private static String bytesToString(byte[] bytes) {
          StringBuffer sb = new StringBuffer();
          for (byte b : bytes) {
               sb.append(String.format("%02x ", b & 0xFF));
          }
          return sb.toString();
     }
     
     /**
     * Internal helper method to do the Smartcard Service binding.
     */
     private void connectToService() {
          logText("Connecting to smart card service...\n");
          try {
               smartcard = new SmartcardClient(this, connectionListener);
          } catch (SecurityException e) {
               logText("Binding not allowed, uses-permission SMARTCARD?");
          } catch (Exception e) {
               logText("Exception: " + e.getMessage());
          }
     }

     
     @Override
     /**
     * Override onCreate and create the UI elements programmatically.
     */
     public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);

          LinearLayout layout = new LinearLayout(this);
          layout.setLayoutParams(new LayoutParams(
                    LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT));
          layout.setOrientation(LinearLayout.VERTICAL);
          
          editText = new EditText(this);
          editText.setLayoutParams(new LayoutParams(
                    LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT));
          button = new Button(this);
          button.setLayoutParams(new LayoutParams(
                    LayoutParams.FILL_PARENT,
                    LayoutParams.WRAP_CONTENT));
          button.setText("Click Me");
          button.setEnabled(false);
          button.setOnClickListener(new OnClickListener() {
               public void onClick(View v) {
                    runSample();
               }
          });

          scrollview = new ScrollView(this);

          textview = new TextView(this);
          textview.setLayoutParams(new LayoutParams(
                    LayoutParams.WRAP_CONTENT,
                    LayoutParams.WRAP_CONTENT));
          scrollview.addView(textview);

          layout.addView(editText);
          layout.addView(button);
          layout.addView(scrollview);

          setContentView(layout);

          connectToService();
     }

     @Override
     /**
     * Override onDestroy to cleanup the service binding
     */
     protected void onDestroy() {
          if (smartcard != null) {
               logText("Disconnecting from smart card service\n");
               smartcard.shutdown();
          }
          super.onDestroy();
     }

     /**
     * Internal method for smart card access called by the onClick handler
     */
     private void runSample() {
          logText("\nExecuting runSample()...\n");
          String cardReader = "";
          ICardChannel cardChannel = null;

          
          logText("List card readers:\n");
          try {
               String[] readers = smartcard.getReaders();
               for (String reader : readers) {
                    logText(" " + reader + "\n");
               }
               if (readers.length > 0) {
                    cardReader = smartcard.getReaders()[0];
               } else {
                    logText("no card reader found on system\n");
                    return;
               }
          } catch (CardException e) {
               logText("CardException: " + e.getMessage());
               return;
          }

          
          logText("Smart card status:\n");
          try {
               boolean isPresent = smartcard.isCardPresent(cardReader);
               logText(" " + (isPresent ? "present\n" : "absent\n"));
               if (isPresent == false) {
                    return;
               }
          } catch (CardException e) {
               logText("CardException: " + e.getMessage());
               return;
          }

          
          logText("Smart card communication:\n");
          try {
               cardChannel = smartcard.openLogicalChannel(cardReader, APPLET_AID);
               
               int x = Integer.parseInt(editText.getText().toString(), 16);
               byte mk = (byte) x;
               byte[] cmdApdu = new byte[] { (byte) 0x90, 0x10, 0x00, 0x00, 0x20,mk };
               logText(" ->: " + bytesToString(cmdApdu) + "\n");
               byte[] rspApdu = cardChannel.transmit(cmdApdu);
               logText(" <-: " + bytesToString(rspApdu) + "\n");

               byte[] helloStr = new byte[rspApdu.length];
               System.arraycopy(rspApdu, 0, helloStr, 0, rspApdu.length);
          

               Toast.makeText(StudentActivity.this, new String(helloStr),
                         Toast.LENGTH_LONG).show();
          } catch (CardException e) {
               logText("CardException: " + e.getMessage());
               return;
          }
          
          
          logText("Closing smart card channel\n");
          try {
               cardChannel.close();
          } catch (CardException e) {
               logText("CardException: " + e.getMessage());
               return;
          }          
     }
}
]


and here is my java card applet

[
package SPak;

import javacard.framework.APDU;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.Applet;
import javacard.framework.ISOException;

public class StudentApp extends Applet {
     
     final static byte Student_CLA= (byte)0xB0;
     final static byte MARK= (byte) 0x20;
     final static short AVERAGE=60;
     

     private StudentApp(byte bArray[], short bOffset, byte bLength) {
          register();
     }

     public static void install(byte bArray[], short bOffset, byte bLength)
     {          
     new StudentApp(bArray, bOffset,bLength);
     }

     
     public void process(APDU apdu) throws ISOException {
          // TODO Auto-generated method stub
          byte[] buffer = apdu.getBuffer();
          if(selectingApplet())
               return;
          if(buffer[ISO7816.OFFSET_CLA] != Student_CLA)
               ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
          switch(buffer[ISO7816.OFFSET_INS]){
          
          case MARK :
               verifyMark(apdu);
               return;
          default:
               ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
          
          }
          
     }
     
     private void verifyMark(APDU apdu){
          
          byte[] buffer = apdu.getBuffer();
          byte numByte = buffer[ISO7816.OFFSET_LC];
          byte byteRead = (byte) (apdu.setIncomingAndReceive());
          
          if((numByte != 1) || (byteRead != 1))
               ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
          
          byte SMARK = buffer[ISO7816.OFFSET_CDATA];
          if(SMARK > AVERAGE)
          {
               buffer[0] = (byte) 'P';
               buffer[1] = (byte) 'A';
               buffer[2] = (byte) 'S';
               buffer[3] = (byte) 'S';
               buffer[4] = (byte) ':';
               buffer[5] = SMARK;
               apdu.setOutgoingAndSend((short) 0, (short)6);
          }
          else{
               
               buffer[0] = (byte) 'F';
               buffer[1] = (byte) 'A';
               buffer[2] = (byte) 'I';
               buffer[3] = (byte) 'L';
               buffer[4] = (byte) ':';
               buffer[5] = SMARK;
               
               apdu.setOutgoingAndSend((short) 0, (short)6);
               
          }
          
          
     }

}
]

Edited by: 962204 on Oct 18, 2012 3:31 AM
  • 1. Re: my first application result
    Umer Journeyer
    Currently Being Moderated
    First of all try to post code within starting and ending code tags with *[]* around it.
    package SPak;
    
    import javacard.framework.APDU;
    import javacard.framework.ISO7816;
    import javacard.framework.ISOException;
    import javacard.framework.Applet;
    import javacard.framework.ISOException;
    
    public class StudentApp extends Applet {
    
    final static byte Student_CLA= (byte)0xB0;
    final static byte MARK= (byte) 0x20;
    final static short AVERAGE=60;
    
    
    private StudentApp(byte bArray[], short bOffset, byte bLength) {
    register();
    }
    
    public static void install(byte bArray[], short bOffset, byte bLength)
    {
    new StudentApp(bArray, bOffset,bLength);
    }
    
    
    public void process(APDU apdu) throws ISOException {
    // TODO Auto-generated method stub
    byte[] buffer = apdu.getBuffer();
    if(selectingApplet())
    return;
    if(buffer[ISO7816.OFFSET_CLA] != Student_CLA)
    ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
    switch(buffer[ISO7816.OFFSET_INS]){
    
    case MARK :
    verifyMark(apdu);
    return;
    default:
    ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
    
    }
    
    }
    
    private void verifyMark(APDU apdu){
    
    byte[] buffer = apdu.getBuffer();
    byte numByte = buffer[ISO7816.OFFSET_LC];
    byte byteRead = (byte) (apdu.setIncomingAndReceive());
    
    if((numByte != 1) || (byteRead != 1))
    ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
    
    byte SMARK = buffer[ISO7816.OFFSET_CDATA];
    if(SMARK > AVERAGE)
    {
    buffer[0] = (byte) 'P';
    buffer[1] = (byte) 'A';
    buffer[2] = (byte) 'S';
    buffer[3] = (byte) 'S';
    buffer[4] = (byte) ':';
    buffer[5] = SMARK;
    apdu.setOutgoingAndSend((short) 0, (short)6);
    }
    else{
    
    buffer[0] = (byte) 'F';
    buffer[1] = (byte) 'A';
    buffer[2] = (byte) 'I';
    buffer[3] = (byte) 'L';
    buffer[4] = (byte) ':';
    buffer[5] = SMARK;
    
    apdu.setOutgoingAndSend((short) 0, (short)6);
    
    }
    
    }
    
    }
    Can you please mention what type of strange output you are getting ? and what you are expecting ?

    Regards
  • 2. Re: my first application result
    965207 Newbie
    Currently Being Moderated
    The result I got is a toast that display (n) letter, but i think that the program should return a toast with (pass) or (fail) according to the mark we send.
  • 3. Re: my first application result
    Umer Journeyer
    Currently Being Moderated
    can you please place the APDU trace/log here...
  • 4. Re: my first application result
    965207 Newbie
    Currently Being Moderated
    I have installed the apk file on mobile so there is no log file avilable...
  • 5. Re: my first application result
    safarmer Expert
    Currently Being Moderated
    Depending on how you send the APDU's you may still be able to get a trace. Are you using nfc_extras.jar from Android or SEEK for Android to access the applet?

    - Shane

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points