When I started working on EMV support for POOM, I did not want to simply display information from a payment card. I wanted to understand the protocol from the lower layers and build enough of the communication stack for POOM to explore an EMV application by itself.
EMV may look like a payment-specific protocol, but it relies on standards that existed before EMV. One of the most important is ISO/IEC 7816-4, which defines how smart-card applications exchange commands and responses.
ISO/IEC 7816-4 uses Application Protocol Data Units, or APDUs. Instead of reading a smart card's memory directly, a reader sends commands and receives structured responses.
Each command starts with a header containing CLA, INS, P1 and P2. Depending on the command, it can also include data, its length, and the expected response length.
The response contains data and always ends with two status bytes, SW1 and SW2.
This command-response model is the foundation of the EMV implementation in POOM.
What is TLV?TLV means Tag, Length and Value.
A smart card returns many different pieces of information in the same response. A fixed binary structure would make the protocol difficult to extend, so many smart-card protocols use self-describing data objects.
A TLV object contains a tag that identifies the information, a length describing how much data follows and the value itself.
A simplified example is:
5A 08 1234567890123456
In this case, 5A is the tag, 08 represents the length and the remaining bytes contain the value.
Real EMV responses are more interesting because TLV objects can contain other TLV objects. The returned data can therefore be represented as a hierarchical structure rather than as a flat sequence of bytes.
This influenced the architecture of the POOM implementation.
Instead of searching for specific data at fixed byte offsets, I created a generic TLV parser. The EMV layer can recursively inspect constructed TLV objects and locate the information it needs.
For example, when POOM parses the payment application directory, it looks for EMV directory entries and extracts information such as the Application Identifier, Application Label and Application Priority.
This makes the implementation more flexible when different cards organize the returned information in slightly different ways.
Discovering the payment applicationA contactless EMV card does not necessarily contain only one application.
The reader first needs to discover which payment applications are available.
POOM starts by selecting the standard contactless payment directory:
2PAY.SYS.DDF01
This directory is commonly referred to as the PPSE, or Proximity Payment System Environment.
The card returns a BER-TLV structure containing the available payment applications.
POOM parses this response and extracts the Application Identifier, or AID, for each application.
The firmware also analyzes the Registered Application Provider Identifier contained in the AID.
This allows POOM to recognize several payment application families, including Visa, Mastercard, American Express, JCB, Discover/Diners, UnionPay, Interac, Cartes Bancaires, eftpos and RuPay.
Instead of presenting only a hexadecimal AID, POOM can therefore show the payment application family detected on the card.
Building an ISO 7816 layer firstOne of the main design decisions was to avoid implementing every EMV operation as an isolated hard-coded byte array.
POOM has a small ISO/IEC 7816 layer responsible for constructing commands and interpreting responses.
The EMV module uses that layer for higher-level operations.
For example, application selection is implemented using a generic ISO 7816 SELECT by DF Name command.
This separation became important because real cards do not always return a simple success response.
A card can return 6Cxx. This indicates that the command should be repeated using a corrected expected response length.
A card can also return 61xx. This indicates that additional response data is available.
POOM handles both situations automatically.
For 6Cxx, the command is repeated using the length returned by the card.
For 61xx, POOM automatically generates a GET RESPONSE APDU and continues collecting the remaining data.
This made the EMV implementation more robust than simply sending a predefined sequence of commands and assuming that every card behaves the same way.
From application selection to processing optionsSelecting an application is only the beginning of an EMV exchange.
Once an application is selected, the card may return a Processing Options Data Object List, or PDOL.
The PDOL describes which terminal-side information the card expects before continuing.
Instead of assuming a fixed set of parameters, POOM parses the PDOL and builds the requested data dynamically.
The firmware currently supports several common EMV terminal values, including amount authorised, amount other, transaction type, Terminal Verification Results, terminal serial number, merchant category code, merchant identifier, terminal identifier, POS entry mode, transaction sequence counter, merchant name, Terminal Transaction Qualifiers, terminal capabilities, terminal type, additional terminal capabilities, transaction date, transaction time, unpredictable number, terminal country and transaction currency.
One interesting example is the EMV Unpredictable Number.
Instead of inserting a fixed value, POOM generates it using the ESP32 random-number source.
The purpose of these values is not to turn POOM into a real payment terminal.
They provide enough terminal-side context to continue a controlled, read-only EMV exploration flow.
Processing EMV dataA large part of the work was not sending APDUs, but interpreting the data returned by the card.
EMV defines many different data objects, each identified by its own tag.
The POOM decoder recognizes many commonly encountered EMV objects, including the Application Identifier, Application Label, Application Interchange Profile, Application File Locator, Processing Options Data Object List, Application Transaction Counter, Cardholder Verification Method List, Application Usage Control, Application Version, CDOL1, CDOL2, DDOL, Issuer Action Codes, Issuer Application Data, Application Cryptogram, Cryptogram Information Data, CA Public Key Index, Issuer Public Key Certificate, ICC Public Key Certificate, Signed Static Application Data, Signed Dynamic Application Data, Language Preference, Log Entry and Log Format.
This allows POOM to present semantic information instead of only showing hexadecimal data.
For example, instead of displaying only:
9F36 02 0037
POOM can identify 9F36 as the Application Transaction Counter.
The raw hexadecimal representation is still useful for debugging, but the decoded representation makes protocol exploration much easier.
AIP and AFLAfter the card processes the terminal data, it can return the Application Interchange Profile and the Application File Locator.
The AIP describes capabilities supported by the application.
The AFL tells the terminal which application records can be read.
This is an important part of the EMV flow because it connects the processing-options stage with the record-reading stage.
Instead of blindly scanning records, POOM can use the information provided by the application itself to determine which records are relevant.
Reading recordsEMV applications store part of their information in records.
The records are accessed through ISO 7816 commands such as READ RECORD.
Depending on the card and application, these records can contain different EMV objects.
POOM parses the returned record templates and passes the contained objects through the same TLV decoder used in the rest of the implementation.
This means the same decoding logic can be reused whether an object was obtained during application selection, processing options or record reading.
Track data decodingSome EMV applications expose Track 1 or Track 2 equivalent data.
POOM contains decoders for both representations.
Depending on what the card exposes, the decoder can interpret information such as PAN, cardholder name, expiration date and service code.
This decoding is handled inside the EMV layer rather than directly in the user interface.
The UI therefore receives structured information while the protocol implementation remains separated from the presentation layer.
Public-key related dataAnother interesting part of EMV is the amount of cryptographic metadata carried by the card.
POOM recognizes several objects related to EMV public-key authentication, including CA Public Key Index, Issuer Public Key Certificate, Issuer Public Key Remainder, Issuer Public Key Exponent, ICC Public Key Certificate, ICC Public Key Remainder, ICC Public Key Exponent, Signed Static Application Data and Signed Dynamic Application Data.
At this stage, POOM focuses mainly on identifying and exposing these objects as part of protocol exploration.
The architecture leaves room for deeper cryptographic analysis in future versions.
Transaction-related informationThe EMV decoder also recognizes several transaction-related objects.
Examples include Application Transaction Counter, Last Online ATC, Application Cryptogram, Cryptogram Information Data, Issuer Application Data, Transaction Currency, Transaction Date and Transaction Time.
Some cards may also expose an EMV transaction log.
POOM recognizes the Log Entry and Log Format objects and can use them to understand how transaction-log records are structured when this information is available.
The presence and accessibility of these records depend on the card and application.APDU capture
While developing the EMV implementation, I wanted to preserve the raw communication as well as the decoded information.
For that reason, the EMV module contains an APDU capture system.
For every exchange, POOM can store the command APDU, the response APDU, the command length, the response length and the transport status.
This makes it possible to inspect the complete conversation between POOM and the card.
A session can contain exchanges such as SELECT PPSE, SELECT AID, GET PROCESSING OPTIONS, READ RECORD and GET DATA.
For development and debugging, this is extremely useful.
If the high-level interface reports an AIP, an AFL or an ATC, I can still return to the original APDU response and verify where that information came from.
This turned the EMV feature into more than a card-information screen.
It also became a small portable protocol analyzer.Why I implemented it this way
The most interesting part of implementing EMV was discovering that it is not one monolithic protocol.
The final behavior comes from several layers working together: NFC communication, ISO 14443-4/ISO-DEP, ISO/IEC 7816 APDUs, APDU status handling, BER-TLV encoding, EMV application discovery, PDOL processing, processing options, AFL-based record reading and EMV data interpretation.
Understanding these layers influenced the firmware architecture.
Instead of creating one function that sends a fixed sequence of payment-card commands, POOM now has reusable components for ISO 7816 command construction, response parsing, status-word handling, TLV decoding, payment application discovery, EMV object decoding and APDU tracing.
This also makes the lower layers useful beyond EMV.
The ISO 7816 and TLV components can potentially be reused later to explore other smart-card applications.
Exported EMV Card ReportWhen POOM reads an EMV card, it can export a complete report containing the detected card information and the communication session.
The exported report includes the payment application, decoded EMV data objects, application capabilities, cardholder verification information, public-key related data, transaction-related information and the APDU exchanges captured during the read process.
The following example shows the information exported by POOM after a successful EMV read.
Filetype: POOM NFC device
Version: 2
Device type: EMV
Summary: Credito
UID: 05805422229200
ATQA: 4400
SAK: 20
ATS: 0D78007002534C4A0130502310
AID: A0000000041010
Read status: complete
Scheme: Mastercard
Kernel hint: Kernel 2 family (expected)
GPO: ok
AFL: presentApplication Information
Application label: Mastercard
Application name: Credito
Cardholder name:
PAN: 5451 **** **** 8308
AIP: 19 80
AIP decoded: TRM, Issuer auth
Expiration date: 26 04 30
Effective date: 23 09 14
Country code: 0218
Currency code: 0840
PAN sequence number (5F34): 00
Service code: 201Application Usage and CVM
Application version number (9F08): 0002
Application usage control (9F07): FF00
Application usage decoded:
Dom cash, Intl cash, Dom goods, Intl goods,
Dom services, Intl services, ATM, Non-ATM
CVM list (8E):
00000000000000001E0342031F03
CVM methods decoded:
Signature, Online PIN, No CVMData Object Lists
CDOL1 (8C):
9F02069F03069F1A0295055F2A029A039C019F37049F35019F45029F4C089F34039F21039F7C14
CDOL1 decoded:
Amt, Other, Country, TVR, Currency, Date, Type,
UN, Term type, Auth code, ICC dyn no,
CVM result, Time, Customer
CDOL2 (8D):
910A8A0295059F37049F4C08
CDOL2 decoded:
91, 8A, TVR, UN, ICC dyn noPublic-Key Related Data
CA public key index (8F): 06
Issuer public key certificate (90): present, 248 bytes
Issuer public key exponent (9F32): 03
ICC public key certificate (9F46): present, 176 bytes
ICC public key exponent (9F47): 03
SDA tag list (9F4A): 82Transaction Log
Transaction count: 10
Transaction 1:
ATC=380
Amount=4402
Currency=0840
Date=260502
Time=083233
Transaction 2:
ATC=379
Amount=5000
Currency=0840
Date=260501
Time=112044APDU Example
[APDU capture excerpt]
01 SELECT PPSE
C-APDU: 00A404000E325041592E5359532E444446303100
R-APDU: 6F2F840E325041592E5359532E4444463031A51DBF0C1A61184F07A0000000041010500A4D6173746572636172648701019000
Status: 9000 (success)
02 SELECT MASTERCARD APPLICATION
C-APDU: 00A4040007A000000004101000
R-APDU: 6F438407A0000000041010A538500A4D6173746572636172648701015F2D066573656E70749F1101019F12074372656469746FBF0C0F9F4D020B0A9F6E07021800003030009000
Status: 9000 (success)
03 GET PROCESSING OPTIONS
C-APDU: 80A8000002830000
R-APDU: 770E82021980940810010101200103009000
Status: 9000 (success)
04 READ RECORD
C-APDU: 00B2011400
R-APDU: [redacted: card and track data]
Status: 9000 (success)
05-21 Additional record and data reads
Responses containing card or transaction details omitted.Purpose of the feature
The purpose of the POOM EMV module is protocol exploration, interoperability testing and security research.
POOM does not attempt to perform a real payment transaction.
The implementation is intended for cards and systems that the user is authorized to examine.
The main objective is to make the structure of an EMV exchange visible directly on a portable embedded device, from the first APDU to the final decoded data objects.
Try It Yourself with POOM LabsTry It Yourself with POOM Labs
This project is only one part of what can be explored with POOM.
If you want to understand what happens before EMV at the NFC protocol level, POOM Labs provides guided exercises that start from concepts such as REQA and ATQA and continue through practical card communication.
Start exploring here:









Comments