Skip to main content

scll_core/command/
set_status.rs

1//! SET STATUS (CLA 84, INS F0) — PDD §5.11, GPCS v2.3.1 §11.10.
2//!
3//! Card/ISD scope (**verified**, §11.10.2.1–.3):
4//! - P1 = `0x80` (Table 11-86: ISD = b8b7b6 `100`).
5//! - P2 = target card life-cycle byte (Table 11-6): `INITIALIZED 0x07`,
6//!   `SECURED 0x0F`, `CARD_LOCKED 0x7F`; unlock → `0x0F`.
7//! - Data = raw, untagged ISD AID; **ignored** when P1=`0x80` (empty also legal).
8
9use crate::command::{build, BuildError, Capdu};
10
11/// Build a SET STATUS for card/ISD scope (P1 fixed `0x80`).
12///
13/// `CLA=84 INS=F0 P1=80`, `P2 = p2_state` (Table 11-6 card life-cycle byte).
14/// Data = the raw, untagged ISD AID; the card ignores it under P1=`0x80`
15/// (§11.10.2.3) but it is sent for cross-card compatibility (empty is also
16/// legal). **No `Le`** (Table 11-85, Case 1/3) — the only builder here that
17/// omits it.
18///
19/// # Errors
20/// Returns [`BuildError::Overflow`] if the encoded inputs would exceed the
21/// short-APDU plaintext buffer (`CAPDU_MAX`).
22pub fn set_card_status(p2_state: u8, isd_aid: &[u8]) -> Result<Capdu, BuildError> {
23    build(0x84, 0xF0, 0x80, p2_state, isd_aid, false)
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29    use scll_test_util::HexSlice;
30
31    #[test]
32    fn secured_with_isd_aid_has_no_le() {
33        let aid = [0xA0, 0x00, 0x00, 0x01, 0x51];
34        let apdu = set_card_status(0x0F, &aid).unwrap();
35        assert_eq!(
36            HexSlice(&apdu),
37            HexSlice([0x84, 0xF0, 0x80, 0x0F, 0x05, 0xA0, 0x00, 0x00, 0x01, 0x51])
38        );
39    }
40
41    #[test]
42    fn empty_aid_is_case_1_header_only() {
43        // Data ignored under P1=0x80, so an empty data field is spec-legal.
44        let apdu = set_card_status(0x07, &[]).unwrap();
45        assert_eq!(HexSlice(&apdu), HexSlice([0x84, 0xF0, 0x80, 0x07]));
46    }
47
48    #[test]
49    fn card_locked_byte_maps_to_p2() {
50        let apdu = set_card_status(0x7F, &[]).unwrap();
51        assert_eq!(HexSlice(&apdu), HexSlice([0x84, 0xF0, 0x80, 0x7F]));
52    }
53
54    #[test]
55    fn oversized_aid_overflows() {
56        let big = [0x00u8; 256];
57        assert_eq!(set_card_status(0x0F, &big), Err(BuildError::Overflow));
58    }
59}