#![feature(vec_into_raw_parts)]
#![allow(clippy::missing_safety_doc)]
use jpki::ap::crypto::CertType;
use jpki::ap::CryptoAp;
use jpki::nfc::{Command, HandlerInCtx, Response};
use jpki::Card;
use std::ffi::{c_char, CStr, CString};
use std::ptr::null_mut;
use std::rc::Rc;
static mut LAST_ERROR: Option<String> = None;
fn unwrap_or<T, E>(result: Result<T, E>, default: T) -> T
where
E: ToString,
{
unsafe {
LAST_ERROR = result.as_ref().err().map(|e| e.to_string());
}
match result {
Ok(value) => value,
Err(_) => default,
}
}
fn unwrap<T, E>(result: Result<T, E>) -> T
where
T: Default,
E: ToString,
{
unwrap_or(result, T::default())
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct ByteArray {
ptr: *mut u8,
len: usize,
cap: usize,
}
impl Default for ByteArray {
fn default() -> Self {
Self {
ptr: null_mut(),
len: 0,
cap: 0,
}
}
}
impl From<Vec<u8>> for ByteArray {
fn from(bytes: Vec<u8>) -> Self {
let bytes = Box::new(bytes);
let (ptr, len, cap) = bytes.into_raw_parts();
Self { ptr, len, cap }
}
}
impl From<ByteArray> for Vec<u8> {
fn from(ByteArray { ptr, len, cap }: ByteArray) -> Self {
unsafe { Self::from_raw_parts(ptr, len, cap) }
}
}
impl ByteArray {
fn drain(self) {
let Self { ptr, len, cap } = self;
let _ = unsafe { Vec::from_raw_parts(ptr, len, cap) };
}
}
pub struct NfcCard {
delegate: extern "C" fn(ByteArray) -> ByteArray,
}
impl HandlerInCtx for NfcCard {
fn handle_in_ctx(&self, _: (), command: Command) -> Response {
let command = Vec::from(command).into();
let response = Response::from(Vec::from((self.delegate)(command)));
command.drain();
response
}
}
#[no_mangle]
pub extern "C" fn jpki_init() {}
#[no_mangle]
pub extern "C" fn jpki_last_error() -> *mut c_char {
match unsafe { LAST_ERROR.clone() }.and_then(|e| CString::new(e).ok()) {
Some(str) => str.into_raw(),
None => null_mut(),
}
}
#[no_mangle]
pub extern "C" fn jpki_new_nfc_card(
delegate: extern "C" fn(ByteArray) -> ByteArray,
) -> *mut NfcCard {
let card = NfcCard { delegate };
Box::into_raw(Box::new(card))
}
#[no_mangle]
pub unsafe extern "C" fn jpki_nfc_card_close(card: &mut NfcCard) {
let _ = Box::from_raw(card);
}
#[no_mangle]
pub unsafe extern "C" fn jpki_new_card(nfc_card: *mut NfcCard) -> *mut Card<NfcCard, ()> {
let nfc_card = Box::from_raw(nfc_card);
let card = Card::new(nfc_card);
Box::into_raw(Box::new(card))
}
#[no_mangle]
pub unsafe extern "C" fn jpki_card_close(card: &mut Card<NfcCard, ()>) {
let _ = Rc::from_raw(card);
}
#[no_mangle]
pub unsafe extern "C" fn jpki_new_crypto_ap(
card: *mut Card<NfcCard, ()>,
) -> *mut CryptoAp<NfcCard, ()> {
let card = Rc::from_raw(card);
unwrap_or(
CryptoAp::open((), card).map(|ap| Box::into_raw(Box::new(ap))),
null_mut(),
)
}
#[no_mangle]
pub unsafe extern "C" fn jpki_crypto_ap_close(crypto_ap: *mut CryptoAp<NfcCard, ()>) {
let _ = Box::from_raw(crypto_ap);
}
#[no_mangle]
pub unsafe extern "C" fn jpki_crypto_ap_read_certificate_sign(
crypto_ap: *mut CryptoAp<NfcCard, ()>,
pin: *const c_char,
ca: bool,
) -> ByteArray {
let pin = CStr::from_ptr(pin).to_bytes().to_vec();
let ty = match ca {
true => CertType::SignCA,
_ => CertType::Sign,
};
unwrap(
crypto_ap
.as_ref()
.unwrap()
.read_certificate((), ty, pin)
.map(|v| v.into()),
)
}
#[no_mangle]
pub unsafe extern "C" fn jpki_crypto_ap_read_certificate_auth(
crypto_ap: *mut CryptoAp<NfcCard, ()>,
ca: bool,
) -> ByteArray {
let ty = match ca {
true => CertType::AuthCA,
_ => CertType::Auth,
};
unwrap(
crypto_ap
.as_ref()
.unwrap()
.read_certificate((), ty, vec![])
.map(|v| v.into()),
)
}
#[no_mangle]
pub unsafe extern "C" fn jpki_crypto_ap_auth(
crypto_ap: *mut CryptoAp<NfcCard, ()>,
pin: *const c_char,
digest: ByteArray,
) -> ByteArray {
let pin = CStr::from_ptr(pin).to_bytes().to_vec();
unwrap(
crypto_ap
.as_ref()
.unwrap()
.auth((), pin, digest.into())
.map(|v| v.into()),
)
}
#[no_mangle]
pub unsafe extern "C" fn jpki_crypto_ap_sign(
crypto_ap: *mut CryptoAp<NfcCard, ()>,
pin: *const c_char,
digest: ByteArray,
) -> ByteArray {
let pin = CStr::from_ptr(pin).to_bytes().to_vec();
unwrap(
crypto_ap
.as_ref()
.unwrap()
.sign((), pin, digest.into())
.map(|v| v.into()),
)
}