Skip to main content

scll_core/command/
get_data.rs

1//! GET DATA (CLA 80, INS CA) — PDD §5.2.
2//!
3//! Tags: `'66'` Card Recognition Data (§H.2), `'67'` Card Capability Information
4//! (§H.4), `'00E0'` Key Information Template (§11.3.3.1), `'0042'` IIN,
5//! `'0045'` CIN.
6
7use crate::command::{build, BuildError, Capdu};
8
9/// Build a GET DATA for the given 2-byte tag (P1P2).
10///
11/// `CLA=80 INS=CA`, P1P2 = the object tag big-endian (e.g. `'0066'` CRD,
12/// `'00E0'` KIT, `'0067'` CCI, `'0042'` IIN, `'0045'` CIN). No command data;
13/// `Le=00` (Case 2S).
14///
15/// # Errors
16/// Returns [`BuildError::Overflow`] if the encoded inputs would exceed the
17/// short-APDU plaintext buffer (`CAPDU_MAX`).
18pub fn get_data(tag_p1p2: u16) -> Result<Capdu, BuildError> {
19    let [p1, p2] = tag_p1p2.to_be_bytes();
20    build(0x80, 0xCA, p1, p2, &[], true)
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26    use proptest::prelude::*;
27    use scll_test_util::HexSlice;
28
29    #[test]
30    fn card_recognition_data_tag_66() {
31        let apdu = get_data(0x0066).unwrap();
32        assert_eq!(HexSlice(&apdu), HexSlice([0x80, 0xCA, 0x00, 0x66, 0x00]));
33    }
34
35    #[test]
36    fn key_information_template_tag_00e0() {
37        let apdu = get_data(0x00E0).unwrap();
38        assert_eq!(HexSlice(&apdu), HexSlice([0x80, 0xCA, 0x00, 0xE0, 0x00]));
39    }
40
41    #[test]
42    fn iin_tag_0042_splits_both_p1_p2_bytes() {
43        // Exercises a non-zero P1 byte so the big-endian split is checked.
44        let apdu = get_data(0x0042).unwrap();
45        assert_eq!(HexSlice(&apdu), HexSlice([0x80, 0xCA, 0x00, 0x42, 0x00]));
46    }
47
48    #[test]
49    fn high_tag_byte_is_p1() {
50        let apdu = get_data(0x9F7F).unwrap();
51        assert_eq!(HexSlice(&apdu), HexSlice([0x80, 0xCA, 0x9F, 0x7F, 0x00]));
52    }
53
54    proptest! {
55        /// For any tag, the APDU is exactly header ‖ P1P2(tag) ‖ Le.
56        #[test]
57        fn is_header_tag_le(tag in any::<u16>()) {
58            let apdu = get_data(tag).unwrap();
59            let [p1, p2] = tag.to_be_bytes();
60            let expected = [0x80, 0xCA, p1, p2, 0x00];
61            prop_assert_eq!(apdu.as_slice(), expected.as_slice());
62        }
63    }
64}