//! Tests for custom derive support #![cfg(feature = "derive")] use flexiber::{Decodable, Encodable}; use flexiber as ber; #[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)] #[tlv(number = "0xAA")] struct S { #[tlv(slice, number = "0x11")] x: [u8; 2], #[tlv(slice, number = "0x22")] y: [u8; 3], #[tlv(slice, number = "0x33")] z: [u8; 4], } #[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)] #[tlv(application, number = "0xAA")] struct SApp { #[tlv(slice, number = "0x11")] x: [u8; 2], #[tlv(slice, number = "0x22")] y: [u8; 3], #[tlv(slice, number = "0x33")] z: [u8; 4], } #[test] fn derived_reconstruct() { let s = S { x: [1,2], y: [3,4,5], z: [6,7,8,9] }; let mut buf = [0u8; 1024]; let encoded = s.encode_to_slice(&mut buf).unwrap(); assert_eq!(encoded, &[0x1F, 0x81, 0x2A, 17, 0x11, 2, 1, 2, 0x1F, 0x22, 3, 3, 4, 5, 0x1F, 0x33, 4, 6, 7, 8, 9, ], ); let s2 = S::from_bytes(encoded).unwrap(); assert_eq!(s, s2); } #[test] fn derived_reconstruct_application() { let s = SApp { x: [1,2], y: [3,4,5], z: [6,7,8,9] }; let mut buf = [0u8; 1024]; let encoded = s.encode_to_slice(&mut buf).unwrap(); assert_eq!(encoded, &[0x5F, 0x81, 0x2A, 17, 0x11, 2, 1, 2, 0x1F, 0x22, 3, 3, 4, 5, 0x1F, 0x33, 4, 6, 7, 8, 9, ], ); let s2 = SApp::from_bytes(encoded).unwrap(); assert_eq!(s, s2); } #[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)] #[tlv(constructed, number = "0x10")] struct T { #[tlv(number = "0x44", slice)] x: [u8; 1234], } #[test] fn pretty_big() { let mut x = [0u8; 1234]; for (i, x) in x.iter_mut().enumerate() { *x = i as _; }; let t = T { x }; let mut buf = [0u8; 1024]; assert!(t.encode_to_slice(&mut buf).is_err()); let mut buf = [0u8; 1500]; let encoded = t.encode_to_slice(&mut buf).unwrap(); assert_eq!(&encoded[..9], [ // 1234 + 5 0x30, 0x82, 0x04, 0xD2 + 5, // 1234 0x1F, 0x44, 0x82, 0x04, 0xD2]); assert_eq!(&encoded[9..], x); let t2 = T::from_bytes(encoded).unwrap(); assert_eq!(t, t2); } #[derive(Clone, Copy, Debug, Decodable, Encodable, Eq, PartialEq)] struct T2 { #[tlv(private, primitive, number = "0x44", slice)] x: [u8; 1234], #[tlv(simple = "0x55", slice)] a: [u8; 5], } #[test] fn derive_untagged() { let mut x = [0u8; 1234]; for (i, x) in x.iter_mut().enumerate() { *x = i as _; }; let t = T2 { x, a: [17u8; 5] }; let mut buf = [0u8; 1500]; let encoded = t.encode_to_slice(&mut buf).unwrap(); assert_eq!(&encoded[..5], [ // 1234 223, 0x44, 0x82, 0x04, 0xD2]); assert_eq!(&encoded[5..(encoded.len() - 7)], x); assert_eq!(&encoded[(encoded.len() - 7)..], [0x55, 5, 17, 17, 17, 17, 17]); let t2 = T2::from_bytes(encoded).unwrap(); assert_eq!(t, t2); } #[derive(Clone, Copy)] pub struct PinUsagePolicy { piv_pin: bool, global_pin: bool, on_card_biometric_comparison: bool, has_virtual_contact_interface: bool, pairing_code_required_for_vci: Option, cardholder_prefers_global_pin: Option, } impl Default for PinUsagePolicy { fn default() -> Self { Self { piv_pin: true, global_pin: false, on_card_biometric_comparison: false, has_virtual_contact_interface: false, pairing_code_required_for_vci: None, cardholder_prefers_global_pin: None, } } } impl Decodable<'_> for PinUsagePolicy { fn decode(decoder: &mut ber::Decoder<'_>) -> ber::Result { let raw: [u8; 2] = decoder.decode()?; let capabilities = raw[0]; let has_global_pin = capabilities & (1 << 5) != 0; let has_virtual_contact_interface = capabilities & (1 << 3) != 0; Ok(Self { piv_pin: capabilities & (1 << 6) != 0, global_pin: has_global_pin, on_card_biometric_comparison: capabilities & (1 << 4) != 0, has_virtual_contact_interface, pairing_code_required_for_vci: if has_virtual_contact_interface { Some(capabilities & (1 << 2) != 0) } else { None }, cardholder_prefers_global_pin: if has_global_pin { Some(raw[1] == 0x20) } else { None }, }) } } impl Encodable for PinUsagePolicy { fn encoded_length(&self) -> ber::Result { Ok(2u8.into()) } fn encode(&self, encoder: &mut ber::Encoder<'_>) -> ber::Result<()> { let mut first_byte = 0u8; if self.piv_pin { first_byte |= 1 << 6; } if self.global_pin { first_byte |= 1 << 5; } if self.on_card_biometric_comparison { first_byte |= 1 << 4; } if self.has_virtual_contact_interface { first_byte |= 1 << 3; } if self.has_virtual_contact_interface && Some(true) == self.pairing_code_required_for_vci { first_byte |= 1 << 2; } let mut second_byte = 0u8; if self.global_pin { if let Some(prefers_global) = self.cardholder_prefers_global_pin { if prefers_global { second_byte = 0x20; } else { second_byte = 0x10; } } } encoder.encode(&[first_byte, second_byte]) } } #[derive(Decodable, Encodable)] #[tlv(application, constructed, number = "0x1E")] // = 0x7E pub struct DiscoveryObject { #[tlv(slice, application, number = "0xF")] piv_card_application_aid: [u8; 11], #[tlv(application, number = "0x2f")] pin_usage_policy: PinUsagePolicy, } impl Default for DiscoveryObject { fn default() -> Self { Self { piv_card_application_aid: hex_literal::hex!("A000000308 00001000 0100"), pin_usage_policy: Default::default(),//[0x40, 0x00], } } } #[test] fn discovery() { let disco = DiscoveryObject::default(); let mut buf = [0u8; 64]; let encoded = disco.encode_to_slice(&mut buf).unwrap(); assert_eq!(encoded, hex_literal::hex!("7e124f0ba0000003080000100001005f2f024000")); }