Chapter 4: MIFARE Ultralight — Lightweight Tags & Ticketing

While MIFARE Classic is optimised for reusable smart cards with per-sector authentication, the MIFARE Ultralight family is designed for a different use case: cheap, disposable, or limited-use tags where cost and simplicity matter more than strong security.

MIFARE Ultralight is the foundation of the NFC Forum Type 2 tag specification, and the NTAG21x derivatives are the most popular NFC sticker and wearable tag chips on the market. Understanding this family is essential for any NFC development involving consumer-facing applications.


4.1 The Ultralight Family

The Ultralight family has grown considerably over the years. The key members:

Chip Memory (user bytes) Pages Security Notes
MIFARE Ultralight (MF0ICU1) 48 bytes 16 Lock bytes only Oldest; NFC Forum Type 2
MIFARE Ultralight C (MF0ICU2) 48 bytes 48 3DES authentication Adds crypto auth
MIFARE Ultralight EV1 (MF0ULx1) 48 or 128 bytes 20 or 41 Password (32-bit) Counter, tearing detection
NTAG210 48 bytes 16 Password (32-bit) Minimal NTAG
NTAG212 128 bytes 36 Password (32-bit)  
NTAG213 144 bytes 45 Password (32-bit) Most common NFC sticker
NTAG215 504 bytes 135 Password (32-bit) Used in Amiibo
NTAG216 888 bytes 231 Password (32-bit) Largest standard NTAG
NTAG I2C 888 bytes / 2 KB Password Adds I2C interface for dual-interface

All chips in this family are ISO 14443 Type A compliant. ATQA is 0x0044, SAK is 0x00.

Note that NTAG213/215/216 are the chips you will find in nearly every “NFC sticker” product sold online. NTAG213 is the cheapest and most ubiquitous.


4.2 Memory Layout — Pages

Unlike MIFARE Classic (blocks of 16 bytes), the Ultralight family uses pages of 4 bytes. This is a fundamental difference in addressing.

MIFARE Ultralight (Original) — 16 pages

Page 0:  UID byte 0, UID byte 1, UID byte 2, BCC0
Page 1:  UID byte 3, UID byte 4, UID byte 5, UID byte 6
Page 2:  BCC1, Internal, Lock byte 0, Lock byte 1
Page 3:  OTP (One-Time Programmable) byte 0–3
Pages 4–15: User data (48 bytes total)

UID: Ultralight uses a 7-byte UID (ISO 14443 cascade level 2). The UID is spread across pages 0 and 1 with BCC (Block Check Character) bytes interspersed.

BCC0 = UID[0] ⊕ UID[1] ⊕ UID[2] ⊕ 0x88 (cascade tag) BCC1 = UID[3] ⊕ UID[4] ⊕ UID[5] ⊕ UID[6]

Lock bytes (pages 2, bytes 2–3): 16 bits that, when set to 1, permanently lock individual pages as read-only. Once a lock bit is set it cannot be cleared — the operation is irreversible. Bit mapping:

Lock byte 0 (page 2, byte 2):
  bit 7: lock page 7     bit 3: lock page 3
  bit 6: lock page 6     bit 2: lock page 2 (OTP)
  bit 5: lock page 5     bit 1: block write access to pages 4–9
  bit 4: lock page 4     bit 0: block write access to pages 0–3

Lock byte 1 (page 2, byte 3):
  bit 7: lock page 15    ...
  bit 0: lock page 8

OTP (One-Time Programmable) page (page 3): A 32-bit OTP register. Individual bits can be set from 0 to 1 but never back to 0. Used to mark a tag as “used” in ticketing applications by flipping specific bits on first validation.

User data (pages 4–15): 12 pages × 4 bytes = 48 bytes available for application data.


4.3 NTAG213 Memory Layout — 45 pages

NTAG213 is the most common chip you will work with. Its 45-page layout:

Page 0:  UID byte 0–2, BCC0
Page 1:  UID byte 3–6
Page 2:  BCC1, Internal, Lock byte 0, Lock byte 1
Page 3:  Capability Container (CC) — 4 bytes
Pages 4–39: User data (144 bytes)
Page 40: Dynamic lock bytes (3 bytes) + RFUI
Page 41: CFG 0 (Mirror, Auth0 config)
Page 42: CFG 1 (Access config, NFC_CNT_EN)
Page 43: PWD  (4-byte password)
Page 44: PACK (2-byte password acknowledge) + RFUI

Capability Container (CC) — page 3

The Capability Container is defined by the NFC Forum Type 2 Tag specification and tells an NDEF reader how to use the tag:

Byte 0: Magic number — 0xE1 (NFC Forum magic)
Byte 1: Version — 0x10 (version 1.0)
Byte 2: Size — 0x12 (NTAG213: 18 × 8 = 144 bytes user memory)
Byte 3: Access — 0x00 (read/write) or 0xFF (read-only)

If byte 0 is not 0xE1, most NFC libraries and smartphones will not attempt to read NDEF from the tag.

Dynamic Lock Bytes (page 40)

NTAG21x has an extended lock mechanism. Three lock bytes at page 40 cover user pages 4–39 in groups of 4 pages:

Byte 0 of page 40:
  bits 7–4: lock pages 36–39
  bits 3–0: lock pages 32–35
Byte 1:
  bits 7–4: lock pages 28–31
  bits 3–0: lock pages 24–27
Byte 2:
  bits 7–4: lock pages 20–23
  bits 3–0: lock pages 16–19

Configuration Pages (41–44)

CFG 0 (page 41):

