1#![feature(vec_into_raw_parts)]
2#![allow(clippy::missing_safety_doc)]
3
4use jpki::ap::crypto::CertType;
5use jpki::ap::CryptoAp;
6use jpki::nfc::{HandleError, HandlerInCtx, Result as NfcResult};
7use jpki::Card;
8use std::ffi::{c_char, CStr, CString};
9use std::ptr::null_mut;
10use std::rc::Rc;
11
12static mut LAST_ERROR: Option<String> = None;
13
14fn unwrap_or<T, E>(result: Result<T, E>, default: T) -> T
15where
16 E: ToString,
17{
18 unsafe {
19 LAST_ERROR = result.as_ref().err().map(|e| e.to_string());
22 }
23
24 match result {
25 Ok(value) => value,
26 Err(_) => default,
27 }
28}
29
30fn unwrap<T, E>(result: Result<T, E>) -> T
31where
32 T: Default,
33 E: ToString,
34{
35 unwrap_or(result, T::default())
36}
37
38#[repr(C)]
42#[derive(Copy, Clone)]
43pub struct ByteArray {
44 ptr: *mut u8,
45 len: usize,
46 cap: usize,
47}
48
49impl Default for ByteArray {
50 fn default() -> Self {
51 Self {
52 ptr: null_mut(),
53 len: 0,
54 cap: 0,
55 }
56 }
57}
58
59impl From<Vec<u8>> for ByteArray {
60 fn from(bytes: Vec<u8>) -> Self {
61 let bytes = Box::new(bytes);
62 let (ptr, len, cap) = bytes.into_raw_parts();
63 Self { ptr, len, cap }
64 }
65}
66
67impl From<ByteArray> for Vec<u8> {
68 fn from(ByteArray { ptr, len, cap }: ByteArray) -> Self {
69 unsafe { Self::from_raw_parts(ptr, len, cap) }
70 }
71}
72
73impl ByteArray {
74 fn drain(self) {
75 let Self { ptr, len, cap } = self;
76 let _ = unsafe { Vec::from_raw_parts(ptr, len, cap) };
77 }
78}
79
80pub struct NfcCard {
81 delegate: extern "C" fn(ByteArray) -> ByteArray,
82}
83
84impl HandlerInCtx for NfcCard {
85 fn handle_in_ctx(&self, _: (), command: &[u8], response: &mut [u8]) -> NfcResult {
86 let command = Vec::from(command).into();
87 let buf = Vec::from((self.delegate)(command));
88 let len = buf.len();
89 if response.len() < len {
90 return Err(HandleError::NotEnoughBuffer(len));
91 }
92
93 response[..len].copy_from_slice(&buf);
94 command.drain();
95 Ok(len)
96 }
97}
98
99#[no_mangle]
103pub extern "C" fn jpki_init() {}
104
105#[no_mangle]
108pub extern "C" fn jpki_last_error() -> *mut c_char {
109 match unsafe { LAST_ERROR.clone() }.and_then(|e| CString::new(e).ok()) {
110 Some(str) => str.into_raw(),
111 None => null_mut(),
112 }
113}
114
115#[no_mangle]
118pub extern "C" fn jpki_new_nfc_card(
119 delegate: extern "C" fn(ByteArray) -> ByteArray,
120) -> *mut NfcCard {
121 let card = NfcCard { delegate };
122
123 Box::into_raw(Box::new(card))
124}
125
126#[no_mangle]
128pub unsafe extern "C" fn jpki_nfc_card_close(card: &mut NfcCard) {
129 let _ = Box::from_raw(card);
130}
131
132#[no_mangle]
135pub unsafe extern "C" fn jpki_new_card(nfc_card: *mut NfcCard) -> *mut Card<NfcCard, ()> {
136 let nfc_card = Box::from_raw(nfc_card);
137 let card = Card::new(nfc_card);
138
139 Box::into_raw(Box::new(card))
140}
141
142#[no_mangle]
144pub unsafe extern "C" fn jpki_card_close(card: &mut Card<NfcCard, ()>) {
145 let _ = Rc::from_raw(card);
147}
148
149#[no_mangle]
151pub unsafe extern "C" fn jpki_new_crypto_ap(
152 card: *mut Card<NfcCard, ()>,
153) -> *mut CryptoAp<NfcCard, ()> {
154 let card = Rc::from_raw(card);
155
156 unwrap_or(
157 CryptoAp::open((), card).map(|ap| Box::into_raw(Box::new(ap))),
158 null_mut(),
159 )
160}
161
162#[no_mangle]
164pub unsafe extern "C" fn jpki_crypto_ap_close(crypto_ap: *mut CryptoAp<NfcCard, ()>) {
165 let _ = Box::from_raw(crypto_ap);
166}
167
168#[no_mangle]
172pub unsafe extern "C" fn jpki_crypto_ap_read_certificate_sign(
173 crypto_ap: *mut CryptoAp<NfcCard, ()>,
174 pin: *const c_char,
175 ca: bool,
176) -> ByteArray {
177 let pin = CStr::from_ptr(pin).to_bytes().to_vec();
178 let ty = match ca {
179 true => CertType::SignCA,
180 _ => CertType::Sign,
181 };
182
183 unwrap(
184 crypto_ap
185 .as_ref()
186 .unwrap()
187 .read_certificate((), ty, pin)
188 .map(|v| v.into()),
189 )
190}
191
192#[no_mangle]
195pub unsafe extern "C" fn jpki_crypto_ap_read_certificate_auth(
196 crypto_ap: *mut CryptoAp<NfcCard, ()>,
197 ca: bool,
198) -> ByteArray {
199 let ty = match ca {
200 true => CertType::AuthCA,
201 _ => CertType::Auth,
202 };
203
204 unwrap(
205 crypto_ap
206 .as_ref()
207 .unwrap()
208 .read_certificate((), ty, vec![])
209 .map(|v| v.into()),
210 )
211}
212
213#[no_mangle]
215pub unsafe extern "C" fn jpki_crypto_ap_auth(
216 crypto_ap: *mut CryptoAp<NfcCard, ()>,
217 pin: *const c_char,
218 digest: ByteArray,
219) -> ByteArray {
220 let pin = CStr::from_ptr(pin).to_bytes().to_vec();
221
222 unwrap(
223 crypto_ap
224 .as_ref()
225 .unwrap()
226 .auth((), pin, digest.into())
227 .map(|v| v.into()),
228 )
229}
230
231#[no_mangle]
233pub unsafe extern "C" fn jpki_crypto_ap_sign(
234 crypto_ap: *mut CryptoAp<NfcCard, ()>,
235 pin: *const c_char,
236 digest: ByteArray,
237) -> ByteArray {
238 let pin = CStr::from_ptr(pin).to_bytes().to_vec();
239
240 unwrap(
241 crypto_ap
242 .as_ref()
243 .unwrap()
244 .sign((), pin, digest.into())
245 .map(|v| v.into()),
246 )
247}