96 lines
2.4 KiB
Rust
96 lines
2.4 KiB
Rust
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
|
|
|
//! 4.2.1 Application Identifier (AID)
|
|
|
|
use anyhow::Result;
|
|
use nom::{bytes::complete as bytes, number::complete as number};
|
|
use std::convert::TryFrom;
|
|
|
|
use crate::card_do::{complete, ApplicationIdentifier};
|
|
|
|
fn parse(input: &[u8]) -> nom::IResult<&[u8], ApplicationIdentifier> {
|
|
let (input, _) = bytes::tag([0xd2, 0x76, 0x0, 0x1, 0x24])(input)?;
|
|
|
|
let (input, application) = number::u8(input)?;
|
|
let (input, version) = number::be_u16(input)?;
|
|
let (input, manufacturer) = number::be_u16(input)?;
|
|
let (input, serial) = number::be_u32(input)?;
|
|
|
|
let (input, _) =
|
|
nom::combinator::all_consuming(bytes::tag([0x0, 0x0]))(input)?;
|
|
|
|
Ok((
|
|
input,
|
|
ApplicationIdentifier {
|
|
application,
|
|
version,
|
|
manufacturer,
|
|
serial,
|
|
},
|
|
))
|
|
}
|
|
|
|
impl TryFrom<&[u8]> for ApplicationIdentifier {
|
|
type Error = anyhow::Error;
|
|
|
|
fn try_from(data: &[u8]) -> Result<Self> {
|
|
complete(parse(data))
|
|
}
|
|
}
|
|
|
|
impl ApplicationIdentifier {
|
|
pub fn application(&self) -> u8 {
|
|
self.application
|
|
}
|
|
|
|
pub fn version(&self) -> u16 {
|
|
self.version
|
|
}
|
|
|
|
pub fn manufacturer(&self) -> u16 {
|
|
self.manufacturer
|
|
}
|
|
|
|
pub fn serial(&self) -> u32 {
|
|
self.serial
|
|
}
|
|
|
|
/// This ident is constructed as the concatenation of manufacturer
|
|
/// id, a colon, and the card serial (in hexadecimal representation,
|
|
/// with uppercase hex digits).
|
|
///
|
|
/// It is a more easily human-readable, shorter form of the full
|
|
/// 16-byte AID ("Application Identifier").
|
|
///
|
|
/// Example: "1234:5678ABCD".
|
|
pub fn ident(&self) -> String {
|
|
format!("{:04X}:{:08X}", self.manufacturer, self.serial)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_gnuk() {
|
|
let data = [
|
|
0xd2, 0x76, 0x0, 0x1, 0x24, 0x1, 0x2, 0x0, 0xff, 0xfe, 0x43, 0x19,
|
|
0x42, 0x40, 0x0, 0x0,
|
|
];
|
|
|
|
let aid = ApplicationIdentifier::try_from(&data[..])
|
|
.expect("failed to parse application id");
|
|
|
|
assert_eq!(
|
|
aid,
|
|
ApplicationIdentifier {
|
|
application: 0x1,
|
|
version: 0x200,
|
|
manufacturer: 0xfffe,
|
|
serial: 0x43194240,
|
|
}
|
|
);
|
|
}
|
|
}
|