Lesson 6. Personal data and the try counter: the card checks the PIN

In pictures

After this lesson the card knows its account number and PIN. A wrong PIN — the card counts the mistakes; three in a row and it is blocked for good, and neither the right PIN nor "take it out and put it back" helps.


6.1. The idea: the identity is in transistors

All cards have the same program, but each has its own identity: account number, PIN and secret key. They lie in the matrix from lesson 3: a transistor = bit 1. Row pr is a byte, column pb is a bit. The whole "identity" of card 1 is 22 transistors.

The PIN is written in binary-coded decimal: each digit is 4 bits, 12 → 0001 0010.

VCCbitpb0pb1pb2pb3pb4pb5pb6pb7pr0acct01pr1PIN 1–212pr2PIN 3–434pr3key 15Apr4key 2C3pr5key 317pr6key 48Edashed — GND0pq01pq10pq20pq31pq40pq50pq60pq7= 12
The personality of card 1 is 22 transistors. Resistors on top hold the columns at 1, in each byte row a transistor sits where the bit is 1, NOT gates below. Row pr1 is read (address 17, the first PIN digits): its transistors pulled pb4 and pb1 — the output is 0001 0010 = "12".

6.2. The idea: tries that are not erased

Two flip-flops try0, try1 count wrong PINs in a row. Reset RST does not touch them — otherwise "take it out and put it back" would give three tries again. Only "factory preparation" clears them — pin C6 (FAC): once a programming voltage was applied to it.

On real cards the PIN can be changed. It is not in a "hard-wired" matrix but in EEPROM — memory that can be rewritten and that keeps data without power. At an ATM you enter the old PIN and the new one, the bank sends the card a "replace the PIN" command signed with its key — and the card rewrites it itself. The bank unblocks a card after three mistakes the same way. Sometimes it is not the card that checks the PIN but the bank: then the card does not store it at all. Our PIN is hard-wired in transistors, like on the very first chip cards — it can be changed only by rewiring the matrix (lesson 8).

6.3. Building

The same project as in lesson 5.

And second: the card counts wrong PINs by itself. Three mistakes in a row — blocked for good; neither a reset nor the right PIN helps. The program does it, and two flip-flops that the reset does not touch remember it.

Step 1. The try counter and factory preparation

Two flip-flops try0, try1 count wrong PINs in a row: 0–3, at 3 the card is blocked. The program writes them (ST 24) and reads them (LD 24). Reset RST does not touch them — otherwise "take out and put back" would give three tries again. Only switch FAC clears them — pin C6, "factory preparation": once a programming voltage was applied to it. Put the FAC switch on the right, next to RST and the adapter (outside the future chip).

PartPinLabel
Input (switch)outFAC
NOTI0
O0
FAC
nFAC
ANDI0
I1
O0
oST
selTRY
wTRY
RBITD
LD
nR
CLK
Q
acc0
wTRY
nFAC
CLK
try0
RBITD
LD
nR
CLK
Q
acc1
wTRY
nFAC
CLK
try1

Step 2. Personal data: the matrix transistors

Card 1: account 01, PIN 1234, key 5A C3 17 8E. A transistor = bit 1: gate — row pr<n> (the byte at address 16 + n), drain — column pb<k> (bit k), source — GND. The card's whole "identity" is these 22 transistors:

AddressWhatHexBits 7…0Row transistors (columns)
16 ($10)account number010000 0001pb0
17 ($11)PIN, digits 1–2120001 0010pb4, pb1
18 ($12)PIN, digits 3–4340011 0100pb5, pb4, pb2
19 ($13)key, byte 15A0101 1010pb6, pb4, pb3, pb1
20 ($14)key, byte 2C31100 0011pb7, pb6, pb1, pb0
21 ($15)key, byte 3170001 0111pb4, pb2, pb1, pb0
22 ($16)key, byte 48E1000 1110pb7, pb3, pb2, pb1

The PIN is written in binary-coded decimal: each digit is 4 bits (12 → 0001 0010).

PartPinLabel
nmosgate
drain
source
pr0
pb0
GND
nmosgate
drain
source
pr1
pb1
GND
nmosgate
drain
source
pr1
pb4
GND
nmosgate
drain
source
pr2
pb2
GND
nmosgate
drain
source
pr2
pb4
GND
nmosgate
drain
source
pr2
pb5
GND
nmosgate
drain
source
pr3
pb1
GND
nmosgate
drain
source
pr3
pb3
GND
nmosgate
drain
source
pr3
pb4
GND
nmosgate
drain
source
pr3
pb6
GND
nmosgate
drain
source
pr4
pb0
GND
nmosgate
drain
source
pr4
pb1
GND
nmosgate
drain
source
pr4
pb6
GND
nmosgate
drain
source
pr4
pb7
GND
nmosgate
drain
source
pr5
pb0
GND
nmosgate
drain
source
pr5
pb1
GND
nmosgate
drain
source
pr5
pb2
GND
nmosgate
drain
source
pr5
pb4
GND
nmosgate
drain
source
pr6
pb1
GND
nmosgate
drain
source
pr6
pb2
GND
nmosgate
drain
source
pr6
pb3
GND
nmosgate
drain
source
pr6
pb7
GND

