You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
248 lines
7.5 KiB
Rust
248 lines
7.5 KiB
Rust
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::<Vec<_>>();
|
|
|
|
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::<Vec<_>>();
|
|
|
|
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::<Vec<_>>();
|
|
|
|
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:#?}");
|
|
}
|