1use 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#[derive(Copy, Clone)]
16pub enum CertType {
17 Auth,
19
20 AuthCA,
22
23 Sign,
25
26 SignCA,
28}
29
30impl CertType {
31 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 pub fn is_pin_required(&self) -> bool {
44 matches!(self, Self::Sign)
45 }
46}
47
48pub 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 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 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 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 pub fn auth_pin_status(&self, ctx: Ctx) -> Result<u8, card::Error> {
97 self.card.pin_status(ctx, EF_AUTH_PIN)
98 }
99
100 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}