openpgp_card/ocard/data/
application_id.rs

1// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4//! 4.2.1 Application Identifier (AID)
5
6use 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    /// Mapping of manufacturer id to a name, data from:
59    /// <https://en.wikipedia.org/wiki/OpenPGP_card> [2022-04-07]
60    ///
61    /// Also see:
62    /// <https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=scd/app-openpgp.c;hb=HEAD#l292>
63    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    /// This ident is constructed as the concatenation of manufacturer
97    /// id, a colon, and the card serial (in hexadecimal representation,
98    /// with uppercase hex digits).
99    ///
100    /// It is a more easily human-readable, shorter form of the full
101    /// 16-byte AID ("Application Identifier").
102    ///
103    /// Example: "1234:5678ABCD".
104    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}