Tuesday 3 April 2012

EMV Transaction Flow: [ Step 1 ] Application Selection


Previous Post Next Post EMV Tags List
  EMV Transaction an Introduction     EMV Transaction: Step 2.) Initiate application processing     EMV Tags List  




Step 1 : Application Selection



Before the 1st step of Application Selection, we need to reset the EMV chip card, lets see how that happens.

Answer To Reset (ATR)

Resetting the card

Before any communication with the card, we need to reset the card. There are two ways of resetting.

Cold Reset:
The cold reset is the initial start of all communication between the card and the reader. If the card is already powered up, then a cold reset will first deactivate power supply. Then power is supplied to the card and the reset line is used to signal a reset to the chip. The terminal then waits for an answer (ATR).

Warm Reset:
During warm reset the terminal is sending a reset signal to the card without disconnecting power supply.


       After the reset signal from the terminal, the card will answer with a byte string called ATR. This string contains certain information about the card which are necessary for the communication between card and terminal. After a warm reset the card answers with a different ATR, e.g. to switch to a slower communication rate.

Example:
0000  3B FF 18 00 FF 81 31 FE 45 65 63 0D 02 50 02 80  ;.....1.Eec..P..
0010  00 08 37 70 20 10 05 00 B2                       ..7p .... 

Example:
TS  : 3B  Direct logic
TO  : FF  K    =  15 byte [historical characters]
TA1 : 18  Fi/f =  372/ 5  [clock rate conversion factor / max. frequency (MHz)]
          Di   =  12      [bit rate conversion factor]
TB1 : 00  pa   =   4 %    [programming voltage accurancy]
          I    =  25 mA   [maximum current]
          P    =   0 V    [programming voltage]
TC1 : FF  N    = 255 etu  [extra guardtime]
TD1 : 81  T    = T=1      [protocol type]
TD2 : 31  T    = T=1      [protocol type]
TA3 : FE  IFSC = 254      [information field size]
TB3 : 45  CWT  =  43 etu  [character waiting time]
          BWT  =  12 etu  [block waiting time]
65630D025002800008377020100500 ec..P....7p ...




The first byte of the string is the initial character "T0". It defines which of the two 
   transmission technique, "direct convention (3B)" or "indirect convention (3F)", should be used.
   In our case we have the byte 3B and a direct convention. 

The second byte is the format character T0. Here we obtain the length of the historical characters. In our ATR the last 15 bytes are the historical characters. They contain some information e.g. the card's features and operating system version.

TA1 to TC3 are interface characters. They are necessary to determine the transmission between the card and the terminal. They contains informations like voltage, transmission rates and timeouts.

TA3 determines the information field size. The terminal used this value to determine the max. size of a block send to the card.

The character TB3 is relevant for the character and block waiting time. The character waiting time is the max. timeout between two subsequent bytes and the block waiting the time between two subsequent blocks.
If the waiting time is higher than determined, then terminal will issue an timeout error.
All waiting times are expressed as Elementary Time Unit (ETU), which is the time required to transmit a single bit. The default communication rate is 9600 bits per second, which translates to an ETU of 1/9600 seconds.

In simple words,
-Physical data transportation is done over an I/O channel.
-The convention of passing data is specified in the Initail Character (TS) transmitted by integrated chip card      in Answer To Reset.
-Number of characters returned by ICC at ATR varies depending on transmission protocols & values supported.
-Two basic ATR are T = 0 (character mode) & T = 1 (block protocol) (in above example we get T0).
-ICC returning one of the two modes confirms correct operation & interoperability in terminals.

If you don't understand this ATR thing, don't worry...its not needed further.
Only thing you need to remember is that on inserting the EMV chip card into a EMV card slot you should get a successful Answer To Reset for your Cold Reset. If you dont then there's some problem in your card or your device.
========================================================================

Reading EMV

An application in ICC has a set of items of information within files. This information is accessible to terminal only after successful application selection.
(here item of information means Data Elements identified by a name or Tag)
For Application Selection lets have a quick view of the file structure within the chip card.

File Structure

The files on a smart card are organized in a tree structure. The topmost file is the Master File (MF). The MF has one or more Application Definition Files (ADF). Inside of an ADF are Applicaton Elementary Files (AEF or EF) that contain data.
You can quickly select an ADF with the Application Identifier (AID). Within an ADF you can select AEFs with the Short File Identifier (SFI). The SFI help us read the records in a file.




