Examining Your EMV Chip Cards
Now we are a few years into EMV mandates in the US, we all have one or more EMV chip cards in our wallet and have used them in stores.
In the old days, the curious bunch bought magnetic card readers to see what’s encoded in the mag stripe. These mag card readers, and many of the similar used in restaurants and stores, simply emulate keyboard input, so what's read when a card is swiped is sent through keyboard I/O to the operating system. Thus, opening Notepad allows us to see what's in the mag stripe.
Hardware
Payment card footprint is ISO/IEC 7810 ID-1 standard. Payment card with Chip is conforming to ISO/IEC 7816, which is also called a Smart Card. Some of the professional grade laptops come with a built-in smart card slot (for access cards), but any USB smart card reader will do. For example, this one for $15. Most of them work with Windows and Mac, but if you are on Linux, chances are they will also work, but you might want to dig a little deeper.
Software
You can certainly write your own software to interact with the reader. Or you can download and use free Smart Card Shell from CardContact Developer Network. You can get access to their git repository if you register with their developer network and store the access key in a SmartCard HSM.
Smart Card Shell is written in Java, so you want to have a JRE on your computer. The latest OpenJDK 14 works smoothly.
Once installed, there are 2 ways to run the shell. scsh3 (or scsh3.cmd) runs the shell in a command line console; scsh3gui (or scsh3gui.cmd) runs a simple GUI which has a a nice "trace" tab that logs not only what you explicitly print in your script, but also the raw interaction with the card.
Since we are interested in EMV, Smart Card Shell also provides EMV abstraction library to work with them. You can git clone or download the scripts from https://github.com/CardContact/scsh-scripts
Now, insert an EMV chip card into your smart card reader, fire up the shell, and load the emv/dump.js script (make sure you have the right path to where the script is):
>load("scripts/emv/dump.js");
Congratulations! Now you have successfully peeked into your EMV card!
A Little Deep Dive
Let's look at dump.js
load("emv.js"); load("emvView.js");
emv.js abstracts the operations supported by EMV, emvView.js pretty formats the data for display.
var card = new Card(_scsh3.reader); card.reset(Card.RESET_COLD);
Card is what Smart Card Shell provides as an abstraction to interact with smart cards. RESET_COLD is to power off and on to the card.
e.selectPSE(false); var aid = e.getAID(); if (aid != null) { e.selectADF(aid); } else { e.tryAID(); }
The very first step of an EMV processing is to select a Payment Service Envrionment (PSE). In general, there are contact and contactless environments. Since we are using a card reader which by definition is contact, selectPSE() with false to indicate it's not contactless.
An EMV card may support one or many "Applications" which are denoted by Application ID (AID). For example, Visa Credit has an AID, Visa Debit has a different AID, MasterCard has many AIDs for different products, etc. On a single card, it can support multiple AIDs, for example, both credit and debit; multiple AIDs are priorized. Terminals have supported AIDs as provisioned by acquirers. So this is a handshake for the terminal and card to agree on which AID to process on. The complete list of AIDs can be found here. The sample script that simulates a terminal supports 3 AIDs, which can be found in emv.js:
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" };
Each AID has specific File Control Information (FCI), which can be retrieved from card. FCI denotes how terminals can read the application data from the card. This can be seen from the tryAID() function in emv.js:
var fci = this.select(aid, true); if (fci.length > 0) { this.cardDE[EMV.AID] = aid; this.decodeFCI(fci); }
Card can also decide which data are required from terminal before terminals start to read application data. Terminals format these Processing Data Object List (PDOL) and send them to cards in Get Processing Options operation. This is done in initApplProc() function in emv.js:
var pdol = this.cardDE[EMV.PDOL]; var pdolenc = null; if (typeof(pdol) != "undefined") { pdolenc = this.createDOL(pdol); var length = pdolenc.length var length = length.toString(HEX); if (pdolenc.length <= 0xF) { length = "0".concat(length); } var length = new ByteString(length, HEX); pdolenc = new ByteString("83", HEX).concat(length).concat(pdolenc); print(pdolenc); } var data = this.getProcessingOptions(pdolenc);
Get Processing Options returns Application Interchange Profile (AIP), which processing steps are supported (card authentication, cardholder verification, etc.) for this transaction.
Now, the terminal can read the application data from the card. Application File Locator (AFL) has the instruction on how to read the data. AFL also indicates which data read are used in Data Authentication (DA) process. These are encoded in the 4 bytes for every Short File Identifier (SFI) inside AFL. This is in emv.js:
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("Record No. " + 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--; }
At this point, we have all the code needed to read application data from EMV cards!
Examining Application Data
Let's go through the output.
<----------------------------Display Data Elements----------------------------- Application Identifier (AID) - card: A000000025010801 Application Label: 414D45524943414E2045585052455353 - AMERICAN EXPRESS Track 2 Equivalent Data (Magnetic Strip): Primary Account Number: 3712*******1009 Expiration Date (YYMM): 2010 Service Code: 201 Discretionary Data: 15107427500000 Application Primary Account Number (PAN): 3712*******1009F
This part shows my American Express card, its AID, the track 2 data (track 2 is what's normally encoded in the mag stripe of a card, and is what's being transmitted for processing), and my PAN. Note I masked mine, but you should see the full PAN.
Application Interchange Profile: 3C00 Byte 1: DDA supported (b6) Cardholder verification is supported (b5) Terminal risk management is to be performed (b4) Issuer authentication is supported (b3) Byte 2:
AIP data here:
- Dynamic Data Authentication (DDA using 3 layers of RSA key pairs including one for the card itself) is supported, but not Static Data Authentication (SDA only CA and Issuer key pairs) for weak security
- Cardholder Verification Methods (CVM) are supported (we will see what methods next)
- Terminal Risk Management can make decisions on its own, ie. offline, to 1) force a transaction to go online; 2) check if recent transaction amounts exceed a floor limit set on the card; 3) if velocity exceeds a threshold set on the card. For the latter 2, terminal can reject the transactions without consulting issuers or networks
- Issuer Authentication is where Issuer, after authorizes a transaction, sends authorization result as well as an application cryptogram called ARPC (Application ResPonse Cryptogram) back to terminal. The terminal can, if Issuer Authentication is supported on card as indicated by AIP, ask the card to verify the ARPC using the secret key the card shares with issuer.
Application Priority Indicator: 01
This selected AID has the highest priority, if there are multiple AIDs matching between terminal and card.
Card Risk Management Data Object List 1 (CDOL1): 9F02069F03069F1A0295055F2A029A039C019F3704 9f02 - 6 - Authorised amount of the transaction (excluding adjustments) 9f03 - 6 - Secondary amount associated with the transaction representing a cashback amount 9f1a - 2 - Terminal Country Code 95 - 5 - Terminal Verification Results 5f2a - 2 - Transaction Currency Code 9a - 3 - Transaction Date 9c - 1 - Transaction Type 9f37 - 4 - Unpredictable Number Card Risk Management Data Object List 2 (CDOL2): 8A029F02069F03069F1A0295055F2A029A039C019F3704 8a - 2 - Authorisation Response Code 9f02 - 6 - Authorised amount of the transaction (excluding adjustments) 9f03 - 6 - Secondary amount associated with the transaction representing a cashback amount 9f1a - 2 - Terminal Country Code 95 - 5 - Terminal Verification Results 5f2a - 2 - Transaction Currency Code 9a - 3 - Transaction Date 9c - 1 - Transaction Type 9f37 - 4 - Unpredictable Number
Card Risk Management Data Object List (CDOL) are the data elements needed to generate Application Cryptogram (AC). CDOL1 is the requirement to generate Application ReQuest Cryptogram (ARQC) by card and sent to issuer for authorization; CDOL2 is the requirement to generate Application ResPonse Cryptogram (ARPC) by issuer and returned in authorization message.
Cardholder Verification Method (CVM) List: 000000000000000042011E031F0200000000000000000000 Apply succeeding CV Rule if this CVM is unsucccessful Enciphered PIN verified online If unattended cash Fail cardholder verification if this CVM is unsuccessful Signature (paper) If terminal supports the CVM Fail cardholder verification if this CVM is unsuccessful No CVM required If not unattended cash and not manual cash and not purchase with cashback Fail cardholder verification if this CVM is unsuccessful Fail CVM processing Always
Cardholder Verification Methods (CVM) is a prioritized list of rules.
For example, the first rule says if this card is used in an unattended cash transaction, require encrypted PIN online, if it fails, not the end of the world, try the next verification method that's applicable. The next one in line is "Signature (paper)" if terminal supports it. But most likely an unattended cash transaction wouldn't have the signature capability, for unattended cash, it will likely skip it. The next one is "No CVM equired" but the condition explicitly excludes unattended cash. The final one is always "Fail CVM processing". So, in nutshell, for unattended cash transaction, one has to successfully pass online encrypted PIN verification.
If the transaction is credit card in store, it will activate "Signature (paper)" rule, the terminal will print a receipt with signature line, and instructs the store clerk to obtain customer signature.
If the transaction is credit card without cashback at a vending machine, it will activate "No CMV Required" rule, which doesn't need cardholder verification.
Certification Authority Public Key Index: 0F Issuer Public Key Certificate: B0A3DCCD60AEEE9EEF61209A655F2E9646B8E8B8FF0F3315CE61BB942702F7D0ED9E6D512AD92D4AD8480B926553926EE50EF47B17E4428A778E7E7EA1C933FD03272D29B8D07E4C54928F169B672242524383A60836A04A70489F8B7AFA70AFD4C989A6BD1A0E25D7B4521D7D08920FC45E087375BEBD4AC04949A101C0A131CBDE121F7FE7E7A0E9730B9A5D0CE730C359D960420DDA241788D6BEE14D663D29176C9367D215B149208E2AF5D94099 Issuer Public Key Remainder: 24E5B52B Issuer Public Key Exponent: 03 Application Currency Code: 0840 ICC Public Key Certificate: 83A1898AF7DE8CD7F8FD7BF008A17FB9612158DC1189EC4EF897BFD99271DAD2DD62087958C44FCA05DC069D6E3555BBA4A89B01ED089BC6796E93E2069574EF416F3C9C622D39B2C60A544E7B44F5FA1DD94AA84C6D47FB4C31A71FC5249AAD1DD5891C01BF5FB8E3EA620D6CA6519274F392B431E3F85ACBABBE60CDE3D8CE5ACABAEA5626540B2B79923D222914F8 ICC Public Key Exponent: 03 ICC Public Key Remainder: C14D885E3ADAC2431E49 Dynamic Data Authentication Data Object List (DDOL): 9F3704 9f37 - 4 - Unpredictable Number Static Data Authentication Tag List: 82
Certification Authority (CA) Public Keys are loaded on terminals by acquirers. CA in EMV context are card schemes (Visa, MasterCard, AMEX, etc.), each can have multiple public keys. Therefore an index is needed to indicate which public key is used to provision this card. The full list of CA public keys can be found here.
CA Public Key is used by terminal to restore Issuer Public Key from the Issuer Public Key Certificate.
The data structure holding Issuer Public Key is often too small for the complete key, therefore, the remainder in Issuer Public Key Remainder needs to be concatenated to the restored Issuer Public Key for completeness.
Similarly, for cards that support offline Dynamic Data Authentication, the ICC Public Key is also embedded in the card in the format of ICC Public Key Certificate. Issuer Public Key is used to restore ICC Public Key from ICC Public Key Certificate.
Similarly, ICC Public Key Remainder contains the overflow of the key.
Dynamic Data Authentication Data Object List (DDOL) denotes which data elements need to be used to run a Dynamic Data Authentication. In this case it's an unpreditable (random) number.
Static Data Authentication Tag List is the piece of original data together with ICC Public Key that are signed into the ICC Public Key Certificate. It is needed to verify if the ICC Public Key Certificate is authentic.
Application File Locator: 0801010008020201080405001002020018030300 SFI: 1 First/Only Record Number: 1 Last Record Number: 1 Number of records involved in offline data authentication: 0 SFI: 1 First/Only Record Number: 2 Last Record Number: 2 Number of records involved in offline data authentication: 1 SFI: 1 First/Only Record Number: 4 Last Record Number: 5 Number of records involved in offline data authentication: 0 SFI: 2 First/Only Record Number: 2 Last Record Number: 2 Number of records involved in offline data authentication: 0 SFI: 3 First/Only Record Number: 3 Last Record Number: 3 Number of records involved in offline data authentication: 0
AFL indicates how to read application data from the card, and which ones are used in data authentication (see above)
Application Usage Control: FF00 Byte 1: Valid at terminals other than ATMs Valid at ATMs Valid for international services Valid for domestic services Valid for international goods Valid for domestic goods Valid for international cash transactions Valid for domestic cash transactions Byte 2:
The card also dictates which use cases are supported. If a terminal's use case isn't supported in this list, terminal should fail the transaction.
Further Experiment
A sample script doemv.js is also included in the git repository. This script not only dumps the data from EMV cards, but also attempts to
- do a Static Data Authentication (SDA)
- do a Dynamic Data Authentication (DDA)
- generate an Application Cryptogram (AC)
Note that many new EMV cards do not support SDA (like mine). If your dump of AIP says only DDA is supported, please comment out the SDA code invocation in doemv.js:
//d.verifySSAD(issuerPublicKeyModulus);
Also important, the CA Public Keys stored in git repository are incomplete, in fact, it only contains a subset of Visa public keys. So in order to support your card, you may need to supplement it with the public key needed by your card.
To find which CA public key is needed, add a debug print in dataAuthentication.js to print out rid and index:
DataAuthentication.prototype.getSchemePublicKey = function() { var rid = this.getRID(); var index = this.getPubKeyIndex(); print("rid="+rid+", index="+index);
Then look up the CA Public Key here by rid and index. For example, my AMEX card's rid is A000000025 and index is 0F, so the missing public key is C8D5AC27A5E1FB89978C7C6479AF993AB3800EB243996FBB2AE26B67B23AC482C4B746005A51AFA7D2D83E894F591A2357B30F85B85627FF15DA12290F70F05766552BA11AD34B7109FA49DE29DCB0109670875A17EA95549E92347B948AA1F045756DE56B707E3863E59A6CBE99C1272EF65FB66CBB4CFF070F36029DD76218B21242645B51CA752AF37E70BE1A84FF31079DC0048E928883EC4FADD497A719385C2BBBEBC5A66AA5E5655D18034EC5, and key length is 1408.
Add a new XML inside schemepublickey directory (this directory is in parallel to emv.js), similar to the Visa public key XMLs already there. Make sure you replace the followings correctly:
- <gp:Component Name="MODULUS" Encoding="HEX" Value=""> The value here is the public key looked up above.
- <gp:KeyInfo Name="RSAPublic" Type="PUBLIC" SubType="RSA" Size="" Mode="PROD"/> The size here is the key length above.
Then, in doemv.js, add the new XML to the public key list:
var d = new DataAuthentication(e); d.addSchemePublicKey(new ByteString("A000000003", HEX), 1, new Key("schemepublickeys/kp_visa_1024_01.xml")); d.addSchemePublicKey(new ByteString("A000000003", HEX), 7, new Key("schemepublickeys/kp_visa_1152_07.xml")); d.addSchemePublicKey(new ByteString("A000000003", HEX), 8, new Key("schemepublickeys/kp_visa_1408_08.xml")); d.addSchemePublicKey(new ByteString("A000000003", HEX), 9, new Key("schemepublickeys/kp_visa_1984_09.xml")); ... ... ...
Further Reading
What's illustrated and explained in this article is the tip of an iceberg. EMV specification is gigantic and complicated and sometimes confusing.
Here are some useful links:
- Ber-TLV message encoding used in EMV
- TLV Parser
- EMV TLV tag list
- APDU Application Protocol Data Unit command format
- EMV Acronym and Glossary
Have fun!