feat: implement high level get_vitale_card_rights over SSV_LireDroitsVitale - without output data parsing

This commit is contained in:
Florian Briand 2024-10-10 15:39:43 +02:00
parent b617c7dd62
commit 21aa637af3
Signed by: florian_briand
GPG Key ID: CC981B9E6B98E70B
3 changed files with 79 additions and 9 deletions

View File

@ -2017,6 +2017,7 @@ name = "fsv"
version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
"deku",
"env_logger",
"fsv-sys",

View File

@ -18,6 +18,7 @@ utils = { path = "../utils" }
#[dev-dependencies]
log = "0.4.22"
env_logger = "0.11.5"
chrono = "0.4.38"
[dev-dependencies]
insta = "1.40.0"

View File

@ -37,6 +37,9 @@ pub struct SSV {
}
impl SSV {
const CPS_READER_NAME: &'static str = "Gemalto PC Twin Reader (645D94C3) 00 00";
const VITALE_READER_NAME: &'static str = "Gemalto PC Twin Reader (645D94C3) 00 00"; // TODO: Change this to the correct reader name
pub fn new(version: SupportedFsvVersion) -> Result<Self, Error> {
let library = match version {
SupportedFsvVersion::V1_40_13 => {
@ -77,18 +80,18 @@ impl SSV {
/// # Read the CPS card
/// Implement: SSV_LireCartePS
pub fn read_professional_card(&self, pin_code: &str) -> Result<Data, Error> {
let pcsc_reader_name = "Gemalto PC Twin Reader (645D94C3) 00 00";
let pin_code = CString::new(pin_code).expect("CString::new failed");
let pcsc_reader_name = CString::new(pcsc_reader_name).expect("CString::new failed");
let cps_pcsc_reader_name = CString::new(SSV::CPS_READER_NAME).expect("CString::new failed");
let vitale_pcsc_reader_name = CString::new(SSV::VITALE_READER_NAME).expect("CString::new failed");
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut out_buffer_size: libc::size_t = 0;
let result = match &self.library {
SsvLibraryVersion::V1_40_13(library) => {
unsafe { library.ssv_lire_carte_ps(
pcsc_reader_name.as_ptr(),
pcsc_reader_name.as_ptr(),
cps_pcsc_reader_name.as_ptr(),
vitale_pcsc_reader_name.as_ptr(),
pin_code.as_ptr(),
&mut out_buffer_ptr,
&mut out_buffer_size)
@ -96,8 +99,8 @@ impl SSV {
},
SsvLibraryVersion::V1_40_14(library) => {
unsafe { library.ssv_lire_carte_ps(
pcsc_reader_name.as_ptr(),
pcsc_reader_name.as_ptr(),
cps_pcsc_reader_name.as_ptr(),
vitale_pcsc_reader_name.as_ptr(),
pin_code.as_ptr(),
&mut out_buffer_ptr,
&mut out_buffer_size)
@ -149,6 +152,58 @@ impl SSV {
unsafe { libc::free(out_buffer_ptr) };
Ok(config_blocks)
}
pub fn get_vitale_card_rights(&self, pin_code: &str) -> Result<Data, Error> {
let pin_code = CString::new(pin_code).expect("CString::new failed");
let cps_pcsc_reader_name = CString::new(SSV::CPS_READER_NAME).expect("CString::new failed");
let vitale_pcsc_reader_name = CString::new(SSV::VITALE_READER_NAME).expect("CString::new failed");
// Today's date, in the format YYYYMMDD
let today = chrono::Local::now().format("%Y%m%d").to_string();
let date_consultation = CString::new(today).expect("CString::new failed");
let mut out_buffer_ptr: *mut libc::c_void = ptr::null_mut();
let mut out_buffer_size: libc::size_t = 0;
let result = match &self.library {
SsvLibraryVersion::V1_40_13(library) => {
unsafe { library.ssv_lire_droits_vitale(
cps_pcsc_reader_name.as_ptr(),
vitale_pcsc_reader_name.as_ptr(),
pin_code.as_ptr(),
date_consultation.as_ptr(),
&mut out_buffer_ptr,
&mut out_buffer_size)
}?
},
SsvLibraryVersion::V1_40_14(library) => {
unsafe { library.ssv_lire_droits_vitale(
cps_pcsc_reader_name.as_ptr(),
vitale_pcsc_reader_name.as_ptr(),
pin_code.as_ptr(),
date_consultation.as_ptr(),
&mut out_buffer_ptr,
&mut out_buffer_size)
}?
},
};
if result != 0 {
// Free memory
unsafe { libc::free(out_buffer_ptr) };
let error = SSVErrorCodes::from(result);
return Err(Error::SSVError(error));
}
// Parse the buffer into a Data struct
let buffer = unsafe { std::slice::from_raw_parts(out_buffer_ptr as *const u8, out_buffer_size) };
////////////////////////////
println!("{:?}", buffer);
////////////////////////////
let (_rest, vitale_blocks) = Data::from_bytes((buffer, 0)).unwrap();
// Free memory
unsafe { libc::free(out_buffer_ptr) };
Ok(vitale_blocks)
}
}
#[cfg(test)]
@ -185,7 +240,7 @@ mod tests {
#[test]
#[ignore="
WARNING: Read the card with PIN 1234 - Risk of blocking the card
WARNING: Read the card with PIN 1234 - Risk of blocking the card if it's not the right card
WARNING: This test will only work with GILBERT's PHARMOFFICE card (titulaire kit pharmacie)
"]
fn test_read_professional_card_good_pin() -> Result<()> {
@ -214,7 +269,7 @@ mod tests {
}
#[test]
#[ignore="WARNING: Read the card with PIN 0000 - Risk of blocking the card"]
#[ignore="WARNING: Read the card with PIN 0000 - Risk of blocking the card if it's not the right card"]
fn test_read_professional_card_bad_pin() -> Result<()> {
let lib = setup::init()?;
let pin_code = "0000";
@ -246,4 +301,17 @@ mod tests {
assert_eq!(header_content.ssv_version.0.revision, "20");
Ok(())
}
#[test]
#[ignore="
WARNING: Read the card with PIN 1234 - Risk of blocking the card if it's not the right card
WARNING: This test needs a CPS and a VITALE card available simultaneously
"]
fn test_get_vitale_card_rights() -> Result<()> {
let lib = setup::init()?;
let pin_code = "1234";
let _cps_blocks = lib.read_professional_card(pin_code)?;
let _vitale_blocks = lib.get_vitale_card_rights(pin_code)?;
Ok(())
}
}