use super::get_session; use crate::tests::AUTHENTICATOR; use ctap2_proto::{ prelude::{ client_pin::{ auth_protocol::{self, platform::Session}, Permission, Request, Response, }, device, }, Ctap2_2Authenticator, }; use sha2::Digest; #[test] fn test_get_pin_retries() { let mut guard = AUTHENTICATOR.lock().unwrap(); let authenticator = guard.as_mut().unwrap(); let req = Request::GetPinRetries; println!("request: {req:#?}"); let res = authenticator.client_pin(req).unwrap(); println!("response: {res:#?}"); let Response::GetPinRetries { pin_retries, power_cycle_state, } = res else { panic!("unexpected response"); }; println!( "pin_retries: {:#?}, power_cycle_state: {:#?}", pin_retries, power_cycle_state ); } #[test] fn test_get_key_agreement() { let mut guard = AUTHENTICATOR.lock().unwrap(); let mut authenticator = guard.as_mut().unwrap(); get_session(&mut authenticator); } #[test] fn test_set_new_pin() { let mut guard = AUTHENTICATOR.lock().unwrap(); let mut authenticator = guard.as_mut().unwrap(); let version = auth_protocol::Version::One; let session = get_session(&mut authenticator); let pin = "12345678"; let mut padded_pin = [0u8; 64]; pin.as_bytes().iter().enumerate().for_each(|(i, b)| { padded_pin[i] = *b; }); let padded_pin: [[u8; 16]; 4] = unsafe { std::mem::transmute(padded_pin) }; let new_pin_encrypted = session.encrypt(&padded_pin).unwrap(); let new_pin_encrypted = new_pin_encrypted.into_iter().flatten().collect::>(); println!("new_pin_encrypted: {:#?}", new_pin_encrypted); // Set New Pin let req = Request::SetPin { key_agreement: session.platform_key_agreement_key().clone(), new_pin_encrypted: new_pin_encrypted.split_array_ref::<64>().0.to_owned(), pin_uv_auth_param: session.authenticate(&new_pin_encrypted).unwrap(), version, }; println!("request: {req:#?}"); let res = authenticator.client_pin(req).unwrap(); println!("response: {res:#?}"); } #[test] fn test_change_pin() { let mut guard = AUTHENTICATOR.lock().unwrap(); let mut authenticator = guard.as_mut().unwrap(); let version = auth_protocol::Version::One; let session = get_session(&mut authenticator); let old_pin = "12345678"; let new_pin = "87654321"; let mut padded_new_pin = [0u8; 64]; new_pin.as_bytes().iter().enumerate().for_each(|(i, b)| { padded_new_pin[i] = *b; }); let padded_new_pin: [[u8; 16]; 4] = unsafe { std::mem::transmute(padded_new_pin) }; let new_pin_encrypted = session.encrypt(&padded_new_pin).unwrap(); let new_pin_encrypted = new_pin_encrypted.into_iter().flatten().collect::>(); println!("new_pin_encrypted: {:#?}", new_pin_encrypted); // pinHashEnc: The result of calling encrypt(shared secret, // LEFT(SHA-256(curPin), 16)). let pin_hash_encrypted = session .encrypt(&[*sha2::Sha256::digest(old_pin.as_bytes()) .split_array_ref::<16>() .0]) .unwrap()[0]; // newPinEnc: the result of calling encrypt(shared secret, paddedPin) let new_pin_encrypted = session.encrypt(&padded_new_pin).unwrap(); let new_pin_encrypted = unsafe { std::mem::transmute::<_, [u8; 64]>(new_pin_encrypted) }; // pinUvAuthParam: the result of calling authenticate(shared secret, newPinEnc // || pinHashEnc). let pin_uv_auth_param = session .authenticate( [new_pin_encrypted.as_slice(), pin_hash_encrypted.as_slice()] .concat() .as_slice(), ) .unwrap(); // Change Pin let req = Request::ChangePin { version, pin_hash_encrypted, new_pin_encrypted, pin_uv_auth_param, key_agreement: session.platform_key_agreement_key().clone(), }; println!("request: {req:#?}"); let res = authenticator.client_pin(req).unwrap(); println!("response: {res:#?}"); } #[test] fn test_get_pin_token() { let mut guard = AUTHENTICATOR.lock().unwrap(); let mut authenticator = guard.as_mut().unwrap(); let version = auth_protocol::Version::One; let session = get_session(&mut authenticator); let pin = "87654321"; let mut padded_pin = [0u8; 64]; pin.as_bytes().iter().enumerate().for_each(|(i, b)| { padded_pin[i] = *b; }); let padded_pin: [[u8; 16]; 4] = unsafe { std::mem::transmute(padded_pin) }; let new_pin_encrypted = session.encrypt(&padded_pin).unwrap(); let new_pin_encrypted = new_pin_encrypted.into_iter().flatten().collect::>(); println!("new_pin_encrypted: {:#?}", new_pin_encrypted); // pinHashEnc: The result of calling encrypt(shared secret, // LEFT(SHA-256(curPin), 16)). let pin_hash_encrypted = session .encrypt(&[*sha2::Sha256::digest(pin.as_bytes()) .split_array_ref::<16>() .0]) .unwrap()[0]; // Get Pin Token let req = Request::GetPinToken { key_agreement: session.platform_key_agreement_key().clone(), version, pin_hash_encrypted, }; println!("request: {req:#?}"); let res = authenticator.client_pin(req).unwrap(); println!("response: {res:#?}"); } #[test] fn test_get_pin_uv_auth_token_using_uv_with_permissions() { let mut guard = AUTHENTICATOR.lock().unwrap(); let authenticator = guard.as_mut().unwrap(); let info = authenticator.get_info(); if let Some(options) = info.options { if !options.contains_key(&device::OptionId::UserVerification) { panic!("UserVerification not supported"); } } todo!() } #[test] fn test_get_uv_retries() { let mut guard = AUTHENTICATOR.lock().unwrap(); let authenticator = guard.as_mut().unwrap(); let options = authenticator.get_info().options.unwrap(); if !options.contains_key(&device::OptionId::UserVerification) { panic!("UserVerification not supported"); } // Get UV Retries let req = Request::GetUvRetries; println!("request: {req:#?}"); let res = authenticator.client_pin(req).unwrap(); println!("response: {res:#?}"); } #[test] fn test_get_pin_uv_auth_token_using_pin_with_permissions() { let mut guard = AUTHENTICATOR.lock().unwrap(); let mut authenticator = guard.as_mut().unwrap(); let info = authenticator.get_info(); if let Some(options) = info.options { if !options .get(&device::OptionId::UserVerification) .unwrap_or(&false) || !options.get(&device::OptionId::ClientPin).unwrap_or(&false) { panic!("UserVerification or ClientPin not supported"); } } let pin = "87654321"; let pin_hash_encrypted = sha2::Sha256::digest(pin.as_bytes()) .split_array_ref::<16>() .0 .to_owned(); let version = auth_protocol::Version::One; let session = get_session(&mut authenticator); let req = Request::GetPinUvAuthTokenUsingPinWithPermissions { version, key_agreement: session.platform_key_agreement_key().clone(), pin_hash_encrypted, permissions: &[ Permission::MakeCredential, Permission::GetAssertion, Permission::CredentialManagement, ] .into_iter() .collect(), relying_party_id: Some("example.com".into()), }; println!("request: {req:#?}"); let res = authenticator.client_pin(req).unwrap(); println!("response: {res:#?}"); }