openpgp_card/ocard/data/
application_id.rs1use std::convert::TryFrom;
7
8use nom::{bytes::complete as bytes, number::complete as number};
9
10use crate::ocard::data::{complete, ApplicationIdentifier};
11
12fn parse(input: &[u8]) -> nom::IResult<&[u8], ApplicationIdentifier> {
13 let (input, _) = bytes::tag([0xd2, 0x76, 0x0, 0x1, 0x24])(input)?;
14
15 let (input, application) = number::u8(input)?;
16 let (input, version) = number::be_u16(input)?;
17 let (input, manufacturer) = number::be_u16(input)?;
18 let (input, serial) = number::be_u32(input)?;
19
20 let (input, _) = nom::combinator::all_consuming(bytes::tag([0x0, 0x0]))(input)?;
21
22 Ok((
23 input,
24 ApplicationIdentifier {
25 application,
26 version,
27 manufacturer,
28 serial,
29 },
30 ))
31}
32
33impl TryFrom<&[u8]> for ApplicationIdentifier {
34 type Error = crate::Error;
35
36 fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
37 complete(parse(data))
38 }
39}
40
41impl ApplicationIdentifier {
42 pub fn application(&self) -> u8 {
43 self.application
44 }
45
46 pub fn version(&self) -> u16 {
47 self.version
48 }
49
50 pub fn manufacturer(&self) -> u16 {
51 self.manufacturer
52 }
53
54 pub fn serial(&self) -> u32 {
55 self.serial
56 }
57
58 pub fn manufacturer_name(&self) -> &'static str {
64 match self.manufacturer {
65 0x0000 => "Testcard",
66 0x0001 => "PPC Card Systems",
67 0x0002 => "Prism Payment Technologies",
68 0x0003 => "OpenFortress Digital signatures",
69 0x0004 => "Wewid AB",
70 0x0005 => "ZeitControl cardsystems GmbH",
71 0x0006 => "Yubico AB",
72 0x0007 => "OpenKMS",
73 0x0008 => "LogoEmail",
74 0x0009 => "Fidesmo AB",
75 0x000A => "Dangerous Things",
76 0x000F => "Nitrokey GmbH",
77 0x000B => "Feitian Technologies",
78 0x002A => "Magrathea",
79 0x0042 => "GnuPG e.V.",
80 0x1337 => "Warsaw Hackerspace",
81 0x2342 => "warpzone e.V.",
82 0x4354 => "Confidential Technologies",
83 0x5443 => "TIF-IT e.V.",
84 0x63AF => "Trustica s.r.o",
85 0xBA53 => "c-base e.V.",
86 0xBD0E => "Paranoidlabs",
87 0xF1D0 => "CanoKeys",
88 0xF517 => "Free Software Initiative of Japan",
89 0xF5EC => "F-Secure",
90 0xFF00..=0xFFFE => "Range reserved for randomly assigned serial numbers.",
91 0xFFFF => "Testcard",
92 _ => "Unknown",
93 }
94 }
95
96 pub fn ident(&self) -> String {
105 format!("{:04X}:{:08X}", self.manufacturer, self.serial)
106 }
107}
108
109#[cfg(test)]
110mod test {
111 use super::*;
112
113 #[test]
114 fn test_gnuk() {
115 let data = [
116 0xd2, 0x76, 0x0, 0x1, 0x24, 0x1, 0x2, 0x0, 0xff, 0xfe, 0x43, 0x19, 0x42, 0x40, 0x0, 0x0,
117 ];
118
119 let aid =
120 ApplicationIdentifier::try_from(&data[..]).expect("failed to parse application id");
121
122 assert_eq!(
123 aid,
124 ApplicationIdentifier {
125 application: 0x1,
126 version: 0x200,
127 manufacturer: 0xfffe,
128 serial: 0x43194240,
129 }
130 );
131 }
132}