Smart Card Debugging Techniques

<\/script>\n
'; }, get iframeSnippet() { const domain = '{ SITE_DOMAIN }'; const type = '{ embed_type }'; const slug = '{ embed_slug }'; return ''; }, get activeSnippet() { return this.method === 'script' ? this.scriptSnippet : this.iframeSnippet; }, copySnippet() { navigator.clipboard.writeText(this.activeSnippet).then(() => { this.copied = true; setTimeout(() => { this.copied = false; }, 2000); }); } }" @keydown.escape.window="open = false" @click.outside="open = false">

Embed This Widget

Theme


      
    

Widget powered by . Free, no account required.

Debugging smart card applications: APDU tracing, status word analysis, remote debugging, and common error patterns.

| 5 min read

Smart Card Debugging Techniques

Smart card debugging is fundamentally different from conventional software debugging: the card executes code inside a tamper-resistant boundary with no console output, limited error codes, and strict communication timing. Effective debugging relies on APDU tracing, protocol analysis, and specialised tools that expose what the card is doing without requiring physical access to the chip internals.

Use the APDU Builder to construct test commands and examine expected vs actual responses without writing any code.

APDU Tracing

The primary debugging primitive is tracing every APDU command and response pair. Any PC/SC middleware trace exposes the raw bytes:

Linux — pcsc-spy:

# Start trace daemon
sudo pcsc-spy &
# Run your application
java -jar myapp.jar
# Stop and read trace

GlobalPlatformPro verbose mode:

java -jar gp.jar --list --verbose --debug 2>&1 | tee trace.log
# Output includes:
# SND: 00A40400 07 D276000085010100
# RCV: 9000

pyscard debug hook:

from smartcard.CardMonitoring import CardMonitor, CardObserver

class APDULogger(CardObserver):
    def update(self, observable, actions):
        (addedcards, removedcards) = actions
        for card in addedcards:
            print("Card inserted ATR:", toHexString(card.atr))

monitor = CardMonitor()
monitor.addObserver(APDULogger())

Status Word Decoding

Every APDU response ends with a two-byte Status Word (SW1 SW2). The first step in debugging any failure is decoding the SW:

SW Meaning Debug Action
9000 Success Normal
6700 Wrong length Check Lc/Le bytes in command
6982 Security status not satisfied Verify PIN/authentication state
6983 Authentication method blocked PIN retry counter exhausted
6985 Conditions of use not satisfied Check lifecycle state, key version
6A82 File or application not found Verify AID or file path
6A86 Incorrect parameters P1/P2 Check command reference
6CXX Wrong Le; XX = correct length Resend with Le=XX
61XX More data available; GET RESPONSE with Le=XX Chain GET RESPONSE commands

For JavaCard applets, ISOException.throwIt(SW_WRONG_LENGTH) maps directly to 6700. Use a reference like GlobalPlatform Card Spec or ISO/IEC 7816-4 Table 5 for the full SW table.

Protocol Analysers

For hardware-level debugging, a protocol analyser intercepts the electrical signals between reader and card:

Tool Type Capability
Total Phase Beagle USB 480 USB analyser PC/SC USB trace with APDU decode
HHD Device Monitoring Studio Software Windows PC/SC trace, APDU decode
Bluetooth Sniffer (for contactless) RF ISO 14443 layer 3/4 decode
Riscure Inspector HW side-channel Power traces, EM, fault injection

For T=0 and T=1 contact protocol analysis, a logic analyser (Saleae Logic Pro) with ISO 7816 decoder can verify clock rate (fd ratio), guard time, and block timing — useful when a card intermittently fails on timing-sensitive operations.

JCOP Debugger (Eclipse)

NXP JCOP Tools for Eclipse provides a software simulator with step-through debugging for JavaCard applets:

  1. Set a breakpoint in your applet's process() method.
  2. Launch the JCOP simulator in debug mode.
  3. Send an APDU via the Script Editor panel.
  4. The debugger pauses at the breakpoint, exposing local variables, the APDU buffer (apdu.getBuffer()), and the card's internal state.

The simulator does not replicate timing or cryptographic execution time, so side-channel behaviour cannot be tested in simulation. Always validate timing-sensitive operations on physical hardware.

JavaCard Exception Tracing

JavaCard applets cannot write to a console, but you can encode debug state into a custom SW:

// Debug helper: encode internal state into SW2
private void debugThrow(short state) {
    ISOException.throwIt((short)(0x6F00 | (state & 0x00FF)));
}
// Caller decodes SW 0x6F01, 0x6F02... to identify failure point

Remove all debug SWs before production deployment — they leak internal state.

Memory Leak Detection (EEPROM)

EEPROM writes are a finite resource on most smart card chips (typically 500,000–1,000,000 write cycles). Track EEPROM usage during development:

// JavaCard: check available persistent memory
short eepromAvail = JCSystem.getAvailableMemory(JCSystem.MEMORY_TYPE_PERSISTENT);
// Write usage to a RAM buffer for inspection via a debug GET DATA command

Excessive EEPROM writes in loops are a common bug that causes premature card failure. Prefer transient arrays (JCSystem.makeTransientByteArray()) for intermediate state.

Common Debugging Scenarios

Symptom Likely Cause Investigation
6985 on first command Applet not selected or wrong lifecycle Send SELECT AID first
Intermittent 6F00 EEPROM write failure or power glitch Check write counter; test with stable power
Reader timeout Card stuck in long crypto op Profile RSA/ECC operations in simulator
6700 on GET RESPONSE Le calculation wrong Inspect SW 61XX chain length

See the Dev Environment Setup Guide for initial reader and middleware configuration, and the Smart Card Testing Framework for systematic test suite approaches.

Frequently Asked Questions

Our guides cover a range of experience levels. Getting Started guides introduce smart card fundamentals. Security guides address Common Criteria certification and key management. Programming guides target developers working with APDU commands, JavaCard applets, and GlobalPlatform card management.