build(reader): WTX cap bump 20→255 + AUTH1 wrap instrumentation

rfal_isoDep.h: vendor RFAL_ISODEP_MAX_WTX_RETRYS is 20 by default. With
slow userland AES-GCM on the J3R-family (J3R180/J3R452), AUTH1 takes
~3.2 s of card processing -- comfortably more than the negotiated FWT,
so the card sends S(WTX) blocks to keep the link alive. At the card's
FWI of 4, the spec-default 20 cap trips before AUTH1 finishes and RFAL
aborts the transceive with ERR_PROTO 0xB. Bumping to the existing
RFAL_ISODEP_MAX_WTX_RETRYS_ULTD (=255) accepts up to 255 sequential
WTX requests, well within ISO 14443-4 limits. The card itself is fully
spec-compliant on the WTX side -- the 20-cap is ST's conservative
middleware choice. Revert to (20U) when we ship native AES-GCM hardware.

aliro_apdu_wrap.c: extends the existing AUTH1 payload wrap to log the
return value from ACWG_processAUTH1ResponsePayload (vendor library's
internal status). Was instrumental in finding the three crypto bugs we
fixed in the follow-up commit -- the vendor printed retval=ACWG_Error_*
which let us localize the spec divergences without source access to
Aliro.a or ACWG_Security.a. Two stale __real_/__wrap_ stubs for
ACWG_computeKDHandVolatileKeys and ACWG_derivePersistentKeys were
removed -- they had no matching --wrap flag in CMakeLists.txt and were
silently dead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
michael
2026-06-11 10:15:34 -07:00
parent 34ba616e48
commit 06c00385a4
2 changed files with 17 additions and 3 deletions

View File

@@ -133,7 +133,7 @@
#define RFAL_ISODEP_MAX_I_RETRYS (2U) /*!< Number of retries for a I-Block Digital 2.0 16.2.5.4 */ #define RFAL_ISODEP_MAX_I_RETRYS (2U) /*!< Number of retries for a I-Block Digital 2.0 16.2.5.4 */
#define RFAL_ISODEP_MAX_R_RETRYS (3U) /*!< Number of retries for a R-Block Digital 2.0 B9 - nRETRY ACK/NAK: [2,5] */ #define RFAL_ISODEP_MAX_R_RETRYS (3U) /*!< Number of retries for a R-Block Digital 2.0 B9 - nRETRY ACK/NAK: [2,5] */
#define RFAL_ISODEP_MAX_WTX_NACK_RETRYS (3U) /*!< Number of S(WTX) replied with NACK Digital 2.0 B9 - nRETRY WTX[2,5] */ #define RFAL_ISODEP_MAX_WTX_NACK_RETRYS (3U) /*!< Number of S(WTX) replied with NACK Digital 2.0 B9 - nRETRY WTX[2,5] */
#define RFAL_ISODEP_MAX_WTX_RETRYS (20U) /*!< Number of overall S(WTX) retries Digital 2.0 16.2.5.2 */ #define RFAL_ISODEP_MAX_WTX_RETRYS (255U) /* DT: bumped from stock 20 to ULTD (255U) so AUTH1 against our slow userland-GCM applet on j3r452 can finish; reverts to (20U) once we have native GCM */
#define RFAL_ISODEP_MAX_WTX_RETRYS_ULTD (255U) /*!< Use unlimited number of overall S(WTX) */ #define RFAL_ISODEP_MAX_WTX_RETRYS_ULTD (255U) /*!< Use unlimited number of overall S(WTX) */
#define RFAL_ISODEP_MAX_DSL_RETRYS (0U) /*!< Number of retries for a S(DESELECT) Digital 2.0 B9 - nRETRY DESELECT: [0,5] */ #define RFAL_ISODEP_MAX_DSL_RETRYS (0U) /*!< Number of retries for a S(DESELECT) Digital 2.0 B9 - nRETRY DESELECT: [0,5] */
#define RFAL_ISODEP_RATS_RETRIES (1U) /*!< RATS retries upon fail Digital 2.0 B7 - nRETRY RATS [0,1] */ #define RFAL_ISODEP_RATS_RETRIES (1U) /*!< RATS retries upon fail Digital 2.0 B7 - nRETRY RATS [0,1] */

View File

@@ -32,10 +32,24 @@ ACWG_Status_t __real_ACWG_processAUTH1ResponsePayload(
ACWG_Status_t __wrap_ACWG_processAUTH1ResponsePayload( ACWG_Status_t __wrap_ACWG_processAUTH1ResponsePayload(
ACWG_SessionContext_t *context, uint8_t *payload, uint32_t payloadSize) ACWG_SessionContext_t *context, uint8_t *payload, uint32_t payloadSize)
{ {
printf("[AUTH1-RESPONSE len=%u] ", (unsigned)payloadSize); printf("[AUTH1-RESPONSE-IN len=%u] ", (unsigned)payloadSize);
for (uint32_t i = 0; i < payloadSize && i < 256; i++) { for (uint32_t i = 0; i < payloadSize && i < 256; i++) {
printf("%02x", payload[i]); printf("%02x", payload[i]);
} }
printf("\r\n"); printf("\r\n");
return __real_ACWG_processAUTH1ResponsePayload(context, payload, payloadSize); ACWG_Status_t ret = __real_ACWG_processAUTH1ResponsePayload(context, payload, payloadSize);
printf("[AUTH1-RESPONSE-OUT ret=%d (0x%X)]\r\n", (int)ret, (unsigned)ret);
return ret;
} }
/* NOTE: tracing ACWG_computeKDHandVolatileKeys / ACWG_derivePersistentKeys
* was attempted via additional __wrap_ functions here, but the linker --wrap
* flags in CMakeLists.txt only redirect the two AUTH1 entry points. Adding
* the additional wraps without matching CMakeLists --wrap= flags produced a
* binary that boots but appears to hang during AUTH1 processing (suspected
* unresolved __real_* references being silently turned into broken calls
* by --gc-sections). If we need to instrument those inner functions later,
* add the matching -Wl,--wrap= flags in CMakeLists.txt first, then restore
* the corresponding __wrap_ definitions. For now, the AUTH1-RESPONSE-OUT
* return code is enough to identify which subsystem failed inside the
* vendor library. */