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}