ISO/IEC 7816 defines a process for application selection. The intent of application selection was to allow cards to contain completely different applications, for example GSM and EMV. EMV however took application selection to be a way of identifying the type of product, so that all product issuers (Visa, MasterCard etc.) have to have their own application. The way application selection is prescribed in EMV is a frequent source of interoperability problems between cards and terminals.
An application identifier (AID) is used to address an application (ADF) in the card. An AID consists of a registered application provider identifier(RID) of five bytes, which is issued by the ISO/IEC 7816-5 registration authority. This is followed by a proprietary application identifier extension (PIX) which enables the application provider to differentiate between the different applications offered. The AID is printed on all EMV cardholder receipts.
Additional ADF's defined under the control of other application providers may be present in thd card, but will not have RID's assigned for payment systems.
The common Payment System Environment PSE,  for all financial or banking cards has Directory name as
"1PAY.SYS.DDF01" which may or may not be a MF. This Directory (DDF-Directory Defination File) has entries for other ADF's. Files revealed by this PSE assures international operability.

In case the card is an NFC card then it will have PPSE (Paypass Payment System Environment) as 
"2PAY.SYS.DDF01" and not "1PAY.SYS.DDF01"

Card scheme RID Product PIX AID
Visa A000000003 Visa credit or debit 1010 A0000000031010
Visa Electron 2010 A0000000032010
V PAY 2020 A0000000032020
Plus 8010 A0000000038010
MasterCard A000000004 MasterCard credit or debit 1010 A0000000041010
MasterCard[4] 9999 A0000000049999
Maestro (debit card) 3060 A0000000043060
Cirrus (interbank network) 6000 A0000000046000
UK Domestic Maestro - Switch (debit card) A000000005 Maestro UK 0001 A0000000050001
Solo 0002 A0000000050002
American Express A000000025 American Express 01 A00000002501
RuPay (India) A000000524 RuPay 1010 A0000005241010
Discover A000000152 Discover 3010 A0000001523010
Interac (Canada) A000000277 Debit card 1010 A0000002771010
JCB A000000065 Japan Credit Bureau 1010 A0000000651010
LINK (UK) ATM network A000000029 ATM card 1010 A0000000291010
Dankort (Denmark) A000000121 Debit card 1010 A0000001211010
CoGeBan (Italy) A000000141 PagoBANCOMAT 0001 A0000001410001
Banrisul (Brazil) A000000154 Banricompras Debito 4442 A0000001544442
ZKA (Germany) A000000359 Girocard 1010028001 A0000003591010028001
CB card (France) A000000042 CB card 1010 A0000000421010
SPAN2 (Saudi Arabia) A000000228 SPAN 1010 A0000002282010/1010

Application Selection

Application Selection is the first step after the Answer to Reset. It has the function to select the ADF for the transaction process.

There are two ways to get the right ADF:

Method 1.)
If the card supports the Payment System Environment (PSE), the terminal reads out the necessary
information to select the ADF.

Method 2.)
If there is no PSE, the terminal will use a list of AIDs and get the right by trying.


Method 1:   

The PSE  Way...
To read the card's data we have to select the ADF first. We'll do this with a SELECT Command APDU.

The SELECT command supports the following options :

Parameter
Description
0x00
Class Byte
0xA4
Instruction Byte :
SELECT Command
0x04
Parameter 1 :
Select a directory by name.
0x00
Parameter 2 :  
0x00 when you write the complete AID Name.
0x0E
Lc = Length of data to be sent to the card :
0x0E  (i.e.) 14
AID
Data bytes to be sent to the card :
Directory name (AID) in bytes of  "1PAY.SYS.DDF01"
0x00
Le = Number of data bytes expected in the response :
Set to 0x00 to retrieve the complete response of up to 256 bytes.

the byte array for "1PAY.SYS.DDF01" is  { 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 }

   1    P   A   Y    .   S   Y   S     .   D   D   F   0   1
 0x31  0x50  0x41  0x59  0x2E  0x53  0x59  0x53   0x2E  0x44  0x44  0x46  0x30  0x31 

COMMAND:
00 A4 04 00 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 00

On sending  this C-APDU if you receive SW1 = 0x90 & SW2 = 0x00
then you have received a successful response.

SW1/SW2=9000 (Normal processing : No error) with some response.

RESPONSE HEX:
6F 15 84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 03 88 01 01








The data structure of any response from the card will be in TLV Format.
[T]  Tag
[L]  Length
[V]  Value
Tag: 0x6F  File Control Information (FCI) Template
Length: 0x15  i.e.  21 
Value: 84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 03 88 01 01
Tag: 0x84  Dedicated File (DF) Name
Length: 0x0E i.e.  14
        Value:  31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 
Tag: 0xA5  File Control Information (FCI) Proprietary Template
Length: 0x03 i.e.  3
                                                                             Value:  88 01 01
Tag: 0x88  Short File Identifier (SFI)
Length: 0x01 i.e.  1
                                                                                      Value: 01