Byte 0: MIRROR — enables ASCII mirror of UID/NFC counter into user data
Byte 1: RFUI (reserved)
Byte 2: MIRROR_PAGE — starting page for mirror
Byte 3: AUTH0 — page number from which password protection starts
         (0xFF = no password protection)

CFG 1 (page 42):

Byte 0: ACCESS
  bit 7: PROT — if 1, write AND read require password; if 0, write only
  bit 6: CFGLCK — if 1, configuration pages 41–42 are locked
  bit 5: RFUI
  bit 4: NFC_CNT_EN — enable NFC counter
  bit 3: NFC_CNT_PWD_PROT — counter read requires password
  bits 2–0: AUTHLIM (0 = unlimited; 1–7 = max failed auth attempts)

PWD (page 43): 4-byte password, written by the programmer, verified by the tag on PWD_AUTH commands. Factory default is 0x00000000.

PACK (page 44, bytes 0–1): 2-byte password acknowledge. The tag returns this value after successful authentication, allowing the reader to verify it is talking to a genuine tag. Factory default is 0x0000.


4.4 Password Authentication

NTAG21x supports a simple 32-bit password mechanism:

  1. Reader sends PWD_AUTH command with the 4-byte password
  2. If correct, tag returns the 2-byte PACK
  3. If incorrect and AUTHLIM > 0, the failed attempt counter increments; after AUTHLIM failures, further authentication attempts return NAK

This is not a cryptographic mutual authentication — it is just a PIN check. The password is sent in plaintext over the RF link. An eavesdropper within range can capture the password. For consumer NFC stickers protecting a URL or product identity, this is generally acceptable. For high-value applications it is not.

# Example: authenticate with nfcpy (simplified)
import nfc

def on_connect(tag):
    password = b'\x01\x02\x03\x04'  # 4-byte password
    pack = tag.authenticate(password)
    print(f"Authenticated, PACK = {pack.hex()}")

with nfc.ContactlessFrontend('usb') as clf:
    clf.connect(rdwr={'on-connect': on_connect})

4.5 MIFARE Ultralight C — 3DES Authentication

Ultralight C adds a real cryptographic authentication layer using 3DES (Triple-DES with 112-bit keys) — the same algorithm used in older banking systems. Memory is the same 48 user bytes as the original Ultralight, plus extra pages for the 3DES key material (pages 44–47, 16 bytes total).

The 3DES authentication is a 3-pass mutual authentication:

  1. Reader sends AUTH command
  2. Tag returns encrypted random nonce RndB
  3. Reader decrypts RndB, generates RndA, sends Enc(RndA   RndB’)
  4. Tag verifies, returns Enc(RndA’) for reader to verify

After authentication, read and write commands to protected pages are encrypted. The protection boundary is configured by pages 42–43.

Ultralight C is less common than NTAG21x because 3DES is expensive in silicon (larger chip, higher cost) and because the 48-byte user memory is small. It is used in some single-use transit tickets and event wristbands where a level of authentication is needed without the complexity of DESFire.


4.6 NTAG215 and Amiibo

NTAG215 has 504 bytes of user memory across 135 pages and is the chip used in Nintendo Amiibo figurines. The Amiibo application uses the full user memory and the password feature, with a specific data structure encoding character ID and user save data. The NTAG215 format and password are well-documented by the reverse engineering community and are used by tools like TagMo to create “homebrew Amiibo” from blank NTAG215 stickers.

This is a useful illustrative example: NTAG21x password protection is sufficient to make casual alteration inconvenient, but with a reader in hand and knowledge of the password structure (or brute force of the 32-bit space), the protection is breakable.


4.7 NTAG I2C

NTAG I2C is a dual-interface chip: it has both an NFC interface (ISO 14443 Type A) and an I2C interface. This allows an embedded microcontroller to write data to the tag over I2C, and an NFC reader to read it contactlessly — or vice versa. It is used in smart packaging where a product’s status (temperature, usage counter) is updated by the product’s own embedded system and readable by a phone.


4.8 Command Set Summary

The Ultralight family uses a small command set (compared to MIFARE Classic):

Command Code Description
GET_VERSION 0x60 Returns chip version and capability info
READ 0x30 Read 4 pages (16 bytes) starting at given page
FAST_READ 0x3A Read a range of pages in one command
WRITE 0xA2 Write 1 page (4 bytes)
COMP_WRITE 0xA0 Compatibility write (for Ultralight compatibility)
READ_CNT 0x39 Read NFC counter
PWD_AUTH 0x1B Submit password
AUTH 0x1A Begin 3DES auth (Ultralight C only)
HALT 0x50 Put tag to sleep

READ returns 4 pages at once (even though you address by page number). Most libraries abstract this and let you read or write individual pages.


4.9 Use Cases

NFC stickers (smart posters, product authentication). NTAG213/215/216 stickers are produced for less than $0.10 in volume. A URL, vCard, or Wi-Fi credentials stored as NDEF in the user memory makes the sticker interactive without a battery. Smartphones read these natively.

Event tickets and wristbands. Single-use event wristbands often use Ultralight EV1 or NTAG21x with an OTP bit or counter as a “punch” mechanism. The OTP page is used to mark a ticket as used.

Single-trip transit. Disposable paper transit tickets use Ultralight C or Ultralight EV1. The trip data is stored in user pages; authentication prevents forgery.

Medical device labelling. NTAG21x tags are embedded in medical device packaging to store lot numbers, expiry dates, and provenance information readable by a smartphone during clinical setup.

Smart packaging. NTAG I2C allows a product’s embedded system to update freshness or usage data that the consumer can read with a phone.


Summary


← Chapter 3: MIFARE Classic Table of Contents Chapter 5: NDEF Format →