Repository navigation
fix: standards conformance fixes from a cross-implementation review - #19
Merged
Merged
Conversation
JIS X 6319-4 assigns 00h to Polling and 04h to Request Response; the constant held 04h and the test cited a wrong source. Add REQUEST_RESPONSE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- DESFireStatus.authenticationDelay (91 AD, NT4H2421Gx Table 23). - authenticateEV2First rejects PCDCap2.1 bit 1 before sending: it requests LRP secure messaging (NT4H2421Gx §9.1), whose answer carries an extra AuthMode byte the EV2 path would misread. The framing test used that bit with an AES transcript and now uses a capability value without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
History records with stations carry the entry / exit region from byte 15 (bits 7-6 / 5-4) in metadata, since a station code is unique only with its region, and process type 17h (bus auto-charge) is a top-up. Metrodroid SuicaTrip and the MJS, Jobcan and yanzm readers agree on both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed Le for long AA signatures Follow the Chip Access Procedure of ICAO 9303-11 §4.2: run PACE right after EF.CardAccess with the Master File as current DF, then select the eMRTD application under PACE secure messaging. The plain SELECT now only precedes BAC. Ask for an extended INTERNAL AUTHENTICATE response (DO'97 0000, outer Le 0000) when the DG15 signature or its secure messaging reply exceeds 256 bytes (ISO/IEC 7816-4 §5.1, ICAO 9303-11 §6.1.4 Note), so RSA-2048 and RSA-3072 Active Authentication keys can return their signature. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ISO/IEC 15693-3 GET MULTIPLE BLOCK SECURITY STATUS returns one byte per block whose b1 is Lock_flag and whose b2-b8 are RFU. ST tags use RFU bits for password protection, so `status != 0` reported those blocks as locked. Map the bytes through the new pure ISO15693BlockSecurityStatus, which masks with 0x01 like ST25 SDK and NFC TagInfo. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET SYSTEM INFORMATION (2Bh) holds the block count in one byte (value - 1), so it cannot describe more than 256 blocks, and the library only used it: the extended-addressing paths for tags above 256 blocks were unreachable and a 2048-block ST25DV64K was dumped, read and formatted as 256 blocks. ISO15693Reader.getSystemInfo() now sends EXTENDED GET SYSTEM INFORMATION (ISO/IEC 15693-3:2019, 3Bh, Info flags requesting the memory size) when 2Bh reports 256 blocks or no memory size, parses the 2-byte block count with the pure ISO15693ExtendedSystemInfo, and takes it only when the block size matches and the count is not smaller. A tag that rejects 3Bh, stays silent or answers malformed keeps the 2Bh result. CoreNFC has no 3Bh call, so the transport sends it with sendRequest and checks the response error flag. The dump, the Type 5 NDEF paths and getISO15693SystemInfo use it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NFC Forum T2T 1.0 §6.1: the data area is CC byte 2 x 8 bytes from page 4. readNDEF took the message from a dump bounded by the product memory map, which is a conservative 16 pages for products GET_VERSION does not identify (NTAG I2C 1k with CC E1 10 6D 00, NTAG203 which NAKs GET_VERSION), so a message past page 15 was reported as ndefMessageNotFound. When the dump read its whole map without a NAK and holds no message, read the further pages the CC declares (4 + ceil(CC2 * 8 / 4), capped at 256) with READ, stopping at the first page the tag refuses. Writes keep the conservative memory map. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NFC Forum NDEF 1.0 §3.2.1: MB is set on the first record of a message and on no other. The parser only checked that MB appeared somewhere, so it accepted `11 01 01 55 00 D1 01 01 55 00` (first record without MB) and `91 01 01 55 00 D1 01 01 55 00` (MB twice). Check MB against the record position, chunks included. ME handling (§3.2.2: nothing after the ME record, ME required on the last one) was already enforced; tests now cover it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Type 2 readNDEF reads past the memory map only when the map holds no complete NDEF TLV; an erased tag (03 00) no longer triggers up to 200 extra READs, whose NAK would send the tag to IDLE before a later write. - Docs: a protected SELECT refused after PACE throws secureMessagingError only for a protected status; a plain status word surfaces as unexpectedStatusWord. - CHANGELOG notes the new DESFireStatus case for exhaustive switches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ance # Conflicts: # CHANGELOG.md
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes found by reviewing every supported card family against its open standard. Closed-source readers were decompiled as cross-references: NXP TagInfo / TagWriter (with NXP's own SDK embedded), NFC TagInfo, NFC Tools, ST25 NFC Tap, Japanese IC readers, passport SDK demos, and My Number / transit apps. Each fix was made only after a test failed on the old code, with the standard clause cited in the test.
& 1readNDEFreads up to the data area declared in the CC (NTAG I2C, NTAG203); an erased tag reads nothing extraFeliCaFrame.POLLINGis00h(it was04h, which is Request Response)91 ADis decoded asauthenticationDelay;authenticateEV2Firstrefuses PCDCap2.1 bit 1 (LRP)17his a top-upNot changed because they are unproven: the Octopus default offset, how the T-Union balance is combined, the My Number header check, and ISO 15693 Protocol_Extension.
Needs hardware validation
03 00 FETLV are written first.Tests
On the iOS Simulator the package tests pass (1068 tests, 69 suites) and the Example app builds. After the fixes, an independent adversarial review of the combined diff found no regressions; its doc and erased-tag findings are fixed in the last commit.
#18 also adds an
## [Unreleased]CHANGELOG section, so whichever PR merges second needs a trivial CHANGELOG merge.🤖 Generated with Claude Code