Here's a link for List of all Tags that may appear in an Response >> EMV Tags List

You may get response with slight variations depending on the card you are using
for example;
RESPONSE HEX :
6F 20 84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 0E 88 01 02 5F 2D 04 6E 6F 65 6E  9F 11 01 01
Here the difference is FCI returned more data (length= 0E i.e 14) which contains
Tag 0x88    (SFI)    Value 0x02
Tag 5F2D    (Language Preference)    Value 0x6E 0x6F 0x65 0x6E  
i.e.  ascii value of following characters        'n'   'o'   'e'   'n'      stands for "norwegian"
Tag 9F11 (Issuer Code Table Index)   Value 0x01


Returned 9000 as SW1 SW2 for this command means, the selection was successful and the card supports the PSE method (Method 1 - Payment System Environment).


Now we need to Read out the necessary information to select the ADF, for which we will need the SFI value we got in the response. (you may get different SFI values for different cards, in first response example SFI is 0x01 where as  in 2nd response example SFI is 0x02) 

 
Read data records using SFI received: 

Read Records 1 to 16 (i.e.  0x01  to  0x10) for the SFI you received.
If we get response other than (SW1/SW2 = 9000) then, stop reading and break from the reading loop.

COMMAND: 0x00, 0xB2, recnum, [(sfi << 0x03) | 0x04], 0x00





 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