Step 3. The program in the ROM

⚙ on ROM → button ⬆ → file 06-pin.rom.json — the card's program without the cipher. After a reset the card sends the greeting $3B (59) by itself, then waits for a command:

Send (switches T)Answer (lamps)What
N (78)account numbercommand "number"
P (80), then 2 PIN bytes144 ($90)
98 / 97 ($62 / $61)
96 ($60)
PIN correct
wrong, 2 / 1 tries left
card blocked
anything else109 ($6D)no such command
; Lesson 6 — the card checks the PIN: the card's program without the cipher (challenge-response is lesson 7).; One for all cards; the personal part is in the permanent memory $10–$17.; Every command is exactly one clock, so the bit length on the IO line is counted in commands: P = 16 clocks.;; Talking to the terminal:;   reset            → $3B (a greeting, like the first ATR byte of real cards);   'N'              → account number;   'P' PIN1 PIN2    → $90 correct · $62/$61 wrong (tries left) · $60 card blocked; (lesson 7) 'A' C1 C2 → R1 = first byte of cipher(challenge, key) — only after a correct PIN; otherwise $69;   (lesson 7) 'R'   → R2 = second byte of the answer (like GET RESPONSE of real cards: an answer longer than a byte —;                      the terminal takes the rest with a separate command; each byte is visible on the adapter lamps);   anything else    → $6D (no such command) — in this lesson also 'A', 'R' ; --- RAM (8 bytes) ---.equ B    $00      ; byte: received / sent.equ N    $01      ; bit counter.equ D    $02      ; delay counter.equ H    $03      ; first argument byte / high byte of the cipher.equ L    $04      ; second argument byte / low byte of the cipher.equ OK   $05      ; 1 = PIN is correct in this session; --- permanent memory (on transistors) ---.equ ACC  $10      ; account number.equ PINH $11      ; PIN, digits 1–2.equ PINL $12      ; PIN, digits 3–4.equ K0   $13      ; key, 4 bytes.equ K1   $14.equ K2   $15.equ K3   $16; --- try register and port ---.equ TRY  $18      ; wrong tries in a row (3 = blocked).equ IN   $1C      ; bit 0 = the IO line.equ OUT  $1D      ; bit 0 = 1 → pull the line to 0 start:  LD #0        ST OK            ; after a reset the PIN is not entered again        ST OUT           ; let go of the line        LD #$3B        ST B        CALL tx          ; greeting loop:   CALL rx          ; command        LD B        CMP #'N'        JZ cmdN        CMP #'P'        JZ cmdP        LD #$6D        JMP reply cmdN:   LD ACC        JMP reply  ; --- PIN check ---cmdP:   CALL rx        LD B        ST H        CALL rx        LD B        ST L        LD #0        ST OK            ; a new try — the earlier correct PIN does not count        LD TRY        CMP #3        JZ blocked        LD H        CMP PINH        JNZ wrong        LD L        CMP PINL        JNZ wrong        LD #0        ST TRY           ; correct: the try counter goes to zero        LD #1        ST OK        LD #$90        JMP replywrong:  LD TRY        ADD #1        ST TRY        LD #3        SUB TRY          ; how many tries are left        OR #$60        JMP replyblocked: LD #$60        JMP reply reply:  ST B        CALL tx        JMP loop ; --- receiving a byte: wait for the start bit, then 8 bits top first, one every 16 clocks ---rx:     LD IN        AND #1        JNZ rx           ; line is 1 — wait        LD #8        ST N        .rept 10         ; get to the middle of the first bit        NOP        .endrrxbit:  NOP        NOP        NOP        NOP        NOP        LD B        ADD B            ; shift B left        ST B        LD IN            ; ← here we read the bit        AND #1        ADD B        ST B        LD N        SUB #1        ST N        JNZ rxbit        ; the loop is exactly 16 clocks        LD #6        ST Drxg:    LD D             ; guard: wait out the terminal's stop bit (2 + 6 × 4 = 26 clocks)        SUB #1        ST D        JNZ rxg        RET ; --- sending byte B: start 0, 8 bits top first, stop 1 ---tx:     LD #1        ST OUT           ; start bit        .rept 7        NOP        .endr        LD #8        ST Ntxbit:  LD B        ADD B            ; top bit → C        ST B        LD #0        ADC #0           ; A = C        XOR #1           ; bit 1 → do not pull, 0 → pull        ST OUT           ; ← here the bit goes out on the line        NOP        NOP        NOP        NOP        NOP        LD N        SUB #1        ST N        JNZ txbit        ; the loop is exactly 16 clocks        NOP        NOP        NOP        NOP        NOP        LD #0        ST OUT           ; stop bit        LD #8        ST Ddly:    LD D             ; guard interval: 2 + 8 × 4 = 34 clocks        SUB #1        ST D        JNZ dly        RET

