Initial snapshot: Aliro applet, harness, Nucleo NFC10A1 reader port
Three components, all bench-validated to varying depths: - applet/: CSA Aliro v1.0 Java Card applet for J3R180. AUTH0 + AUTH1 expedited-standard flow end-to-end green via PC/SC bench reader (aliro-bench-test). Userland AES-256-GCM and HMAC-SHA-256 layered on top of J3R180's primitives because the card lacks both natively. P-256 curve params seeded explicitly per J3R180's quirk. - harness/: Python orchestrator (aliro-trustgen, aliro-personalize, aliro-bench-test) for trust-bundle generation, card personalization via PersonalizationApplet, and PC/SC AUTH0+AUTH1 transactions. 126 pytest cases passing. - reader/STM32CubeExpansion_ALIRO_V1_0_0/: ST X-CUBE-ALIRO V1.0.0 with our NFC10A1 port (NUCLEO-U545RE-Q + X-NUCLEO-NFC10A1, ST25R200 shared with NFC09A1). nfc10-only/ project, NFC10A1 BSP shim, ALIRO_TRUST_OVERRIDE include into vendor's provisioning.c, and an ALIRO_APDU_TRACE wrapper around demoTransceiveBlocking. Boots, detects the J3R180, completes SELECT + AUTH0; AUTH1 currently fails with RFAL ERR_PROTO (0xB) — under investigation, see docs/plans/2026-04-20-nucleo-nfc10a1-port.md and bench-notes/. Excluded: x-cube-aliro.zip vendor archive, harness/.venv, build dirs, generated aliro_trust.h (contains private reader scalar), all PEMs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
package com.dangerousthings.aliro;
|
||||
|
||||
import javacard.framework.APDU;
|
||||
import javacard.framework.Applet;
|
||||
import javacard.framework.ISO7816;
|
||||
import javacard.framework.ISOException;
|
||||
import javacard.framework.Util;
|
||||
|
||||
/**
|
||||
* Scaffold for the Aliro step-up phase (spec §8.4). Lives under
|
||||
* {@link AliroAids#STEP_UP}.
|
||||
*
|
||||
* <p>This first pass only answers SELECT with a minimal FCI and rejects
|
||||
* unknown commands cleanly. The actual step-up protocol — mdoc
|
||||
* SessionData framing (DeviceRequest/DeviceResponse CBOR with
|
||||
* Aliro-remapped integer keys per Tables 8-21/8-22), ENVELOPE/GET
|
||||
* RESPONSE command chaining, and a fresh AES-256-GCM session keyed by
|
||||
* StepUpSKDevice/StepUpSKReader derived per spec §8.4.3 — comes in
|
||||
* follow-up iterations.
|
||||
*
|
||||
* <p>When that work lands, this applet will need access to the
|
||||
* {@code StepUpSK} (a 32-byte session-bound value produced by
|
||||
* {@link AliroApplet}'s derivation in §8.3.1.13). Since Java Card
|
||||
* installs distinct instances per AID, that state will be exchanged via
|
||||
* a shared package-private holder (not yet implemented).
|
||||
*/
|
||||
public class StepUpApplet extends Applet {
|
||||
|
||||
private static final byte CLA_PROPRIETARY = (byte) 0x80;
|
||||
|
||||
public static void install(byte[] bArray, short bOffset, byte bLength) {
|
||||
StepUpApplet applet = new StepUpApplet();
|
||||
if (bArray == null || bLength == 0) {
|
||||
applet.register();
|
||||
} else {
|
||||
applet.register(bArray, (short) (bOffset + 1), bArray[bOffset]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean select() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(APDU apdu) {
|
||||
if (selectingApplet()) {
|
||||
sendStepUpFci(apdu);
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] buf = apdu.getBuffer();
|
||||
if (buf[ISO7816.OFFSET_CLA] != CLA_PROPRIETARY) {
|
||||
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
// Until the mdoc DeviceRequest pipeline lands, every proprietary INS
|
||||
// is unrecognised. ENVELOPE + GET RESPONSE handlers plug in here.
|
||||
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimal FCI for step-up SELECT. The spec (§10.2.1.2) allows the UD to
|
||||
* advertise supported APDU command/response sizes here; those get added
|
||||
* when we implement ENVELOPE/GET RESPONSE.
|
||||
*
|
||||
* <pre>
|
||||
* 6F L
|
||||
* 84 09 [step-up AID]
|
||||
* </pre>
|
||||
*/
|
||||
private void sendStepUpFci(APDU apdu) {
|
||||
byte[] buf = apdu.getBuffer();
|
||||
short off = 0;
|
||||
buf[off++] = 0x6F;
|
||||
short outerLenPos = off++;
|
||||
|
||||
buf[off++] = (byte) 0x84;
|
||||
buf[off++] = (byte) AliroAids.STEP_UP.length;
|
||||
off = Util.arrayCopyNonAtomic(AliroAids.STEP_UP, (short) 0,
|
||||
buf, off, (short) AliroAids.STEP_UP.length);
|
||||
|
||||
buf[outerLenPos] = (byte) (off - 2);
|
||||
apdu.setOutgoingAndSend((short) 0, off);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user