YET TO COMPLETE THE REMAINING PART OF THIS POST...   :( 
 
 
 
 



Read EMV
To read all data from the card, you can use the script contained in the following section:
try 
{
    var card = new Card(_scsh3.reader);
    card.reset(Card.RESET_COLD);

    var aid = new ByteString("A0000000041010", HEX); // MC
 // var aid = new ByteString("A0000000031010", HEX);  // VISA

 // var aid = new ByteString("1PAY.SYS.DDF01", ASCII);



    var fcp = card.sendApdu(0x00, 0xA4, 0x04, 0x00, aid, 0x00, [0x9000]);

    print("FCP returned in SELECT: ", new ASN1(fcp));

    for (var sfi = 1; sfi <= 31; sfi++) 
    {
        for (var rec = 1; rec <= 16; rec++) 
        {
            var tlv = card.sendApdu(0x00, 0xB2, rec, (sfi << 3) | 4, 0x00);
            if (card.SW == 0x9000) 
            {
                print("SFI " + sfi.toString(16) + " record #" + rec);
                try 
                {
                    var asn = new ASN1(tlv);
                    print(asn);
                }
                catch(e) 
                {
                    print(tlv.toString(HEX));
                }
            }
        }
    }
}

catch(e) 
{
 print("Exception reading from Credit Card Application: " + e.toString());
}
Line 06
This script works either with Mastercard or VISA because both cards are using different AIDs. You'll need to activate the AID that matches your card.
Line 13


















The card.sendAPDU() method supports a further parameter, which is used to define a list of expected SW codes. [0x9000] defines a list with a single 0x9000 entry.
Line 17
Now we create a loop that starts with the first AEF (SFI=1) and ends with SFI 31.
Line 19
In a second loop the record number of every AEF will be iterated from 1 to 16.
Line 21
With the READ RECORD command issued using card.sendApdu() we can obtain the data.

Parameter
Description
0x00
Class byte
0xB2
Instruction byte
READ RECORD Command
rec
Parameter 1 byte. It contains the record number.
(sfi << 3) | 4
Parameter P2 byte. The first 5 bits contain the SFI and the last three bits are set to 1,0,0, which means that P1 is a record number.
To calculate the P2 parameter, the SFI will be shift three bits to the left and combinated with a '4'
e.g.
00000001
00001000 <<3
00000100 | 4
00001100 = 0x0C
0x00
Le byte. It is '00' so up to 256 bytes are expected.
Line 22
If the statusword has the value 0x9000 the command was successful and the tlv object will be printed.

============================

Data Structure

ASN.1 - Abstract Syntax Notation One

ASN.1 is a formal language to describe data structures. It consists of primitive data objects (boolean, integer, UTF8 string) that can be constructed to define more complex data structures (Sequences, Sets).
e.g.
Record ::= SEQUENCE
{
 Name::= UTF8 String
 Age::= Integer
 Vegetarian::= Boolean OPTIONAL
 Smoker::= [0] Boolean OPTIONAL
}
Based on ASN.1, instances of data structures can be defined:
Record
{
 Name::= "Möller"
 Age::= "30"
 Vegetarian::= "false"
 Smoker::= "true"
}

TLV - [T]ag [L]ength [V]alue

To encode ASN.1 instances in a computer readable form, a notation called TLV is used. Every data object consists of a tag, a length byte and the value/data.
The tag defines, for example, if the object is an integer, boolean or something else.
Tag
30 : Sequence
OC : UTF8 String
02 : Integer
01 : Boolean
Here we have the ASN.1 example from above encoded as TLV structure:

30 11 OC 06 4D 7E 6C 6C 65 72 02 01 1E 01 01 00 80 01 00

which means

Tag Length Value

30 11                   Sequence with a length of 17 bytes
OC 06 4D 7E 6C 6C 65 72 UTF8 String with a length of 6 bytes and the value Möller
02 01 1E                Integer with a length of 1 and the value 30
01 01 00                Optional Boolean with the value false
80 01 FF                Optional Boolean with the value true

Coding of the Tag



b8
b7
b6
b5
b4
b3
b2
b1
Meaning
0
0






universal class
0
1






application class
1
0






context specific class
1
1






private class


0





primitiv data object


1





constructed data object



x
x
x
x
x
tag value



1
1
1
1
1
tag continoues on a 2nd byte

Optional Byte 2:

b8
b7
b6
b5
b4
b3
b2
b1
explanation
x







b8 = 0 : this is the last byte of the tag

x
x
x
x
x
x
x
tag value
Tags are divided into four classes defined by b8 and b7.
The universal class contains basic data types like integer, boolean, etc.
The application class is used for data elements defined by an application specification or industry standard (e.g. EMV).
The context specific class is used for data elements that are unique within it's enclosing context (Like the concept of local variables in a programming language). For example the second optional boolean "smoker" is a context specific class so that it has a tag different from "vegetarian".
The private class is used for all privately defined data objects.
Example
The SEQEUNCE tag '30' decodes to :
b8 b7 b6 b5 b4 b3 b2 b1
0  0                    = universal class 
      1                 = constructed
         1  0  0  0  0  = tag value

0011 0000
  '30'

  ---------------
  
The UTF8 String tag '0C' decoded:
b8 b7 b6 b5 b4 b3 b2 b1
0  0                    = universal class
      0                 = primitive
         0  1  1  0  0  = tag value

0000 1100
   '0C'

Length field

Depending on the length of the value field we have one or more bytes in the length field.
The length field has the following structure:
Number of length bytes Length of value Coding
1 0-127 0xxxxxx
2 128-255 10000001 xxxxxxxx
3 256-65535 10000010 xxxxxxxx xxxxxxxx
For length encodings > 127, the first byte contains the number of subsequent bytes, while the most significant bit is set to 1. The actual length is then encoded as integer value on the subsequent bytes with the most significant byte first.
Here we have two examples read from a credit card using the reademv.js script:

Example 1:
A2 C: 00 A4 04 00 - SELECT Lc=7 
      0005  A0 00 00 00 04 10 10                             .......
      Le=0 
   R: SW1/SW2=9000 (Normal processing: No error) Lr=28
      0000  6F 1A 84 07 A0 00 00 00 04 10 10 A5 0F 50 0A 4D  o............P.M
      0010  61 73 74 65 72 43 61 72 64 87 01 01              asterCard...

// We will focus on the response value:
6F 1A 84 07 A0 00 00 00 04 10 10 A5 0F 50 0A 4D 61 73 74 65 72 43 61 72 64 87 01 01
Tag: "6F"
Application class
Primitive data object

Length: "1A"
'1A' = binary 00011010 = decimal 26 . There are 26 value bytes

Value:
"84 07 A0 00 00 00 04 10 10 A5 0F 50 0A 4D 61 73 74 65 72 43 61 72 64 87 01 01"
Example 2:
A2 C: 00 B2 01 1C - READ RECORD      Le=0 
   R: SW1/SW2=9000 (Normal processing: No error) Lr=195
      0000  70 81 C0 8F 01 04 9F 32 01 03 92 24 9F FB FB 7F  p......2...$....
      0010  EE C7 B0 43 67 B3 E4 C6 71 C3 0B 4A EE AD A2 C1  ...Cg...q..J....
      0020  93 49 58 DD 61 04 D1 50 EA FD 3C 05 2C 97 0E 8D  .IX.a..P..<.,...
      0030  90 81 90 52 D7 78 E3 33 2B 72 0F 4F E4 1D 7C 1B  ...R.x.3+r.O..|.
      0040  ED 06 45 EA 7D EF 14 E4 E3 6F 80 90 A1 42 B7 E1  ..E.}....o...B..
      0050  B1 7D DE CF AA 80 FC B4 BF 04 1C 2D 44 04 AD 1E  .}.........-D...
      0060  7F 19 C9 56 5B 93 7F 5E B5 02 90 6F EE 32 F5 21  ...V[..^...o.2.!
      0070  E5 32 AB FC 37 F0 46 1E 91 AA 46 79 8D 74 C4 BA  .2..7.F...Fy.t..
      0080  FA 08 81 A3 0E 1F 9B B8 7A B7 85 C7 E2 9A 45 46  ........z.....EF
      0090  D1 B7 FD 6F 98 A4 65 19 FB 7F 53 20 3A 93 AA C9  ...o..e...S :...
      00A0  5C 5B 53 B8 CC 6E 9A D3 DB C9 25 CC 72 B9 6E DD  \[S..n....%.r.n.
      00B0  78 3B B0 D7 B6 E8 E9 78 BB 35 5E 45 5E 7A 5B CA  x;.....x.5^E^z[.
      00C0  57 C4 95                                         W..
Tag: "70"
Application class
Constructed data object

Length: "81 C0"
1st byte '81' = binary 10000001 . There are two length bytes in the range 128 and 255.
2nd byte 'C0' = binary 11000000 = decimal 192. There are 192 value bytes.

Value:
"8F 01 04 9F 32 01 03 92 24 9F FB FB 7F EE C7 B0 43 67 B3 E4 C6 71 C3 0B 4A EE AD A2 C1 04 D1 50 EA FD 3C 05 2C 97 0E 8D 78 E3 33 2B 72 0F 4F E4 1D 7C 1B EF 14 E4 E3 6F 80 90 A1 42 B7 E1 B1 7D DE CF AA 80 FC B4 BF 04 1C 2D 44 04 AD 1E 7F 19 C9 56 5B 93 7F 5E B5 02 90 6F EE 32 F5 21 E5 32 AB FC 37 F0 46 1E 91 AA 46 79 8D 74 C4 BA FA 08 81 A3 0E 1F 9B B8 7A B7 85 C7 E2 9A 45 46 D1 B7 FD 6F 98 A4 65 19 FB 7F 53 20 3A 93 AA C9 5C 5B 53 B8 CC 6E 9A D3 DB C9 25 CC 72 B9 6E DD 78 3B B0 D7 B6 E8 E9 78 BB 35 5E 45 5E 7A 5B CA 57 C4 95"

===================================

Using the PSE method

/**
 * Send SELECT APDU
 */
EMV.prototype.select = function(dfname, first) {
    var fci = this.card.sendApdu
              (0x00, 0xA4, 0x04, (first ? 0x00 : 0x02), dfname, 0x00);
    return(fci);
}



/**
 * Send READ RECORD APDU
 *
 * Return empty ByteString if no data was read
 */
EMV.prototype.readRecord = function(sfi, recno) {
    var data = this.card.sendApdu(0x00, 0xB2, recno, (sfi << 3) | 0x04, 0);
    if (this.card.SW1 == 0x6C) {
        var data = this.card.sendApdu
                   (0x00, 0xB2, recno, (sfi << 3) | 0x04, this.card.SW2);
    }

    return(data);
}
First we select the PSE (1PAY.SYS.DDF01)
/**
 * Select and read Payment System Environment on either
 * contact or contactless card
 */
EMV.prototype.selectPSE = function(contactless) {
    this.PSE = null;

    var dfname = (contactless ? EMV.PSE2 : EMV.PSE1);
    var fci = this.select(dfname, true);
    print(fci);
    if (fci.length == 0) {
        GPSystem.trace("No " + dfname.toString(ASCII) + " found");
        return;
    }
A2 C: 00 A4 04 00 - SELECT Lc=14 
      0005  31 50 41 59 2E 53 59 53 2E 44 44 46 30 31        1PAY.SYS.DDF01
      Le=0 
   R: SW1/SW2=9000 (Normal processing: No error) Lr=23
      0000  6F 15 84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46  o...1PAY.SYS.DDF
      0010  30 31 A5 03 88 01 01                             01.....
The selection was successful (SW1/SW2=9000), so the card supports the PSE method.

Get the SFI

To process we need the SFI.
Therefore we have to decode first the returned FCI.
    // Decode FCI Template
    var tl = new TLVList(fci, TLV.EMV);
    var t = tl.index(0);
var t:
6F 15 84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 03 88 01 01
    assert(t.getTag() == EMV.FCI); // EMV.FCI = 0x6F
    var tl = new TLVList(t.getValue(), TLV.EMV);
    assert(tl.length >= 2);
var tl:
84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31 A5 03 88 01 01
 
    // Decode DF Name
    t = tl.index(0);
var t:
84 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31
    assert(t.getTag() == EMV.DFNAME); // EMV.DFNAME = 0x84;
 
    // Decode FCI Proprietary Template
    t = tl.index(1);
var t:
A5 03 88 01 01
    assert(t.getTag() == EMV.FCI_ISSUER); // EMV.FCI_ISSUER = 0xA5;

    var tl = new TLVList(t.getValue(), TLV.EMV);
    // Decode SFI of the Directory Elementary File
    t = tl.index(0);
var t:
88 01 01
    assert(t.getTag() == EMV.SFI); // EMV.SFI = 0x88;
    var sfi = t.getValue();
    assert(sfi.length == 1);
    sfi = sfi.byteAt(0);
sfi: 0x01
    this.PSE = new Array();

Read Records

Now we create a loop to read all records in this AEF, started with record number 1.
    // Read all records from Directory Elementary File
    var recno = 1;
    do {
        var data = this.readRecord(sfi, recno++);
        if (data.length > 0) {
            var tl = new TLVList(data, TLV.EMV);
            assert(tl.length == 1);
            var t = tl.index(0);
            assert(t.getTag() == EMV.TEMPLATE);
            var tl = new TLVList(t.getValue(), TLV.EMV);
            assert(tl.length >= 1);
            for (var i = 0; i < tl.length; i++) {
                var t = tl.index(i);
                assert(t.getTag() == 0x61);
                this.PSE.push(new TLVList(t.getValue(), TLV.EMV));
            }
        }
    } while (data.length > 0);
}
At this time we have two entries in this PSE:
61 1F 4F 08 A0 00 00 00 25 01 05 01 50 10 50 65 72 73 6F 6E 61 6C 20 41 63 63 6F 75 6E
74 87 01 01
and
61 1E 4F 07 A0 00 00 00 29 10 10 50 10 50 65 72 73 6F 6E 61 6C 20 41 63 63 6F 75 6E 74
87 01 02

Check Priority

Every entry contains an AID. Now we proof which of them have they highest priority.
/**
 * Return array of PSE entries or null if none defined
 */
EMV.prototype.getPSE = function() {
    return this.PSE;
}

/**
 * Return AID of application with highest priority or null if no PSE defined
 */
EMV.prototype.getAID = function() {

    var prio = 0xFFFF;
    var aid = null;
    var pse = e.getPSE();
    if (pse == null) {
    return null;
    }
    // Iterate through PSE entries
    for (var i = 0; i < pse.length; i++) {
        var t = pse[i].find(EMV.AID);
        assert(t != null);
        var entryAid = t.getValue();
        print(entryAid);

        var t = pse[i].find(EMV.LABEL);
        assert(t != null);
        print(t.getValue().toString(ASCII));

        var entryPrio = 0xFFFE;
        var t = pse[i].find(EMV.PRIORITY);
        if (t != null) {
            entryPrio = t.getValue().toUnsigned();
            entryPrio &= 0x0F;
        }
        if (entryPrio < prio) {
            prio = entryPrio;
            aid = entryAid;
        }
    }
    this.cardDE[EMV.AID] = aid;
    return aid;
}
In the first run the value for the entryPrio is: 0x01. 0x01 &= 0x0F is 0x01. 0x01 is less than 0xFFFF and from this it follows that 0x01 is now the prio and the aid is now the entryAid.
In the second run the value for the entryPrio is: 0x02. 0x02 &= 0x0F is 0x02. 0x02 is greater than 0x01, the priority of this entry is lower.

Final Selection

Select The ADF with the given AID.
/**
 * Select application and return FCI
 */
EMV.prototype.selectADF = function(aid) {
    var fci = this.select(aid, true);
    print(fci);
    this.cardDE[EMV.AID] = aid;
}

Using a list of AIDs

First we select the PSE (1PAY.SYS.DDF01)
/**
 * Select and read Payment System Environment on either
 * contact or contactless card
 */
EMV.prototype.selectPSE = function(contactless) {
    this.PSE = null;

    var dfname = (contactless ? EMV.PSE2 : EMV.PSE1);
    var fci = this.select(dfname, true);
    print(fci);
    if (fci.length == 0) {
        GPSystem.trace("No " + dfname.toString(ASCII) + " found");
        return;
    }
96 C: 00 A4 04 00 - SELECT Lc=14 
      0005  31 50 41 59 2E 53 59 53 2E 44 44 46 30 31        1PAY.SYS.DDF01
      Le=0 
   R: SW1/SW2=6A82 (Checking error: File not found) Lr=0
No 1PAY.SYS.DDF01 found
The selection failed because the ADF doesn't exist (SW1/SW2=6A82). The terminal uses now a list of AIDs to select the right ADF.
The terminal starts with the first AID in the Array. If the selection failed the terminal tries the next AID.
/**
 * Try a list of predefined AID in order to select an application
 */
EMV.prototype.tryAID = function() {
    for (var i = 0; i < EMV.AIDLIST.length; i++) {
        var le = EMV.AIDLIST[i];
        var aid = new ByteString(le.aid, HEX);
        var fci = this.select(aid, true);
  
        if (fci.length > 0) {
            this.cardDE[EMV.AID] = aid;
            return;
        }
    }
}


// EMV.AIDLIST:
EMV.AIDLIST = new Array();
EMV.AIDLIST[0] = { aid : "A00000002501", partial : true, name : "AMEX" };
EMV.AIDLIST[1] = { aid : "A0000000031010", partial : false, name : "VISA" };
EMV.AIDLIST[2] = { aid : "A0000000041010", partial : false, name : "MC" };
96 C: 00 A4 04 00 - SELECT Lc=6 
      0005  A0 00 00 00 25 01                                ....%.
      Le=0 
   R: SW1/SW2=6A82 (Checking error: File not found) Lr=0
96 C: 00 A4 04 00 - SELECT Lc=7 
      0005  A0 00 00 00 03 10 10                             .......
      Le=0 
   R: SW1/SW2=9000 (Normal processing: No error) Lr=42
      0000  6F 28 84 07 A0 00 00 00 03 10 10 A5 1D 50 04 56  o(...........P.V
      0010  49 53 41 87 01 01 9F 38 0C 9F 33 03 9F 1A 02 9F  ISA....8..3.....
      0020  35 01 9F 40 05 5F 2D 02 64 65                    5..@._-.de 
 
 
====================================================================

Initiate Application Process

Initiate Application Process is the next step after the Application Selection. It initiates the transaction process and provides to the card a Processing Options Data Object List (PDOL) which contains necessary data. The card returns the Application Interchange Profile (AIP) and the Application File Locator (AFL). The AIP shows which Application are supported by the card. The AFL list all files that are required for the Transaction.

Script

EMV.prototype.initApplProc = function() { // Create PDOL var data = this.getProcessingOptions(null); print(data); var tl = new TLVList(data, TLV.EMV); assert(tl.length == 1); var t = tl.index(0); if (t.getTag() == EMV.RMTF1) { // Format 1 0x80 this.cardDE[EMV.AIP] = t.getValue().left(2); this.cardDE[EMV.AFL] = t.getValue().bytes(2); } else { assert(t.getTag() == EMV.RMTF2); // Format 2 0x77 tl = new TLVList(t.getValue(), TLV.EMV); assert(tl.length >= 2); this.addCardDEFromList(tl); } }

Get Processing Options

/** * Send GET PROCESSING OPTION APDU * * */ EMV.prototype.getProcessingOptions = function(pdol) { if (pdol == null) { //var pdol = new ByteString("8300", HEX); // OTHER var pdol = new ByteString("830B0000000000000000000000", HEX); // VISA } var data = this.card.sendApdu(0x80, 0xA8, 0x00, 0x00, pdol, 0); return(data); } The Get Processin Options command initiates the transaction within the card. The card returns the AIP and AFL.
The command has the following structure:


Code Value
CLA '80'
INS 'A8'
P1 '00'; all other values are RFU
P2 '00'; all other values are RFU
Lc var.
Data PDOL related data
Le '00'

PDOL

The data the terminal should send to the card is given in the PDOL. The PDOL is stored in the FCI of the ADF and has the tag '9F38'. The PDOL only contains the expected tagname and length.
Here an example for VISA cards:
FCI: 6F [ APPLICATION 15 ] IMPLICIT SEQUENCE SIZE( 40 ) 84 [ CONTEXT 4 ] SIZE( 7 ) 0000 A0 00 00 00 03 10 10 ....... A5 [ CONTEXT 5 ] IMPLICIT SEQUENCE SIZE( 29 ) 50 [ APPLICATION 16 ] SIZE( 4 ) 0000 56 49 53 41 VISA 87 [ CONTEXT 7 ] SIZE( 1 ) 0000 01 . 9F38 [ CONTEXT 56 ] SIZE( 12 ) 0000 9F 33 03 9F 1A 02 9F 35 01 9F 40 05 .3.....5..@. // PDOL 5F2D [ APPLICATION 45 ] SIZE( 2 ) 0000 64 65 This VISA-Card needs for the transaction the following data:

Tag Name Length
'9F33' Terminal Capabilities '03'
'9F1A' Terminal Country Code '02'
'9F35' Terminal Type '01'
'9F40' Additional Terminal Capabilities '05'
The PDOL related bytestring has the tag '83', the length byte and the concatenated data from the list above without tag and length bytes as value. In this case we set the value to zero.
96 C: 80 A8 00 00 - UNKNOWN_INS Lc=13 0005 83 0B 00 00 00 00 00 00 00 00 00 00 00 ............. Le=0 R: SW1/SW2=9000 (Normal processing: No error) Lr=36 0000 77 22 82 02 78 00 94 1C 10 01 04 00 10 05 05 00 w"..x........... 0010 08 06 06 01 08 07 07 01 08 08 09 01 08 0A 0A 00 ................ 0020 08 01 04 00 The initApplProc function extract now the AIP and AFL information of the response and store them in the cardDE array. The response can have two different formats with ever tag '80' or tag '77'. In this case the data in the response have the tag '77' and will be processed by the function addCardDEFromList which stores the AIP and AFL in the cardDE array.
EMV.prototype.addCardDEFromList = function(tlvlist) { for (var i = 0; i < tlvlist.length; i++) { var t = tlvlist.index(i); print(t.getTag().toString(16) + " - " + t.getValue()); this.cardDE[t.getTag()] = t.getValue(); } }


=========================================================

Read Application Data

This function reads all data from the Application File Locator (AFL). The AFL identifies the files and records which are necessary for the transaction.

AFL

Structure

Every 4 bytes stick together.

Byte Function
1 Short File Identifier
The five most significant bits are the SFI.
The three least significant bits are set to zero.
Example:
  '10'
   00010000 >>3
=  00000010
= '02' = SFI
2 Start Record
3 End Record
4 Number of records included in data authentication beginning from the Start Record

Script


/**
 * Read application data as indicated in the Application File Locator
 * Collect input to data authentication
 *
 */
EMV.prototype.readApplData = function() {
    // Application File Locator must exist
    assert(typeof(this.cardDE[EMV.AFL]) != "undefined");
    var afl = this.cardDE[EMV.AFL];

    // Must be a multiple of 4
    assert((afl.length & 0x03) == 0);

    // Collect input to data authentication 
    var da = new ByteBuffer();

    while(afl.length > 0) {
        var sfi = afl.byteAt(0) >> 3;   // Short file identifier
        var srec = afl.byteAt(1);        // Start record
        var erec = afl.byteAt(2);        // End record
        var dar = afl.byteAt(3);         // Number of records included in
                                         // data authentication

        for (; srec <= erec; srec++) {
            // Read all indicated records
            var data = this.readRecord(sfi, srec);
            print(data);

            // Decode template
            var tl = new TLVList(data, TLV.EMV);
            assert(tl.length == 1);
            var t = tl.index(0);
            assert(t.getTag() == EMV.TEMPLATE);

            // Add data authentication input   
            if (dar > 0) {
                if (sfi <= 10) { // Only value
                    da.append(t.getValue());
                } else {  // Full template
                    da.append(data);
                }
                dar--;
            }

            // Add card based data elements to internal list
            var tl = new TLVList(t.getValue(), TLV.EMV);
            this.addCardDEFromList(tl);
        }

        // Continue with next entry in AFL
        afl = afl.bytes(4);
    }
    this.daInput = da.toByteString();
    print(this.daInput);
}
The function always extract the first 4 bytes of the bytestring. That is why the length of the AFL bytestring has to be a multiple of 4. With a read record command and the bytes from the start record to the end record will be read. If start and end record are equal, there is only one record. The records will be stored in the cardDE array without the EMV.TEMPLATE (tag: '70' and length).
The data marked by the fourth byte will be stored in the da bytebuffer. If the SFI is greater as 10, the whole record will be stored in the bytebuffer. The data in the bytebuffer will be need for dynamic data authentication.
After this the 4 bytes of the AFL bytestring will be removed. This process will be repeated untill the AFL bytestring is empty.



 


Magicard Company Logo

Biometrics


RFID















Links to some POS systems to use in your projects:

Verifone POS:
https://www.alibaba.com/trade/search?fsb=y&IndexArea=product_en&CatId=&SearchText=verifone+vx520+vx680+vx675

Verifone Latest POS devices:
https://www.verifone.com/en/us/portables-and-transportables


Ingenico POS devices:
https://www.amazon.com/s?k=ingenico  

Ingenico Latest POS devices:
https://www.ingenico.com/pos-solutions#smart-pos

mPOS devices :
https://www.alibaba.com/trade/search?fsb=y&IndexArea=product_en&CatId=&SearchText=mpos
https://dir.indiamart.com/impcat/mpos-machine.html

**NOTE:
Only purchasing POS devices is not enough for a project. You also require to purchase the software SDK & its license from the respective device vendor, which is required to develop credit/debit/giftcard application on the device.

To compare which device are best for your project:
There are many new POS system manufacturers coming up now. But I can say from my experience Verifone & Ingenico provide one of the best POS systems in the world.