use crate::card::{Card, Retries};
use crate::data::{
ApIdentification, CardVerifiableCertificate, Date, Image, KeyId, RsaPublicKey, Sex, TlvFields,
malformed,
};
use crate::error::{Error, Result};
use crate::pin::Pin;
use crate::transport::Transmit;
pub const DF: [u8; 10] = [0xD3, 0x92, 0x10, 0x00, 0x31, 0x00, 0x01, 0x01, 0x04, 0x02];
pub mod ef {
pub const AGE_RECORD: u16 = 0x0001;
pub const CARD_FACE: u16 = 0x0002;
pub const AP_BASIC_DATA: u16 = 0x0003;
pub const CERTIFICATE: u16 = 0x0004;
pub const MY_NUMBER_IMAGE: u16 = 0x0005;
pub const UNKNOWN_0006: u16 = 0x0006;
pub const BIRTH_DATE: u16 = 0x0011;
pub const CODE_B: u16 = 0x0012;
pub const CODE_A: u16 = 0x0013;
}
#[derive(Debug)]
pub struct SurfaceAp<'a, T> {
card: &'a mut Card<T>,
}
impl<'a, T: Transmit> SurfaceAp<'a, T> {
pub fn select(card: &'a mut Card<T>) -> Result<Self> {
card.select_df(&DF)?;
Ok(SurfaceAp { card })
}
pub fn card(&mut self) -> &mut Card<T> {
self.card
}
pub fn read_ef(&mut self, id: u16) -> Result<Vec<u8>> {
self.card.select_ef(id)?;
self.card.read_binary_all()
}
pub fn read_ap_basic_data(&mut self) -> Result<ApBasicData> {
let raw = self.read_ef(ef::AP_BASIC_DATA)?;
ApBasicData::parse(&raw)
}
pub fn read_age_record(&mut self) -> Result<AgeRecord> {
let raw = self.read_ef(ef::AGE_RECORD)?;
AgeRecord::parse(&raw)
}
pub fn read_card_face(&mut self) -> Result<CardFace> {
let raw = self.read_ef(ef::CARD_FACE)?;
CardFace::parse(&raw)
}
pub fn read_my_number_image(&mut self) -> Result<MyNumberImage> {
let raw = self.read_ef(ef::MY_NUMBER_IMAGE)?;
MyNumberImage::parse(&raw)
}
pub fn read_certificate(&mut self) -> Result<CardVerifiableCertificate> {
let raw = self.read_ef(ef::CERTIFICATE)?;
CardVerifiableCertificate::parse(&raw)
}
#[cfg(feature = "verify")]
pub fn sign(&mut self, data: &[u8]) -> Result<Vec<u8>> {
let digest_info = crate::data::sha256_digest_info(&crate::data::sha256(data));
self.card.call_ok(&crate::apdu::Command::with_data_le(
0x80,
crate::card::ins::COMPUTE_SIGNATURE,
0x00,
0x00,
digest_info,
256,
))
}
pub fn verify_birth_date(&mut self, code: &Pin) -> Result<()> {
self.card.select_ef(ef::BIRTH_DATE)?;
self.card.verify(code)
}
pub fn verify_code_a(&mut self, code: &Pin) -> Result<()> {
self.card.select_ef(ef::CODE_A)?;
self.card.verify(code)
}
pub fn verify_code_b(&mut self, code: &Pin) -> Result<()> {
self.card.select_ef(ef::CODE_B)?;
self.card.verify(code)
}
pub fn retries(&mut self, key: u16) -> Result<Retries> {
self.card.select_ef(key)?;
self.card.pin_retries()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ApBasicData {
pub identification: ApIdentification,
pub public_key_id: KeyId,
pub version: u8,
pub municipality_code: String,
pub encrypted_reference_number: EncryptedReferenceNumber,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EncryptedReferenceNumber {
pub key_id: KeyId,
pub data: Vec<u8>,
}
impl ApBasicData {
pub const TAG: u32 = 0xFF30;
pub fn parse(raw: &[u8]) -> Result<Self> {
let f = TlvFields::parse(raw, Self::TAG, None)?;
let version = f.get(0xDF33)?;
let df35 = f.get(0xDF35)?;
let (key_id, data) = df35.split_at_checked(KeyId::LEN).ok_or_else(|| {
Error::Malformed(format!(
"DF35 is {} bytes, too short to contain its 16 byte reference",
df35.len()
))
})?;
Ok(ApBasicData {
identification: ApIdentification::parse(f.get(0xDF31)?)?,
public_key_id: KeyId::parse(f.get(0xDF32)?)?,
version: *version
.first()
.ok_or_else(|| Error::Malformed("version field is empty".into()))?,
municipality_code: String::from_utf8_lossy(f.get(0xDF34)?).into_owned(),
encrypted_reference_number: EncryptedReferenceNumber {
key_id: KeyId::parse(key_id)?,
data: data.to_vec(),
},
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AgeRecord {
pub birth_date: Date,
pub public_key: RsaPublicKey,
pub signature: Vec<u8>,
pub signed_data: Vec<u8>,
}
impl AgeRecord {
pub const TAG: u32 = 0xFF10;
pub fn parse(raw: &[u8]) -> Result<Self> {
let f = TlvFields::parse(raw, Self::TAG, None)?;
Ok(AgeRecord {
birth_date: Date::parse(f.get(0xDF11)?)?,
public_key: RsaPublicKey::parse(f.get(0xDF12)?)?,
signature: f.get(0xDF13)?.to_vec(),
signed_data: f.bytes_before(0xDF13)?.to_vec(),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CardFace {
pub birth_date: Date,
pub sex: Sex,
pub public_key: RsaPublicKey,
pub name_image: Image,
pub address_image: Image,
pub photo: Image,
pub signature: Vec<u8>,
pub expiry: Date,
pub security_code_image: Image,
pub signed_segments: [Vec<u8>; 3],
}
impl CardFace {
pub const TAG: u32 = 0xFF20;
pub const TAG_OFFSETS: u32 = 0xDF21;
pub fn parse(raw: &[u8]) -> Result<Self> {
let f = TlvFields::parse(raw, Self::TAG, Some(Self::TAG_OFFSETS))?;
Ok(CardFace {
birth_date: Date::parse(f.get(0xDF22)?)?,
sex: Sex::from_byte(
*f.get(0xDF23)?
.first()
.ok_or_else(|| malformed("性別 is empty"))?,
),
public_key: RsaPublicKey::parse(f.get(0xDF24)?)?,
name_image: Image::new(f.get(0xDF25)?.to_vec()),
address_image: Image::new(f.get(0xDF26)?.to_vec()),
photo: Image::new(f.get(0xDF27)?.to_vec()),
signature: f.get(0xDF28)?.to_vec(),
expiry: Date::parse(f.get(0xDF29)?)?,
security_code_image: Image::new(f.get(0xDF2A)?.to_vec()),
signed_segments: [
f.bytes_of(&[0xDF22, 0xDF23, 0xDF24])?,
f.bytes_of(&[0xDF25, 0xDF26])?,
f.bytes_of(&[0xDF27])?,
],
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MyNumberImage {
pub image: Image,
pub public_key: RsaPublicKey,
pub signature: Vec<u8>,
pub signed_data: Vec<u8>,
}
impl MyNumberImage {
pub const TAG: u32 = 0xFF40;
pub fn parse(raw: &[u8]) -> Result<Self> {
let f = TlvFields::parse(raw, Self::TAG, None)?;
Ok(MyNumberImage {
image: Image::new(f.get(0xDF41)?.to_vec()),
public_key: RsaPublicKey::parse(f.get(0xDF42)?)?,
signature: f.get(0xDF43)?.to_vec(),
signed_data: f.bytes_before(0xDF43)?.to_vec(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::data::ImageFormat;
fn tlv(tag: u16, value: &[u8]) -> Vec<u8> {
let mut out = tag.to_be_bytes().to_vec();
if value.len() < 0x80 {
out.push(value.len() as u8);
} else {
out.push(0x82);
out.extend_from_slice(&(value.len() as u16).to_be_bytes());
}
out.extend_from_slice(value);
out
}
fn public_key() -> Vec<u8> {
let mut k = vec![0x90, 0x03, 0x01, 0x00, 0x01, 0x91, 0x82, 0x01, 0x00, 0xC9];
k.extend(std::iter::repeat_n(0xAA, 255));
k
}
fn png() -> Vec<u8> {
let mut p = b"\x89PNG\r\n\x1a\n".to_vec();
p.extend_from_slice(b"\x00\x00\x00\x0DIHDR\x00\x00\x00\x48\x00\x00\x00\x0C\x01\x00");
p
}
fn with_offsets(outer_tag: u16, table_tag: u16, fields: &[Vec<u8>]) -> Vec<u8> {
let table_len = fields.len() * 2;
let table = tlv(table_tag, &vec![0u8; table_len]);
let body_len = table.len() + fields.iter().map(Vec::len).sum::<usize>();
let header_len = if body_len < 0x80 { 3 } else { 5 };
let mut offsets = Vec::new();
let mut pos = header_len + table.len();
for f in fields {
offsets.extend_from_slice(&(pos as u16).to_be_bytes());
pos += f.len();
}
let mut body = tlv(table_tag, &offsets);
for f in fields {
body.extend_from_slice(f);
}
tlv(outer_tag, &body)
}
#[test]
fn parses_the_age_record() {
let mut body = tlv(0xDF11, b"19800217");
body.extend_from_slice(&tlv(0xDF12, &public_key()));
body.extend_from_slice(&tlv(0xDF13, &[0xBC; 256]));
let raw = tlv(0xFF10, &body);
let rec = AgeRecord::parse(&raw).unwrap();
assert_eq!(
rec.birth_date,
Date {
year: 1980,
month: 2,
day: 17
}
);
assert_eq!(rec.public_key.bits(), 2048);
assert_eq!(rec.signature.len(), 256);
}
#[test]
fn parses_the_card_face() {
let raw = with_offsets(
0xFF20,
0xDF21,
&[
tlv(0xDF22, b"19800217"),
tlv(0xDF23, b"1"),
tlv(0xDF24, &public_key()),
tlv(0xDF25, &png()),
tlv(0xDF26, &png()),
tlv(0xDF27, b"\x00\x00\x00\x0CjP \r\n\x87\n"),
tlv(0xDF28, &[0xBC; 256]),
tlv(0xDF29, b"20350217"),
tlv(0xDF2A, &png()),
],
);
let face = CardFace::parse(&raw).unwrap();
assert_eq!(
face.birth_date,
Date {
year: 1980,
month: 2,
day: 17
}
);
assert_eq!(face.sex, Sex::Male);
assert_eq!(
face.expiry,
Date {
year: 2035,
month: 2,
day: 17
}
);
assert_eq!(face.name_image.format, ImageFormat::Png);
assert_eq!(face.photo.format, ImageFormat::Jpeg2000);
assert_eq!(face.signature.len(), 256);
}
#[test]
fn parses_the_my_number_image() {
let mut body = tlv(0xDF41, &png());
body.extend_from_slice(&tlv(0xDF42, &public_key()));
body.extend_from_slice(&tlv(0xDF43, &[0xBC; 256]));
let raw = tlv(0xFF40, &body);
let img = MyNumberImage::parse(&raw).unwrap();
assert_eq!(img.image.format, ImageFormat::Png);
assert_eq!(img.public_key.bits(), 2048);
}
#[test]
fn a_wrong_offset_table_is_rejected() {
let mut raw = with_offsets(
0xFF20,
0xDF21,
&[
tlv(0xDF22, b"19800217"),
tlv(0xDF23, b"1"),
tlv(0xDF24, &public_key()),
tlv(0xDF25, &png()),
tlv(0xDF26, &png()),
tlv(0xDF27, b"\x00\x00\x00\x0CjP \r\n\x87\n"),
tlv(0xDF28, &[0xBC; 256]),
tlv(0xDF29, b"20350217"),
tlv(0xDF2A, &png()),
],
);
let i = raw.iter().position(|&b| b == 0xDF).unwrap() + 3 + 1;
raw[i] = raw[i].wrapping_add(1);
assert!(CardFace::parse(&raw).is_err());
}
}
#[cfg(feature = "verify")]
mod verify {
use super::{AgeRecord, CardFace, MyNumberImage};
use crate::data::{RsaPublicKey, sha256, sha256_digest_info};
use crate::error::Result;
impl AgeRecord {
pub fn verify(&self, issuer: &RsaPublicKey) -> Result<()> {
issuer.verify_pkcs1_sha256(&self.signed_data, &self.signature)
}
}
impl MyNumberImage {
pub fn verify(&self, issuer: &RsaPublicKey) -> Result<()> {
issuer.verify_pkcs1_sha256(&self.signed_data, &self.signature)
}
}
impl CardFace {
pub fn verify(&self, issuer: &RsaPublicKey) -> Result<()> {
let mut digests = Vec::with_capacity(96);
for segment in &self.signed_segments {
digests.extend_from_slice(&sha256(segment));
}
issuer.verify_pkcs1(&sha256_digest_info(&digests), &self.signature)
}
}
}