jpki/ap/
crypto.rs

1//! Crypto AP (formerly JPKI AP)
2
3use std::rc::Rc;
4
5use crate::ap::open;
6use crate::{card, nfc, Card};
7
8const DF_NAME: [u8; 10] = [0xD3, 0x92, 0xF0, 0x00, 0x26, 0x01, 0x00, 0x00, 0x00, 0x01];
9const EF_AUTH: [u8; 2] = [0x00, 0x17];
10const EF_AUTH_PIN: [u8; 2] = [0x00, 0x18];
11const EF_SIGN: [u8; 2] = [0x00, 0x1A];
12const EF_SIGN_PIN: [u8; 2] = [0x00, 0x1B];
13
14/// Type of the certificate to fetch
15#[derive(Copy, Clone)]
16pub enum CertType {
17    /// Certificate for authentication
18    Auth,
19
20    /// Certificate of CA (Certificate Authority) that issued the authentication certificate
21    AuthCA,
22
23    /// Certificate for signing documents
24    Sign,
25
26    /// Certificate of CA (Certificate Authority) that issued the signing certificate
27    SignCA,
28}
29
30impl CertType {
31    /// Converts the variant into the identifier to select a EF
32    /// that corresponds with the selected certificate.
33    pub fn into_efid(self) -> [u8; 2] {
34        match self {
35            Self::Auth => [0x00, 0x0A],
36            Self::AuthCA => [0x00, 0x0B],
37            Self::Sign => [0x00, 0x01],
38            Self::SignCA => [0x00, 0x02],
39        }
40    }
41
42    /// Determines whether it is needed for fetching the certificate to unlock it with a PIN.
43    pub fn is_pin_required(&self) -> bool {
44        matches!(self, Self::Sign)
45    }
46}
47
48/// An AP to sign or verify messages using a key-pair issued by JPKI
49pub struct CryptoAp<T, Ctx>
50where
51    T: nfc::HandlerInCtx<Ctx>,
52    Ctx: Copy,
53{
54    card: Rc<Card<T, Ctx>>,
55}
56
57impl<T, Ctx> CryptoAp<T, Ctx>
58where
59    T: nfc::HandlerInCtx<Ctx>,
60    Ctx: Copy,
61{
62    open!(T, Ctx, DF_NAME);
63
64    /// Reads a certificate of the type, unlocking with the PIN if required.
65    pub fn read_certificate(
66        &self,
67        ctx: Ctx,
68        ty: CertType,
69        pin: Vec<u8>,
70    ) -> Result<Vec<u8>, card::Error> {
71        if ty.is_pin_required() {
72            self.verify_sign_pin(ctx, pin)?;
73        }
74
75        self.card
76            .select_ef(ctx, ty.into_efid().into())
77            .and_then(|_| self.card.read_der_size(ctx))
78            .and_then(|size| self.card.read(ctx, Some(size)))
79    }
80
81    /// Computes a signature using the key-pair for authentication.
82    pub fn auth(&self, ctx: Ctx, pin: Vec<u8>, digest: Vec<u8>) -> Result<Vec<u8>, card::Error> {
83        self.verify_auth_pin(ctx, pin)
84            .and_then(|_| self.card.select_ef(ctx, EF_AUTH.into()))
85            .and_then(|_| self.card.sign(ctx, digest))
86    }
87
88    /// Computes a signature using the key-pair for signing.
89    pub fn sign(&self, ctx: Ctx, pin: Vec<u8>, digest: Vec<u8>) -> Result<Vec<u8>, card::Error> {
90        self.verify_sign_pin(ctx, pin)
91            .and_then(|_| self.card.select_ef(ctx, EF_SIGN.into()))
92            .and_then(|_| self.card.sign(ctx, digest))
93    }
94
95    /// Gets the status of PIN for user authentication.
96    pub fn auth_pin_status(&self, ctx: Ctx) -> Result<u8, card::Error> {
97        self.card.pin_status(ctx, EF_AUTH_PIN)
98    }
99
100    /// Gets the status of PIN for signing.
101    pub fn sign_pin_status(&self, ctx: Ctx) -> Result<u8, card::Error> {
102        self.card.pin_status(ctx, EF_SIGN_PIN)
103    }
104
105    fn verify_auth_pin(&self, ctx: Ctx, pin: Vec<u8>) -> Result<(), card::Error> {
106        self.card.verify_pin(ctx, EF_AUTH_PIN, pin)
107    }
108
109    fn verify_sign_pin(&self, ctx: Ctx, pin: Vec<u8>) -> Result<(), card::Error> {
110        self.card.verify_pin(ctx, EF_SIGN_PIN, pin)
111    }
112}