Skip to main content

myna_card/
data.rs

1//! The values the card stores, and the credentials derived from them.
2//!
3//! JICSAP specifies the containers — transparent and record structured files, and the two TLV
4//! encodings — but says nothing about what any application puts inside them, so every layout here
5//! was established by reading a physical card and is described on the type that parses it.
6
7use std::fmt;
8
9use crate::error::{Error, Result};
10use crate::pin::Pin;
11use crate::tlv::ber;
12
13/// The four-byte identification field in an application's basic-data file.
14///
15/// The bytes are stored in this order:
16///
17/// ```text
18/// 00  specification version
19/// 01  extended Lc/Le support status
20/// 02  vendor identifier
21/// 03  vendor-specific value
22/// ```
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24pub struct ApIdentification {
25    /// Byte 0: specification version.
26    pub specification_version: u8,
27    /// Byte 1: extended Lc/Le support status.
28    pub extended_lc_le_support: u8,
29    /// Byte 2: vendor identifier.
30    pub vendor_id: u8,
31    /// Byte 3: vendor-specific value.
32    pub vendor_specific: u8,
33}
34
35impl ApIdentification {
36    /// Encoded length of the field.
37    pub const LEN: usize = 4;
38
39    /// Parse the four bytes of an application-identification field.
40    ///
41    /// # Errors
42    ///
43    /// [`Error::Malformed`] if `bytes` is not exactly four bytes long.
44    pub fn parse(bytes: &[u8]) -> Result<Self> {
45        let [
46            specification_version,
47            extended_lc_le_support,
48            vendor_id,
49            vendor_specific,
50        ] = <[u8; Self::LEN]>::try_from(bytes).map_err(|_| {
51            malformed(&format!(
52                "AP identification must be 4 bytes, got {}",
53                bytes.len()
54            ))
55        })?;
56        Ok(Self {
57            specification_version,
58            extended_lc_le_support,
59            vendor_id,
60            vendor_specific,
61        })
62    }
63
64    /// Encode the field in its original byte order.
65    pub const fn to_bytes(self) -> [u8; Self::LEN] {
66        [
67            self.specification_version,
68            self.extended_lc_le_support,
69            self.vendor_id,
70            self.vendor_specific,
71        ]
72    }
73}
74
75/// A calendar date, as the card writes it: eight ASCII digits, `YYYYMMDD`.
76#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub struct Date {
78    /// Gregorian year.
79    pub year: u16,
80    /// Month, 1 to 12.
81    pub month: u8,
82    /// Day, 1 to 31.
83    pub day: u8,
84}
85
86impl Date {
87    /// Parse eight ASCII digits, `YYYYMMDD`.
88    pub fn parse(bytes: &[u8]) -> Result<Self> {
89        let text = std::str::from_utf8(bytes)
90            .ok()
91            .filter(|s| s.len() == 8 && s.bytes().all(|b| b.is_ascii_digit()))
92            .ok_or_else(|| malformed(&format!("expected 8 digits, got {}", hex(bytes))))?;
93        let date = Date {
94            year: text[0..4].parse().unwrap(),
95            month: text[4..6].parse().unwrap(),
96            day: text[6..8].parse().unwrap(),
97        };
98        if !(1..=12).contains(&date.month) || !(1..=31).contains(&date.day) {
99            return Err(malformed(&format!("not a calendar date: {date}")));
100        }
101        Ok(date)
102    }
103
104    /// The date a Unix timestamp falls on, in UTC.
105    ///
106    /// Used for certificate validity, which the card records to the second; the time of day is
107    /// dropped.
108    pub fn from_unix_seconds(seconds: i64) -> Self {
109        // Howard Hinnant's civil_from_days, with the era shifted so March starts the year and
110        // the leap day lands at the end of it.
111        let days = seconds.div_euclid(86_400) + 719_468;
112        let era = days.div_euclid(146_097);
113        let doe = days.rem_euclid(146_097);
114        let yoe = (doe - doe / 1460 + doe / 36_524 - doe / 146_096) / 365;
115        let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
116        let mp = (5 * doy + 2) / 153;
117        let day = (doy - (153 * mp + 2) / 5 + 1) as u8;
118        let month = if mp < 10 { mp + 3 } else { mp - 9 } as u8;
119        let year = (yoe + era * 400 + i64::from(month <= 2)) as u16;
120        Date { year, month, day }
121    }
122
123    /// The Japanese era this date falls in, and the year within it.
124    ///
125    /// `None` before the Meiji era began on 1868-01-25.
126    pub fn to_era(self) -> Option<(Era, u16)> {
127        let key = (self.year, self.month, self.day);
128        let era = match key {
129            k if k >= (2019, 5, 1) => Era::Reiwa,
130            k if k >= (1989, 1, 8) => Era::Heisei,
131            k if k >= (1926, 12, 25) => Era::Showa,
132            k if k >= (1912, 7, 30) => Era::Taisho,
133            k if k >= (1868, 1, 25) => Era::Meiji,
134            _ => return None,
135        };
136        Some((era, self.year - era.first_gregorian_year() + 1))
137    }
138}
139
140impl fmt::Display for Date {
141    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142        write!(f, "{:04}-{:02}-{:02}", self.year, self.month, self.day)
143    }
144}
145
146/// A Japanese era.
147#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
148#[allow(missing_docs)]
149pub enum Era {
150    Meiji,
151    Taisho,
152    Showa,
153    Heisei,
154    Reiwa,
155}
156
157impl Era {
158    /// The Gregorian year in which era year 1 falls.
159    pub const fn first_gregorian_year(self) -> u16 {
160        match self {
161            Era::Meiji => 1868,
162            Era::Taisho => 1912,
163            Era::Showa => 1926,
164            Era::Heisei => 1989,
165            Era::Reiwa => 2019,
166        }
167    }
168
169    /// The era's name in Japanese.
170    pub const fn name(self) -> &'static str {
171        match self {
172            Era::Meiji => "明治",
173            Era::Taisho => "大正",
174            Era::Showa => "昭和",
175            Era::Heisei => "平成",
176            Era::Reiwa => "令和",
177        }
178    }
179}
180
181/// Sex, as one ASCII digit.
182///
183/// The card follows JIS X 0303. Only `1` has been seen on a real card; the rest are decoded from
184/// the standard, and anything else is preserved rather than rejected.
185#[derive(Debug, Clone, Copy, PartialEq, Eq)]
186pub enum Sex {
187    /// `1`.
188    Male,
189    /// `2`.
190    Female,
191    /// `0` — not known.
192    Unknown,
193    /// `9` — not applicable.
194    NotApplicable,
195    /// Anything else, kept as written.
196    Other(u8),
197}
198
199impl Sex {
200    /// Decode the single byte the card stores.
201    pub const fn from_byte(b: u8) -> Self {
202        match b {
203            b'0' => Sex::Unknown,
204            b'1' => Sex::Male,
205            b'2' => Sex::Female,
206            b'9' => Sex::NotApplicable,
207            other => Sex::Other(other),
208        }
209    }
210}
211
212/// An 個人番号 — twelve decimal digits.
213///
214/// Also the value of 照合番号A; see [`MyNumber::as_verification_code_a`].
215#[derive(Clone, PartialEq, Eq)]
216pub struct MyNumber([u8; 12]);
217
218impl MyNumber {
219    /// Parse twelve ASCII digits.
220    pub fn parse(bytes: &[u8]) -> Result<Self> {
221        let digits: [u8; 12] = bytes
222            .try_into()
223            .ok()
224            .filter(|d: &[u8; 12]| d.iter().all(u8::is_ascii_digit))
225            .ok_or_else(|| malformed(&format!("個人番号 must be 12 digits, got {}", hex(bytes))))?;
226        Ok(MyNumber(digits))
227    }
228
229    /// The twelve digits, as ASCII.
230    pub fn as_bytes(&self) -> &[u8; 12] {
231        &self.0
232    }
233
234    /// The twelve digits, as a string.
235    pub fn as_str(&self) -> &str {
236        // Every byte was checked to be an ASCII digit when this was built.
237        std::str::from_utf8(&self.0).expect("digits are ASCII")
238    }
239
240    /// 照合番号A, which is the 個人番号 itself.
241    ///
242    /// Confirmed on a card: this value unlocks 券面入力補助AP `0001`, and that file returns the
243    /// same twelve digits.
244    pub fn as_verification_code_a(&self) -> Result<Pin> {
245        Pin::numeric(self.0)
246    }
247}
248
249/// Redacted; an 個人番号 should not reach a log by accident.
250impl fmt::Debug for MyNumber {
251    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252        write!(f, "MyNumber(<12 digits redacted>)")
253    }
254}
255
256/// Build 照合番号B from the three things printed on the card.
257///
258/// Fourteen digits: the date of birth as `YYMMDD` in the **Japanese era year**, the Gregorian year
259/// the card expires, and the four digit security code. Confirmed on a card — a date of birth of
260/// 1980-02-17 (昭和55) with an expiry in 2035 and security code `2285` gives `55021720352285`.
261///
262/// # Only four of the fourteen digits are off the chip
263///
264/// 照合番号A opens 券面事項確認AP `0002`, and that file carries both the date of birth and the
265/// expiry — the first ten digits of this value, confirmed by reading `2035` out of it on the card
266/// the example above comes from. A party holding 照合番号A, which is the 個人番号, therefore has
267/// everything here but the security code, and that is four digits against a counter of ten
268/// attempts.
269///
270/// The consequence is smaller than it first sounds, because 照合番号A already opens the rendered
271/// card face: what 照合番号B adds is the 基本4情報 as UTF-8 rather than as an image of the same
272/// fields. It is worth knowing all the same that the two 照合番号 are not independent secrets.
273///
274/// # Errors
275///
276/// Returns [`Error::Malformed`] if the date of birth predates the Meiji era or its era year
277/// exceeds two digits, and [`Error::InvalidPin`] if the security code is not four digits.
278pub fn verification_code_b(
279    birth_date: Date,
280    expiry_year: u16,
281    security_code: &[u8],
282) -> Result<Pin> {
283    let (_, era_year) = birth_date
284        .to_era()
285        .ok_or_else(|| malformed(&format!("{birth_date} predates the Meiji era")))?;
286    if era_year > 99 {
287        return Err(malformed(&format!(
288            "era year {era_year} does not fit in two digits"
289        )));
290    }
291    if security_code.len() != 4 || !security_code.iter().all(u8::is_ascii_digit) {
292        return Err(Error::InvalidPin("security code must be 4 digits"));
293    }
294    let text = format!(
295        "{:02}{:02}{:02}{:04}{}",
296        era_year,
297        birth_date.month,
298        birth_date.day,
299        expiry_year,
300        std::str::from_utf8(security_code).expect("digits are ASCII"),
301    );
302    Pin::numeric(text)
303}
304
305/// An RSA public key, as the card stores it: tag `90` for the exponent, `91` for the modulus.
306#[derive(Debug, Clone, PartialEq, Eq)]
307pub struct RsaPublicKey {
308    /// Public exponent, big-endian.
309    pub exponent: Vec<u8>,
310    /// Modulus, big-endian.
311    pub modulus: Vec<u8>,
312}
313
314impl RsaPublicKey {
315    /// Tag of the public exponent.
316    pub const TAG_EXPONENT: u32 = 0x90;
317    /// Tag of the modulus.
318    pub const TAG_MODULUS: u32 = 0x91;
319
320    /// Parse the concatenated `90` and `91` objects.
321    pub fn parse(data: &[u8]) -> Result<Self> {
322        let mut exponent = None;
323        let mut modulus = None;
324        for tlv in ber::iter(data) {
325            let tlv = tlv?;
326            match tlv.tag {
327                Self::TAG_EXPONENT => exponent = Some(tlv.value.to_vec()),
328                Self::TAG_MODULUS => modulus = Some(tlv.value.to_vec()),
329                _ => {}
330            }
331        }
332        Ok(RsaPublicKey {
333            exponent: exponent.ok_or_else(|| malformed("no public exponent (tag 90)"))?,
334            modulus: modulus.ok_or_else(|| malformed("no modulus (tag 91)"))?,
335        })
336    }
337
338    /// Modulus size in bits, which is the key size.
339    pub fn bits(&self) -> usize {
340        match self.modulus.iter().position(|&b| b != 0) {
341            Some(first) => {
342                (self.modulus.len() - first) * 8 - self.modulus[first].leading_zeros() as usize
343            }
344            None => 0,
345        }
346    }
347}
348
349/// A 16 byte key identifier — 証明者鍵ID, 被証明者鍵ID, and the references the 券面 applications'
350/// basic information files carry.
351///
352/// ```text
353/// "6000024" 08 05 "001" 00 00 00 00
354///  ^^^^^^^ number      ^^^ group    ^^^^^^^^^^^ padding, whose last byte is not always zero
355/// ```
356///
357/// It names a *key*, not an issuer: the same organisation appears under several of these. The
358/// leading digit separates hierarchies — production identifiers begin `5`, the JPKI test
359/// hierarchy's begin `6`.
360///
361/// Comparison and lookup use all 16 bytes, so a certificate from one hierarchy never resolves to
362/// the other's key by accident.
363#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
364pub struct KeyId([u8; Self::LEN]);
365
366impl KeyId {
367    /// Length of the identifier.
368    pub const LEN: usize = 16;
369
370    /// Take the identifier from exactly 16 bytes.
371    ///
372    /// # Errors
373    ///
374    /// [`Error::Malformed`] if the slice is not 16 bytes long, or if the two digit groups are not
375    /// ASCII digits.
376    pub fn parse(bytes: &[u8]) -> Result<Self> {
377        let bytes: [u8; Self::LEN] = bytes.try_into().map_err(|_| {
378            malformed(&format!(
379                "key identifier must be 16 bytes, got {}",
380                bytes.len()
381            ))
382        })?;
383        if !bytes[..7].iter().all(u8::is_ascii_digit)
384            || !bytes[9..12].iter().all(u8::is_ascii_digit)
385        {
386            return Err(malformed("key identifier is not digits where it should be"));
387        }
388        Ok(KeyId(bytes))
389    }
390
391    /// The seven digit number that names the key.
392    pub fn number(&self) -> &str {
393        std::str::from_utf8(&self.0[..7]).unwrap_or("???????")
394    }
395
396    /// The three digit group that follows it.
397    pub fn group(&self) -> &str {
398        std::str::from_utf8(&self.0[9..12]).unwrap_or("???")
399    }
400
401    /// All 16 bytes.
402    pub fn as_bytes(&self) -> &[u8; Self::LEN] {
403        &self.0
404    }
405}
406
407impl fmt::Display for KeyId {
408    /// `6000024/001` — the two digit groups, which is what identifies the key to a reader.
409    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
410        write!(f, "{}/{}", self.number(), self.group())
411    }
412}
413
414impl fmt::Debug for KeyId {
415    /// The printable form plus the padding, since that is where two identifiers can differ
416    /// invisibly.
417    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
418        write!(f, "KeyId({self}")?;
419        for byte in &self.0[12..] {
420            write!(f, " {byte:02X}")?;
421        }
422        write!(f, ")")
423    }
424}
425
426/// A card-verifiable certificate, tag `7F21`.
427///
428/// Both 券面 applications keep the card's own certificate in EF `0004` in this format. The
429/// proprietary `80 A2` command takes a terminal's certificate in the same shape, checks it against
430/// the terminal CA key, and keeps the public key inside it. The command's formal name is unknown.
431///
432/// ```text
433/// 7F 21 82 02 33
434///   5F 4E 82 01 29   297 bytes:
435///                      16  証明者鍵ID
436///                      16  被証明者鍵ID
437///                     265  RSA-2048 public key (90 exponent, 91 modulus)
438///   5F 37 82 01 00   256 byte signature over those 297 bytes
439/// ```
440///
441/// The signing key is named by [`issuer_key_id`](Self::issuer_key_id) and is **not on the card**:
442/// a verifier is expected to hold the CA keys and look one up by that identifier. Production
443/// certificates name `"5000023"` (券面事項確認AP) and `"5000033"` (券面入力補助AP), and a JPKI test
444/// card names `"6000023"` and `"6000033"` instead. See [`crate::ca`].
445#[derive(Debug, Clone, PartialEq, Eq)]
446pub struct CardVerifiableCertificate {
447    /// 証明者鍵ID — which key signed this certificate.
448    pub issuer_key_id: KeyId,
449    /// 被証明者鍵ID — which key is being certified.
450    pub subject_key_id: KeyId,
451    /// The certified public key.
452    pub public_key: RsaPublicKey,
453    /// Signature over the body, tag `5F37`.
454    pub signature: Vec<u8>,
455    /// Exactly the bytes the signature covers: the `5F4E` value, without its own header.
456    pub signed_data: Vec<u8>,
457}
458
459impl CardVerifiableCertificate {
460    /// Tag of the whole certificate.
461    pub const TAG: u32 = 0x7F21;
462    /// Tag of the certificate body.
463    pub const TAG_BODY: u32 = 0x5F4E;
464    /// Tag of the signature.
465    pub const TAG_SIGNATURE: u32 = 0x5F37;
466    /// Length of each of the two key identifiers.
467    pub const KEY_ID_LEN: usize = 16;
468    /// Length of the body: two key identifiers and an RSA-2048 public key.
469    pub const BODY_LEN: usize = 297;
470
471    /// Parse a certificate, with or without its `7F21` template.
472    ///
473    /// A certificate read out of an EF carries the template. GET DATA hands back the template's
474    /// contents instead, so both forms turn up on the same card and both are accepted here.
475    pub fn parse(data: &[u8]) -> Result<Self> {
476        let contents = if data.starts_with(&[0x7F, 0x21]) {
477            let outer = ber::parse(data)?;
478            if outer.tag != Self::TAG {
479                return Err(malformed(&format!(
480                    "expected tag 7F21, got {:04X}",
481                    outer.tag
482                )));
483            }
484            outer.value
485        } else {
486            data
487        };
488        let mut body = None;
489        let mut signature = None;
490        for tlv in ber::iter(contents) {
491            let tlv = tlv?;
492            match tlv.tag {
493                Self::TAG_BODY => body = Some(tlv.value),
494                Self::TAG_SIGNATURE => signature = Some(tlv.value.to_vec()),
495                _ => {}
496            }
497        }
498        let body = body.ok_or_else(|| malformed("certificate has no body (tag 5F4E)"))?;
499        // Fixed size, because the key is: 16 + 16 + 265. Being strict here means a certificate
500        // that is not shaped like this card's is rejected rather than silently mis-split.
501        if body.len() != Self::BODY_LEN {
502            return Err(malformed(&format!(
503                "certificate body must be {} bytes, got {}",
504                Self::BODY_LEN,
505                body.len()
506            )));
507        }
508        let ids = 2 * Self::KEY_ID_LEN;
509        Ok(CardVerifiableCertificate {
510            issuer_key_id: KeyId::parse(&body[..Self::KEY_ID_LEN])?,
511            subject_key_id: KeyId::parse(&body[Self::KEY_ID_LEN..ids])?,
512            public_key: RsaPublicKey::parse(&body[ids..])?,
513            signature: signature
514                .ok_or_else(|| malformed("certificate has no signature (tag 5F37)"))?,
515            signed_data: body.to_vec(),
516        })
517    }
518}
519
520/// The format of an image the card stores.
521///
522/// Recognised from the magic bytes, because the card gives no other indication and the two are
523/// mixed within one file: the rendered text fields are PNG and the photograph is JPEG 2000.
524#[derive(Debug, Clone, Copy, PartialEq, Eq)]
525pub enum ImageFormat {
526    /// PNG. The rendered card-face fields are 1-bit greyscale.
527    Png,
528    /// JPEG 2000, in the JP2 container. The photograph.
529    Jpeg2000,
530    /// Not recognised.
531    Unknown,
532}
533
534impl ImageFormat {
535    /// Identify an image by its leading bytes.
536    pub fn detect(data: &[u8]) -> Self {
537        if data.starts_with(b"\x89PNG\r\n\x1a\n") {
538            ImageFormat::Png
539        } else if data.len() >= 8 && &data[4..8] == b"jP  " {
540            ImageFormat::Jpeg2000
541        } else {
542            ImageFormat::Unknown
543        }
544    }
545
546    /// The usual file extension.
547    pub const fn extension(self) -> &'static str {
548        match self {
549            ImageFormat::Png => "png",
550            ImageFormat::Jpeg2000 => "jp2",
551            ImageFormat::Unknown => "bin",
552        }
553    }
554}
555
556/// An image read from the card, with its format already identified.
557#[derive(Debug, Clone, PartialEq, Eq)]
558pub struct Image {
559    /// Encoded image data, exactly as the card stores it.
560    pub data: Vec<u8>,
561    /// Which encoding that is.
562    pub format: ImageFormat,
563}
564
565impl Image {
566    /// Wrap image bytes, identifying the format.
567    pub fn new(data: Vec<u8>) -> Self {
568        let format = ImageFormat::detect(&data);
569        Image { data, format }
570    }
571}
572
573/// Read a `u16` offset table, and check it against where the objects actually start.
574///
575/// Both 券面 applications open their data files with one: a list of big-endian `u16` offsets from
576/// the first byte of the file to each following object. Verifying it is a cheap integrity check on
577/// a parse that is otherwise all reverse engineering.
578pub(crate) fn check_offsets(file: &[u8], table: &[u8], starts: &[usize]) -> Result<()> {
579    if table.len() != starts.len() * 2 {
580        return Err(malformed(&format!(
581            "offset table is {} bytes for {} objects",
582            table.len(),
583            starts.len()
584        )));
585    }
586    for (i, (chunk, &start)) in table.chunks_exact(2).zip(starts).enumerate() {
587        let declared = usize::from(u16::from_be_bytes([chunk[0], chunk[1]]));
588        if declared != start {
589            return Err(malformed(&format!(
590                "offset {i} says {declared:#06X} but the object starts at {start:#06X}"
591            )));
592        }
593    }
594    let _ = file;
595    Ok(())
596}
597
598/// The objects inside one of the 券面 applications' data files, with any offset table checked.
599///
600/// Those files share a shape — an outer tag then a run of fields — but only some carry a table of
601/// `u16` offsets from the start of the file, so which tag is the table (if any) has to be stated
602/// rather than guessed: 券面事項確認AP `0001` and `0005` open with `DF11` and `DF41`, which are
603/// ordinary fields despite the matching low nibble.
604pub(crate) struct TlvFields<'a> {
605    /// Tag, value, and the object's own bytes including its header.
606    items: Vec<(u32, &'a [u8], &'a [u8])>,
607}
608
609impl<'a> TlvFields<'a> {
610    pub(crate) fn parse(
611        raw: &'a [u8],
612        expected_tag: u32,
613        offset_table: Option<u32>,
614    ) -> Result<Self> {
615        let outer = ber::parse(raw)?;
616        if outer.tag != expected_tag {
617            return Err(malformed(&format!(
618                "expected tag {expected_tag:04X}, got {:04X}",
619                outer.tag
620            )));
621        }
622        // The header's own length, not `raw.len() - value.len()`: a file read straight off the
623        // card carries filler past the end of the object, and taking the difference would push
624        // every offset out by however much filler there is.
625        let mut pos = ber::parse_header(raw)?.header_len;
626        let mut rest = outer.value;
627        let mut offsets = None;
628        let mut items = Vec::new();
629        let mut starts = Vec::new();
630        while let Some(&first) = rest.first() {
631            if first == 0x00 || first == 0xFF {
632                break;
633            }
634            let header = ber::parse_header(rest)?;
635            let end = header.total_len();
636            let value = rest
637                .get(header.header_len..end)
638                .ok_or_else(|| malformed("a field runs past the end of the file"))?;
639            if Some(header.tag) == offset_table {
640                offsets = Some(value);
641            } else {
642                items.push((header.tag, value, &rest[..end]));
643                starts.push(pos);
644            }
645            pos += end;
646            rest = &rest[end..];
647        }
648        if let Some(table) = offsets {
649            check_offsets(raw, table, &starts)?;
650        }
651        Ok(TlvFields { items })
652    }
653
654    pub(crate) fn get(&self, tag: u32) -> Result<&'a [u8]> {
655        self.items
656            .iter()
657            .find(|(t, _, _)| *t == tag)
658            .map(|(_, v, _)| *v)
659            .ok_or_else(|| malformed(&format!("no field with tag {tag:04X}")))
660    }
661
662    /// Every object before `tag`, as written — what these files' signatures cover.
663    pub(crate) fn bytes_before(&self, tag: u32) -> Result<Vec<u8>> {
664        let end = self
665            .items
666            .iter()
667            .position(|(t, _, _)| *t == tag)
668            .ok_or_else(|| malformed(&format!("no field with tag {tag:04X}")))?;
669        Ok(self.items[..end]
670            .iter()
671            .flat_map(|(_, _, raw)| *raw)
672            .copied()
673            .collect())
674    }
675
676    /// The named objects concatenated, as written.
677    pub(crate) fn bytes_of(&self, tags: &[u32]) -> Result<Vec<u8>> {
678        let mut out = Vec::new();
679        for tag in tags {
680            let raw = self
681                .items
682                .iter()
683                .find(|(t, _, _)| t == tag)
684                .map(|(_, _, raw)| *raw)
685                .ok_or_else(|| malformed(&format!("no field with tag {tag:04X}")))?;
686            out.extend_from_slice(raw);
687        }
688        Ok(out)
689    }
690}
691
692pub(crate) fn malformed(what: &str) -> Error {
693    Error::Malformed(what.to_owned())
694}
695
696fn hex(bytes: &[u8]) -> String {
697    bytes
698        .iter()
699        .map(|b| format!("{b:02X}"))
700        .collect::<Vec<_>>()
701        .join(" ")
702}
703
704/// Build the PKCS #1 v1.5 `DigestInfo` for a SHA-256 digest.
705///
706/// ```text
707/// 30 <len> 30 0D 06 09 60 86 48 01 65 03 04 02 01 05 00 04 <n> <digest>
708/// ```
709///
710/// `digest` is normally 32 bytes, but the card face record of 券面事項確認AP `0002` puts three
711/// concatenated SHA-256 digests in one `DigestInfo` and declares the length accordingly — so the
712/// length is taken from what is passed rather than fixed.
713pub fn sha256_digest_info(digest: &[u8]) -> Vec<u8> {
714    const ALGORITHM: [u8; 15] = [
715        0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
716    ];
717    let inner = ALGORITHM.len() + 2 + digest.len();
718    let mut out = vec![0x30];
719    if inner < 0x80 {
720        out.push(inner as u8);
721    } else {
722        out.push(0x81);
723        out.push(inner as u8);
724    }
725    out.extend_from_slice(&ALGORITHM);
726    out.push(0x04);
727    out.push(digest.len() as u8);
728    out.extend_from_slice(digest);
729    out
730}
731
732#[cfg(feature = "verify")]
733impl RsaPublicKey {
734    fn to_rsa(&self) -> Result<rsa::RsaPublicKey> {
735        rsa::RsaPublicKey::new(
736            rsa::BigUint::from_bytes_be(&self.modulus),
737            rsa::BigUint::from_bytes_be(&self.exponent),
738        )
739        .map_err(|_| Error::SignatureInvalid("the public key is not usable"))
740    }
741
742    /// Verify a PKCS #1 v1.5 signature whose payload is `digest_info`, byte for byte.
743    ///
744    /// The padding is checked in full — this is not a search for the payload inside the block —
745    /// so a signature with anything appended is rejected.
746    pub fn verify_pkcs1(&self, digest_info: &[u8], signature: &[u8]) -> Result<()> {
747        self.to_rsa()?
748            .verify(rsa::Pkcs1v15Sign::new_unprefixed(), digest_info, signature)
749            .map_err(|_| Error::SignatureInvalid("PKCS #1 v1.5 signature does not verify"))
750    }
751
752    /// Verify a PKCS #1 v1.5 signature over the SHA-256 of `message`.
753    pub fn verify_pkcs1_sha256(&self, message: &[u8], signature: &[u8]) -> Result<()> {
754        use rsa::sha2::Digest as _;
755        let digest = rsa::sha2::Sha256::digest(message);
756        self.verify_pkcs1(&sha256_digest_info(&digest), signature)
757    }
758
759    /// Verify an RSASSA-PSS signature over the SHA-256 of `message`.
760    pub fn verify_pss_sha256(&self, message: &[u8], signature: &[u8]) -> Result<()> {
761        use rsa::sha2::Digest as _;
762        self.verify_pss_prehashed(&rsa::sha2::Sha256::digest(message), signature)
763    }
764
765    /// Encrypt `message` with RSAES-OAEP and SHA-256, both as the digest and in MGF1.
766    ///
767    /// Used to hand a session key to the 券面入力補助AP. The card's own answer distinguishes a
768    /// ciphertext at or above the modulus (`6F00`) from one below it (`6A80` when the plaintext is
769    /// not what it wanted), which is a property of its input range check rather than a leak: the
770    /// modulus is in EF `0006` for anyone to read.
771    #[cfg(feature = "sm")]
772    pub fn encrypt_oaep_sha256(&self, message: &[u8]) -> Result<Vec<u8>> {
773        use rsa::rand_core::OsRng;
774        self.to_rsa()?
775            .encrypt(&mut OsRng, rsa::Oaep::new::<rsa::sha2::Sha256>(), message)
776            .map_err(|_| Error::SignatureInvalid("OAEP encryption failed"))
777    }
778
779    /// Verify an RSASSA-PSS signature over a SHA-256 digest you already have.
780    pub fn verify_pss_prehashed(&self, digest: &[u8], signature: &[u8]) -> Result<()> {
781        self.to_rsa()?
782            .verify(rsa::Pss::new::<rsa::sha2::Sha256>(), digest, signature)
783            .map_err(|_| Error::SignatureInvalid("PSS signature does not verify"))
784    }
785}
786
787/// SHA-256 of `data`.
788#[cfg(feature = "verify")]
789pub fn sha256(data: &[u8]) -> [u8; 32] {
790    use rsa::sha2::Digest as _;
791    rsa::sha2::Sha256::digest(data).into()
792}
793
794#[cfg(all(test, feature = "verify"))]
795mod verify_tests {
796    use super::*;
797
798    #[test]
799    fn builds_digest_infos_of_both_lengths() {
800        // The ordinary one: 32 byte digest, 49 byte structure.
801        let one = sha256_digest_info(&[0xAA; 32]);
802        assert_eq!(&one[..2], &[0x30, 0x31]);
803        assert_eq!(&one[17..19], &[0x04, 0x20]);
804        assert_eq!(one.len(), 51);
805
806        // The card face record declares three concatenated digests in one DigestInfo.
807        let three = sha256_digest_info(&[0xAA; 96]);
808        assert_eq!(&three[..2], &[0x30, 0x71]);
809        assert_eq!(&three[17..19], &[0x04, 0x60]);
810        assert_eq!(three.len(), 115);
811    }
812}
813
814#[cfg(feature = "verify")]
815impl CardVerifiableCertificate {
816    /// Check the certificate against the CA key its [`issuer_key_id`](Self::issuer_key_id) names.
817    ///
818    /// The key is looked up in [`crate::ca`], which carries the two production keys. To supply one
819    /// yourself instead, use [`verify_with`](Self::verify_with).
820    ///
821    /// # Errors
822    ///
823    /// [`Error::UnknownCertificateAuthority`] if no key is known for that identifier — which is
824    /// what a test card gets, since its certificates are issued under `"6000023"`/`"6000033"`.
825    /// Nothing is checked in that case; it is not a signature failure.
826    pub fn verify(&self) -> Result<()> {
827        let ca = crate::ca::find(&self.issuer_key_id)
828            .ok_or(Error::UnknownCertificateAuthority(self.issuer_key_id))?;
829        self.verify_with(&ca.to_public_key())
830    }
831
832    /// Check a chain: the first certificate against [`crate::ca`], each later one against the key
833    /// the certificate before it certifies.
834    ///
835    /// This is what makes the master file chain self-contained — only its root needs a key that
836    /// did not come off the card. The links are checked in order and the first failure is
837    /// returned, so a chain that verifies here verifies as a whole.
838    ///
839    /// # Errors
840    ///
841    /// [`Error::Malformed`] if the chain is empty or two consecutive certificates do not link,
842    /// and whatever [`verify`](Self::verify) or [`verify_with`](Self::verify_with) reports
843    /// otherwise.
844    pub fn verify_chain(chain: &[Self]) -> Result<()> {
845        let (first, rest) = chain
846            .split_first()
847            .ok_or_else(|| malformed("an empty chain verifies nothing"))?;
848        first.verify()?;
849        let mut issuer = first;
850        for cert in rest {
851            if cert.issuer_key_id != issuer.subject_key_id {
852                return Err(malformed(
853                    "chain is broken: a certificate names an issuer the one above does not certify",
854                ));
855            }
856            cert.verify_with(&issuer.public_key)?;
857            issuer = cert;
858        }
859        Ok(())
860    }
861
862    /// Check the certificate against a CA key you supply.
863    ///
864    /// The signature is PKCS #1 v1.5 with SHA-256 over the body — the two key identifiers followed
865    /// by the certified public key, exactly the 297 bytes of [`signed_data`](Self::signed_data).
866    ///
867    /// The CA key does not come from the card, and the whole security of the 券面 protocol rests
868    /// on where it does come from: a certificate checked against a key taken off the same card
869    /// proves nothing at all.
870    pub fn verify_with(&self, ca_key: &RsaPublicKey) -> Result<()> {
871        ca_key.verify_pkcs1_sha256(&self.signed_data, &self.signature)
872    }
873}
874
875#[cfg(test)]
876mod tests {
877    use super::*;
878
879    #[test]
880    fn parses_an_ap_identification_field() {
881        let identification = ApIdentification::parse(&[0x06, 0x03, 0x0E, 0x01]).unwrap();
882        assert_eq!(identification.specification_version, 0x06);
883        assert_eq!(identification.extended_lc_le_support, 0x03);
884        assert_eq!(identification.vendor_id, 0x0E);
885        assert_eq!(identification.vendor_specific, 0x01);
886        assert_eq!(identification.to_bytes(), [0x06, 0x03, 0x0E, 0x01]);
887        assert!(ApIdentification::parse(&[0x06, 0x03, 0x0E]).is_err());
888        assert!(ApIdentification::parse(&[0x06, 0x03, 0x0E, 0x01, 0x00]).is_err());
889    }
890
891    #[test]
892    fn parses_a_date() {
893        assert_eq!(
894            Date::parse(b"19800217").unwrap(),
895            Date {
896                year: 1980,
897                month: 2,
898                day: 17
899            }
900        );
901        assert_eq!(Date::parse(b"19800217").unwrap().to_string(), "1980-02-17");
902        assert!(Date::parse(b"1980021").is_err());
903        assert!(Date::parse(b"19801317").is_err());
904        assert!(Date::parse(b"1980-2-17").is_err());
905    }
906
907    #[test]
908    fn converts_to_japanese_eras() {
909        // The test card: 1980-02-17 is 昭和55, which is what 照合番号B encodes.
910        assert_eq!(
911            Date::parse(b"19800217").unwrap().to_era(),
912            Some((Era::Showa, 55))
913        );
914        // Era boundaries are mid-year, so the day matters.
915        assert_eq!(
916            Date::parse(b"19890107").unwrap().to_era(),
917            Some((Era::Showa, 64))
918        );
919        assert_eq!(
920            Date::parse(b"19890108").unwrap().to_era(),
921            Some((Era::Heisei, 1))
922        );
923        assert_eq!(
924            Date::parse(b"20190430").unwrap().to_era(),
925            Some((Era::Heisei, 31))
926        );
927        assert_eq!(
928            Date::parse(b"20190501").unwrap().to_era(),
929            Some((Era::Reiwa, 1))
930        );
931        assert_eq!(Date::parse(b"18670101").unwrap().to_era(), None);
932        assert_eq!(Era::Showa.name(), "昭和");
933    }
934
935    #[test]
936    fn builds_verification_code_b() {
937        // The exact value that unlocks 券面入力補助AP 0002 on the test card.
938        let dob = Date::parse(b"19800217").unwrap();
939        let code = verification_code_b(dob, 2035, b"2285").unwrap();
940        assert_eq!(code.as_bytes(), b"55021720352285");
941        assert_eq!(code.len(), 14);
942    }
943
944    #[test]
945    fn rejects_a_code_b_it_cannot_build() {
946        let dob = Date::parse(b"19800217").unwrap();
947        assert!(verification_code_b(dob, 2035, b"228").is_err());
948        assert!(verification_code_b(dob, 2035, b"22X5").is_err());
949        assert!(verification_code_b(Date::parse(b"18000101").unwrap(), 2035, b"2285").is_err());
950    }
951
952    #[test]
953    fn my_number_is_also_verification_code_a() {
954        let n = MyNumber::parse(b"537686677188").unwrap();
955        assert_eq!(n.as_str(), "537686677188");
956        assert_eq!(
957            n.as_verification_code_a().unwrap().as_bytes(),
958            b"537686677188"
959        );
960        assert!(!format!("{n:?}").contains("5376"));
961        assert!(MyNumber::parse(b"53768667718").is_err());
962        assert!(MyNumber::parse(b"53768667718X").is_err());
963    }
964
965    #[test]
966    fn parses_a_public_key() {
967        let mut data = vec![0x90, 0x03, 0x01, 0x00, 0x01, 0x91, 0x82, 0x01, 0x00];
968        data.push(0xC9);
969        data.extend(std::iter::repeat_n(0xAA, 255));
970        let key = RsaPublicKey::parse(&data).unwrap();
971        assert_eq!(key.exponent, [0x01, 0x00, 0x01]);
972        assert_eq!(key.modulus.len(), 256);
973        assert_eq!(key.bits(), 2048);
974    }
975
976    #[test]
977    fn detects_image_formats() {
978        assert_eq!(
979            ImageFormat::detect(b"\x89PNG\r\n\x1a\n\x00"),
980            ImageFormat::Png
981        );
982        assert_eq!(
983            ImageFormat::detect(b"\x00\x00\x00\x0CjP  \r\n"),
984            ImageFormat::Jpeg2000
985        );
986        assert_eq!(ImageFormat::detect(b"nope"), ImageFormat::Unknown);
987        assert_eq!(ImageFormat::Png.extension(), "png");
988    }
989
990    /// A certificate shaped exactly like the card's: 16 + 16 + a 265 byte RSA-2048 key.
991    fn cv_certificate() -> Vec<u8> {
992        let mut body = b"9200073\x08\x050010000".to_vec();
993        body.extend_from_slice(b"9299774\x08\x050010000");
994        body.extend_from_slice(&[0x90, 0x03, 0x01, 0x00, 0x01, 0x91, 0x82, 0x01, 0x00]);
995        body.push(0xC9);
996        body.extend(std::iter::repeat_n(0xAA, 255));
997        assert_eq!(body.len(), CardVerifiableCertificate::BODY_LEN);
998
999        let mut inner = vec![0x5F, 0x4E, 0x82];
1000        inner.extend_from_slice(&(body.len() as u16).to_be_bytes());
1001        inner.extend_from_slice(&body);
1002        inner.extend_from_slice(&[0x5F, 0x37, 0x82, 0x01, 0x00]);
1003        inner.extend(std::iter::repeat_n(0xBC, 256));
1004
1005        let mut cert = vec![0x7F, 0x21, 0x82];
1006        cert.extend_from_slice(&(inner.len() as u16).to_be_bytes());
1007        cert.extend_from_slice(&inner);
1008        cert
1009    }
1010
1011    #[test]
1012    fn parses_a_card_verifiable_certificate() {
1013        let parsed = CardVerifiableCertificate::parse(&cv_certificate()).unwrap();
1014        assert_eq!(parsed.issuer_key_id.to_string(), "9200073/001");
1015        assert_eq!(parsed.subject_key_id.to_string(), "9299774/001");
1016        assert_eq!(parsed.public_key.bits(), 2048);
1017        assert_eq!(parsed.signature.len(), 256);
1018        // The signature covers the body, and only the body.
1019        assert_eq!(
1020            parsed.signed_data.len(),
1021            CardVerifiableCertificate::BODY_LEN
1022        );
1023        assert!(parsed.signed_data.starts_with(b"9200073"));
1024    }
1025
1026    #[test]
1027    fn rejects_a_body_of_the_wrong_size() {
1028        let mut cert = cv_certificate();
1029        // Shrink the body by one byte, keeping every length field consistent.
1030        let body_len = CardVerifiableCertificate::BODY_LEN - 1;
1031        cert[8] = (body_len >> 8) as u8;
1032        cert[9] = body_len as u8;
1033        cert.remove(10 + body_len);
1034        cert[3] = ((cert.len() - 5) >> 8) as u8;
1035        cert[4] = (cert.len() - 5) as u8;
1036        let err = CardVerifiableCertificate::parse(&cert).unwrap_err();
1037        assert!(format!("{err}").contains("297"), "{err}");
1038    }
1039
1040    #[test]
1041    fn offset_table_mismatch_is_an_error() {
1042        assert!(check_offsets(&[], &[0x00, 0x0E, 0x00, 0x20], &[14, 32]).is_ok());
1043        assert!(check_offsets(&[], &[0x00, 0x0E, 0x00, 0x20], &[14, 33]).is_err());
1044        assert!(check_offsets(&[], &[0x00, 0x0E], &[14, 32]).is_err());
1045    }
1046}