From 9a7bb6345f907e074c3d89b5b36347e427e844ee Mon Sep 17 00:00:00 2001 From: Florian Franzen Date: Wed, 30 Sep 2026 05:20:16 +0200 Subject: [PATCH] Treat an absent Le as up to 256 bytes --- dispatch/CHANGELOG.md | 3 ++- dispatch/src/dispatch.rs | 11 ++++++++++- dispatch/tests/dispatch.rs | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/dispatch/CHANGELOG.md b/dispatch/CHANGELOG.md index 5dfe773..3e95e92 100644 --- a/dispatch/CHANGELOG.md +++ b/dispatch/CHANGELOG.md @@ -6,7 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- +- Treat an absent Le as 'up to 256 bytes' like a YubiKey instead of 'no response + data' ## [0.4.0] diff --git a/dispatch/src/dispatch.rs b/dispatch/src/dispatch.rs index c795594..3700051 100644 --- a/dispatch/src/dispatch.rs +++ b/dispatch/src/dispatch.rs @@ -260,7 +260,16 @@ impl<'pipe> ApduDispatch<'pipe> { // Parse the message as an APDU. match apdu { Ok(command) => { - self.response_len_expected = command.expected(); + // A real YubiKey treats an absent Le byte -- which is what + // ykman, yubico-piv-tool and yubikey.rs send -- as "up to + // 256 bytes", not as "no response data": short replies come + // back whole and longer ones chunk over GET RESPONSE. Those + // clients never issue GET RESPONSE after a plain SELECT, so + // answering 61XX there loses them entirely. + self.response_len_expected = match command.expected() { + 0 => 256, + expected => expected, + }; // The Apdu may be standalone or part of a chain. self.buffer_chained_apdu_if_needed(command.as_view(), interface) } diff --git a/dispatch/tests/dispatch.rs b/dispatch/tests/dispatch.rs index bc51927..ad6a82a 100644 --- a/dispatch/tests/dispatch.rs +++ b/dispatch/tests/dispatch.rs @@ -370,6 +370,22 @@ fn echo_1() { ]) } +#[test] +#[serial] +fn echo_without_le() { + run_apdus(&[ + // Select + &hex!("00A40400 05 0A01000001"), + // Ok + &hex!("9000"), + // Echo without an Le byte: Yubico ecosystem clients omit it and still + // expect up to 256 bytes of response data, like a YubiKey sends + &hex!("00100000 05 0102030405"), + // Echo + Ok + &hex!("0000000000 01020304059000"), + ]) +} + #[test] #[serial] fn echo_with_cla_bits_set() {