6.4. Checking

Go down the rows from top to bottom: one row is one action. After SEND wait until the "exchange" lamp goes off (lamp), and compare with the "Lamps" column. Command P is three transmissions in a row: the letter P itself and the two halves of the PIN.

№What to doLamps (● lit)What it is
1Clock — MAX (click on the body)
2switch FAC and RST on, wait a second, switch both off
3do not touch anything, look at the lamps○○●●●○●● 59the card said hello: $3B
4switches T7…T0 = 0100 1110, press SEND○○○○○○○● 1N — account number: 1
5switches T7…T0 = 0101 0000, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
6switches T7…T0 = 0001 0010, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
7switches T7…T0 = 0011 0100, press SEND●○○●○○○○ 144P 12 34 — PIN correct ($90)
8switches T7…T0 = 0101 0000, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
9switches T7…T0 = 0001 0001, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
10switches T7…T0 = 0001 0001, press SEND○●●○○○●○ 98P 11 11 — wrong, 2 tries left ($62)
11switches T7…T0 = 0101 0000, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
12switches T7…T0 = 0010 0010, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
13switches T7…T0 = 0010 0010, press SEND○●●○○○○● 97P 22 22 — wrong, 1 left ($61)
14RST on and off ("took the card out and put it back")○○●●●○●● 59the greeting again: the card restarted
15switches T7…T0 = 0101 0000, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
16switches T7…T0 = 0011 0011, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
17switches T7…T0 = 0011 0011, press SEND○●●○○○○○ 96P 33 33 — third mistake: blocked ($60)
18switches T7…T0 = 0101 0000, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
19switches T7…T0 = 0001 0010, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
20switches T7…T0 = 0011 0100, press SEND○●●○○○○○ 96P 12 34 — even the right PIN: blocked
21FAC on and off ("the factory prepared the card again")
22RST on and off○○●●●○●● 59greeting
23switches T7…T0 = 0101 0000, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
24switches T7…T0 = 0001 0010, press SEND○○○○○○○○ go offthe byte went, the card waits for the next one
25switches T7…T0 = 0011 0100, press SEND●○○●○○○○ 144P 12 34 — correct again
  • While the "exchange" lamp is lit, the sr lamps blink — look when it has gone off.
  • After the letter P and the first half of the PIN the lamps go off: the card received the byte and silently waits for the next one. The answer comes only after the third transmission.
  • Rows 17–20 are the heart of the lesson: after three mistakes the card does not believe even the right PIN, and a reset does not help it.

Do not fold into a chip — lesson 8.

⚠ A common mistake. One matrix transistor is missing — in the key. The PIN is checked correctly (the key is not needed for it), but in lesson 7 the card answers the challenge wrongly. Compare the matrix with the table row by row.

Lesson 6 paste (Cmd+I)

On top of lesson 5.

# Lesson 6 — personal data (card 1: account 01, PIN 1234, key 5A C3 17 8E) and the try counter. On top of lesson 5; then 06-pin.rom.json.input(Out=FAC)NOT(FAC, nFAC)AND(oST, selTRY, wTRY)RBIT(D=acc0, LD=wTRY, nR=nFAC, CLK=CLK, Q=try0)RBIT(D=acc1, LD=wTRY, nR=nFAC, CLK=CLK, Q=try1) nmos(pr0, pb0, GND)nmos(pr1, pb1, GND)nmos(pr1, pb4, GND)nmos(pr2, pb2, GND)nmos(pr2, pb4, GND)nmos(pr2, pb5, GND)nmos(pr3, pb1, GND)nmos(pr3, pb3, GND)nmos(pr3, pb4, GND)nmos(pr3, pb6, GND)nmos(pr4, pb0, GND)nmos(pr4, pb1, GND)nmos(pr4, pb6, GND)nmos(pr4, pb7, GND)nmos(pr5, pb0, GND)nmos(pr5, pb1, GND)nmos(pr5, pb2, GND)nmos(pr5, pb4, GND)nmos(pr6, pb1, GND)nmos(pr6, pb2, GND)nmos(pr6, pb3, GND)nmos(pr6, pb7, GND)

¿No te sale? Algo no funciona →