Lesson 6. Personal data and the try counter: the card checks the PIN
In picturesAfter 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.
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).
| Part | Pin | Label |
|---|---|---|
| Input (switch) | out | FAC |
| NOT | I0 O0 | FAC nFAC |
| AND | I0 I1 O0 | oST selTRY wTRY |
| RBIT | D LD nR CLK Q | acc0 wTRY nFAC CLK try0 |
| RBIT | D 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:
| Address | What | Hex | Bits 7…0 | Row transistors (columns) |
|---|---|---|---|---|
| 16 ($10) | account number | 01 | 0000 0001 | pb0 |
| 17 ($11) | PIN, digits 1–2 | 12 | 0001 0010 | pb4, pb1 |
| 18 ($12) | PIN, digits 3–4 | 34 | 0011 0100 | pb5, pb4, pb2 |
| 19 ($13) | key, byte 1 | 5A | 0101 1010 | pb6, pb4, pb3, pb1 |
| 20 ($14) | key, byte 2 | C3 | 1100 0011 | pb7, pb6, pb1, pb0 |
| 21 ($15) | key, byte 3 | 17 | 0001 0111 | pb4, pb2, pb1, pb0 |
| 22 ($16) | key, byte 4 | 8E | 1000 1110 | pb7, pb3, pb2, pb1 |
The PIN is written in binary-coded decimal: each digit is 4 bits (12 → 0001 0010).
| Part | Pin | Label |
|---|---|---|
| nmos | gate drain source | pr0 pb0 GND |
| nmos | gate drain source | pr1 pb1 GND |
| nmos | gate drain source | pr1 pb4 GND |
| nmos | gate drain source | pr2 pb2 GND |
| nmos | gate drain source | pr2 pb4 GND |
| nmos | gate drain source | pr2 pb5 GND |
| nmos | gate drain source | pr3 pb1 GND |
| nmos | gate drain source | pr3 pb3 GND |
| nmos | gate drain source | pr3 pb4 GND |
| nmos | gate drain source | pr3 pb6 GND |
| nmos | gate drain source | pr4 pb0 GND |
| nmos | gate drain source | pr4 pb1 GND |
| nmos | gate drain source | pr4 pb6 GND |
| nmos | gate drain source | pr4 pb7 GND |
| nmos | gate drain source | pr5 pb0 GND |
| nmos | gate drain source | pr5 pb1 GND |
| nmos | gate drain source | pr5 pb2 GND |
| nmos | gate drain source | pr5 pb4 GND |
| nmos | gate drain source | pr6 pb1 GND |
| nmos | gate drain source | pr6 pb2 GND |
| nmos | gate drain source | pr6 pb3 GND |
| nmos | gate 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 number | command "number" |
| P (80), then 2 PIN bytes | 144 ($90) 98 / 97 ($62 / $61) 96 ($60) | PIN correct wrong, 2 / 1 tries left card blocked |
| anything else | 109 ($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 RET6.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 do | Lamps (● lit) | What it is |
|---|---|---|---|
| 1 | Clock — MAX (click on the body) | ||
| 2 | switch FAC and RST on, wait a second, switch both off | ||
| 3 | do not touch anything, look at the lamps | ○○●●●○●● 59 | the card said hello: $3B |
| 4 | switches T7…T0 = 0100 1110, press SEND | ○○○○○○○● 1 | N — account number: 1 |
| 5 | switches T7…T0 = 0101 0000, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 6 | switches T7…T0 = 0001 0010, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 7 | switches T7…T0 = 0011 0100, press SEND | ●○○●○○○○ 144 | P 12 34 — PIN correct ($90) |
| 8 | switches T7…T0 = 0101 0000, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 9 | switches T7…T0 = 0001 0001, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 10 | switches T7…T0 = 0001 0001, press SEND | ○●●○○○●○ 98 | P 11 11 — wrong, 2 tries left ($62) |
| 11 | switches T7…T0 = 0101 0000, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 12 | switches T7…T0 = 0010 0010, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 13 | switches T7…T0 = 0010 0010, press SEND | ○●●○○○○● 97 | P 22 22 — wrong, 1 left ($61) |
| 14 | RST on and off ("took the card out and put it back") | ○○●●●○●● 59 | the greeting again: the card restarted |
| 15 | switches T7…T0 = 0101 0000, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 16 | switches T7…T0 = 0011 0011, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 17 | switches T7…T0 = 0011 0011, press SEND | ○●●○○○○○ 96 | P 33 33 — third mistake: blocked ($60) |
| 18 | switches T7…T0 = 0101 0000, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 19 | switches T7…T0 = 0001 0010, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 20 | switches T7…T0 = 0011 0100, press SEND | ○●●○○○○○ 96 | P 12 34 — even the right PIN: blocked |
| 21 | FAC on and off ("the factory prepared the card again") | ||
| 22 | RST on and off | ○○●●●○●● 59 | greeting |
| 23 | switches T7…T0 = 0101 0000, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 24 | switches T7…T0 = 0001 0010, press SEND | ○○○○○○○○ go off | the byte went, the card waits for the next one |
| 25 | switches T7…T0 = 0011 0100, press SEND | ●○○●○○○○ 144 | P 12 34 — correct again |
- While the "exchange" lamp is lit, the
srlamps blink — look when it has gone off. - After the letter
Pand 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 →