Page 1 of 1

How to correctly implement GPO in OpenEMV ?

Posted: Wed Nov 16, 2016 7:17 am
by eclessiastes
I have some questions regarding implementation of Get Processing Options in OpenEMV applet.
My function looks like:

Code: Select all

   private final static byte[] gpo = new byte[]
   {
      (byte)0x80, 0x0A, 0x1C, 0x00, 0x08, 0x01, 0x01, 0x00, 0x18, 0x01, 0x02, 0x00
   };
   
   public void process(APDU apdu)
   {
      byte[] apduBuffer = apdu.getBuffer();
      byte cla = apduBuffer[ISO7816.OFFSET_CLA];
      byte ins = apduBuffer[ISO7816.OFFSET_INS];
      
      if (selectingApplet())
      {
         apdu.setOutgoing();
         apdu.setOutgoingLength((short)fci.length);
         apdu.sendBytesLong(fci, (short)0, (short)fci.length);
         return;
      }
       
        switch(cla)
        {
           case (byte)0x00:
              {
                 switch(ins)
                 {
                    case (byte)0xB2:
                       {
                             byte[] buf = apdu.getBuffer();
                      Util.arrayCopyNonAtomic(gpo,(byte)0,buf,ISO7816.OFFSET_CDATA,(short)gpo.length);
                          apdu.setOutgoingAndSend(ISO7816.OFFSET_CDATA,(short)gpo.length);
                       }
                       break;
                       
                    default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); break;
                 }
              }
           break;
         
         case (byte)0x80:
            {
               switch(ins)
               {
                   case (byte)0xA8:
                      {
                         byte[] buffer = apdu.getBuffer(); 
                         short le = apdu.setOutgoing();          
                         apdu.setOutgoingLength((byte)10);   
                         apdu.sendBytesLong(GPO_COMMAND, (short)0, (short)10);

                      }
                      break;
                      
                  case (byte)0xCA: getData(apdu, apduBuffer); break;
                  default: ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED); break;
               }
            }

          break;

      default: ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED); break;
        }
   }

I have some questions regarding this code
1: When i send: 80 A8 00 00 02 83 00, I receive 6C 0A. When i send again: 80 A8 00 00 0A i get the gpo, however if i send 00 A8 00 0A 83 00 or do this automatically from my c++ program or with program like CardPeek, this function goes in an endless loop.
How can i programmatically ignore the Data In field and just process apdu with success response regardless of Data Field ?
2: In some applets when i select application i receive 61 xx status and then retrieve the bytes with C0. How can i implement this on selectingApplet() ? Currently my function just return the full bytes.
Thanks in advance!

Re: How to correctly implement GPO in OpenEMV ?

Posted: Wed Nov 16, 2016 9:55 am
by tay00000
These codes seems to be rather incomplete and does not give the full picture. Your questions are rather vague and confusing as well.

Are you trying to write a card applet implementation or are you trying to write a desktop application that reads card ?

Since these code fragments are largely incomplete, it is hard to diagnose the problem...

1.) Did you call apdu.setIncomingAndReceive() before you apdu.getBuffer() ? Without the setIncomingAndReceive(), if you are using T=0, it will start to act strangely. That might explain the weird infinite looping ?

2.) Is the card reading program set to T=0, 1, or Auto ?

3.) You asked "How can i programmatically ignore the Data In field and just process apdu with success response regardless of Data Field ?". Are you referring to desktop application side that reads the card or are you referring to card applet side ?

If it's a desktop application receiving a card's response APDU, you will get 2 bytes SW and then the rest are data. Essentially you should not need to do anything with the response APDU from the card as it's mostly a byte array and you simply traverse the array and read the SW bytes off as the last two bytes from the desktop application.

4.) The error 6C XX indicates some sort of bad length. 6C XX usually indicates bad Le length. Take a look at this SW response table (https://www.eftlab.co.uk/index.php/site ... ponse-list). Essentially, 6C 0A response means bad Le length for 0x0A bytes (10 bytes should be the Le) is required thus when you send "80 A8 00 00 02 83 00", it will show error because it is expecting 10 data bytes while you only sent 2 data bytes.

5.) You asked "In some applets when i select application i receive 61 xx status and then retrieve the bytes with C0. How can i implement this on selectingApplet() ? Currently my function just return the full bytes.". Ok, spoonfeeding time :P . Below is the answer.

Code: Select all

public void process(APDU apdu) {

    // Remember to do selectingApplet() first before calling other functions like processing CLA, INS, and so on...
    if (selectingApplet()) {
        // TODO: DO SOMETHING HERE
    }
   
    // Process CLA, INS ... normally
    if (buffer[ISO7816.OFFSET_CLA] == CLA) {
       // TODO: DO OTHER THINGS
    }
}

Re: How to correctly implement GPO in OpenEMV ?

Posted: Wed Nov 16, 2016 10:22 pm
by eclessiastes

Code: Select all

apdu.setIncomingAndReceive();

this line before apdu.getBuffer() solved all problems.
Thanks