Return arrays for fixed-size objects
This commit is contained in:
@@ -464,7 +464,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut auth_data = self.generate_auth_data(&rp_id_hash, flags)?;
|
let mut auth_data = self.generate_auth_data(&rp_id_hash, flags)?;
|
||||||
auth_data.append(&mut self.persistent_store.aaguid()?);
|
auth_data.extend(&self.persistent_store.aaguid()?);
|
||||||
// The length is fixed to 0x20 or 0x70 and fits one byte.
|
// The length is fixed to 0x20 or 0x70 and fits one byte.
|
||||||
if credential_id.len() > 0xFF {
|
if credential_id.len() > 0xFF {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG);
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG);
|
||||||
@@ -493,7 +493,6 @@ where
|
|||||||
// decide whether batch attestation is needed.
|
// decide whether batch attestation is needed.
|
||||||
let (signature, x5c) = match self.persistent_store.attestation_private_key()? {
|
let (signature, x5c) = match self.persistent_store.attestation_private_key()? {
|
||||||
Some(attestation_private_key) => {
|
Some(attestation_private_key) => {
|
||||||
let attestation_private_key = array_ref![attestation_private_key, 0, 32];
|
|
||||||
let attestation_key =
|
let attestation_key =
|
||||||
crypto::ecdsa::SecKey::from_bytes(attestation_private_key).unwrap();
|
crypto::ecdsa::SecKey::from_bytes(attestation_private_key).unwrap();
|
||||||
let attestation_certificate = self
|
let attestation_certificate = self
|
||||||
@@ -722,7 +721,6 @@ where
|
|||||||
String::from("clientPin"),
|
String::from("clientPin"),
|
||||||
self.persistent_store.pin_hash()?.is_some(),
|
self.persistent_store.pin_hash()?.is_some(),
|
||||||
);
|
);
|
||||||
let aaguid = self.persistent_store.aaguid()?;
|
|
||||||
Ok(ResponseData::AuthenticatorGetInfo(
|
Ok(ResponseData::AuthenticatorGetInfo(
|
||||||
AuthenticatorGetInfoResponse {
|
AuthenticatorGetInfoResponse {
|
||||||
versions: vec![
|
versions: vec![
|
||||||
@@ -731,7 +729,7 @@ where
|
|||||||
String::from(FIDO2_VERSION_STRING),
|
String::from(FIDO2_VERSION_STRING),
|
||||||
],
|
],
|
||||||
extensions: Some(vec![String::from("hmac-secret")]),
|
extensions: Some(vec![String::from("hmac-secret")]),
|
||||||
aaguid: *array_ref![aaguid, 0, 16],
|
aaguid: self.persistent_store.aaguid()?,
|
||||||
options: Some(options_map),
|
options: Some(options_map),
|
||||||
max_msg_size: Some(1024),
|
max_msg_size: Some(1024),
|
||||||
pin_protocols: Some(vec![
|
pin_protocols: Some(vec![
|
||||||
@@ -855,7 +853,7 @@ mod test {
|
|||||||
0x02, 0x81, 0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
|
0x02, 0x81, 0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
|
||||||
0x03, 0x50,
|
0x03, 0x50,
|
||||||
]);
|
]);
|
||||||
expected_response.extend(ctap_state.persistent_store.aaguid().unwrap());
|
expected_response.extend(&ctap_state.persistent_store.aaguid().unwrap());
|
||||||
expected_response.extend(&[
|
expected_response.extend(&[
|
||||||
0x04, 0xA3, 0x62, 0x72, 0x6B, 0xF5, 0x62, 0x75, 0x70, 0xF5, 0x69, 0x63, 0x6C, 0x69,
|
0x04, 0xA3, 0x62, 0x72, 0x6B, 0xF5, 0x62, 0x75, 0x70, 0xF5, 0x69, 0x63, 0x6C, 0x69,
|
||||||
0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E, 0xF4, 0x05, 0x19, 0x04, 0x00, 0x06, 0x81, 0x01,
|
0x65, 0x6E, 0x74, 0x50, 0x69, 0x6E, 0xF4, 0x05, 0x19, 0x04, 0x00, 0x06, 0x81, 0x01,
|
||||||
@@ -954,7 +952,7 @@ mod test {
|
|||||||
0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2,
|
0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2,
|
||||||
0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00,
|
0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00,
|
||||||
];
|
];
|
||||||
expected_auth_data.extend(ctap_state.persistent_store.aaguid().unwrap());
|
expected_auth_data.extend(&ctap_state.persistent_store.aaguid().unwrap());
|
||||||
expected_auth_data.extend(&[0x00, 0x20]);
|
expected_auth_data.extend(&[0x00, 0x20]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
auth_data[0..expected_auth_data.len()],
|
auth_data[0..expected_auth_data.len()],
|
||||||
@@ -991,7 +989,7 @@ mod test {
|
|||||||
0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2,
|
0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2,
|
||||||
0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00,
|
0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00,
|
||||||
];
|
];
|
||||||
expected_auth_data.extend(ctap_state.persistent_store.aaguid().unwrap());
|
expected_auth_data.extend(&ctap_state.persistent_store.aaguid().unwrap());
|
||||||
expected_auth_data.extend(&[0x00, ENCRYPTED_CREDENTIAL_ID_SIZE as u8]);
|
expected_auth_data.extend(&[0x00, ENCRYPTED_CREDENTIAL_ID_SIZE as u8]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
auth_data[0..expected_auth_data.len()],
|
auth_data[0..expected_auth_data.len()],
|
||||||
@@ -1136,7 +1134,7 @@ mod test {
|
|||||||
0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2,
|
0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2,
|
||||||
0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0xC1, 0x00, 0x00, 0x00, 0x00,
|
0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0xC1, 0x00, 0x00, 0x00, 0x00,
|
||||||
];
|
];
|
||||||
expected_auth_data.extend(ctap_state.persistent_store.aaguid().unwrap());
|
expected_auth_data.extend(&ctap_state.persistent_store.aaguid().unwrap());
|
||||||
expected_auth_data.extend(&[0x00, 0x20]);
|
expected_auth_data.extend(&[0x00, 0x20]);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
auth_data[0..expected_auth_data.len()],
|
auth_data[0..expected_auth_data.len()],
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ enum Key {
|
|||||||
MinPinLengthRpIds,
|
MinPinLengthRpIds,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MasterKeys(Vec<u8>);
|
pub struct MasterKeys([u8; 64]);
|
||||||
|
|
||||||
impl MasterKeys {
|
impl MasterKeys {
|
||||||
pub fn encryption(&self) -> &[u8; 32] {
|
pub fn encryption(&self) -> &[u8; 32] {
|
||||||
@@ -382,10 +382,10 @@ impl PersistentStore {
|
|||||||
if entry.data.len() != 64 {
|
if entry.data.len() != 64 {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
Ok(MasterKeys(entry.data.to_vec()))
|
Ok(MasterKeys(*array_ref![entry.data, 0, 64]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pin_hash(&self) -> Result<Option<Vec<u8>>, Ctap2StatusCode> {
|
pub fn pin_hash(&self) -> Result<Option<[u8; PIN_AUTH_LENGTH]>, Ctap2StatusCode> {
|
||||||
let data = match self.store.find_one(&Key::PinHash) {
|
let data = match self.store.find_one(&Key::PinHash) {
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
Some((_, entry)) => entry.data,
|
Some((_, entry)) => entry.data,
|
||||||
@@ -393,7 +393,7 @@ impl PersistentStore {
|
|||||||
if data.len() != PIN_AUTH_LENGTH {
|
if data.len() != PIN_AUTH_LENGTH {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
Ok(Some(data.to_vec()))
|
Ok(Some(*array_ref![data, 0, PIN_AUTH_LENGTH]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_pin_hash(
|
pub fn set_pin_hash(
|
||||||
@@ -575,7 +575,7 @@ impl PersistentStore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn aaguid(&self) -> Result<Vec<u8>, Ctap2StatusCode> {
|
pub fn aaguid(&self) -> Result<[u8; AAGUID_LENGTH], Ctap2StatusCode> {
|
||||||
let (_, entry) = self
|
let (_, entry) = self
|
||||||
.store
|
.store
|
||||||
.find_one(&Key::Aaguid)
|
.find_one(&Key::Aaguid)
|
||||||
@@ -584,7 +584,7 @@ impl PersistentStore {
|
|||||||
if data.len() != AAGUID_LENGTH {
|
if data.len() != AAGUID_LENGTH {
|
||||||
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
Ok(data.to_vec())
|
Ok(*array_ref![data, 0, AAGUID_LENGTH])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_aaguid(&mut self, aaguid: &[u8; AAGUID_LENGTH]) -> Result<(), Ctap2StatusCode> {
|
pub fn set_aaguid(&mut self, aaguid: &[u8; AAGUID_LENGTH]) -> Result<(), Ctap2StatusCode> {
|
||||||
@@ -954,14 +954,14 @@ mod test {
|
|||||||
// Setting the pin hash sets the pin hash.
|
// Setting the pin hash sets the pin hash.
|
||||||
let random_data = rng.gen_uniform_u8x32();
|
let random_data = rng.gen_uniform_u8x32();
|
||||||
assert_eq!(random_data.len(), 2 * PIN_AUTH_LENGTH);
|
assert_eq!(random_data.len(), 2 * PIN_AUTH_LENGTH);
|
||||||
let pin_hash_1 = array_ref!(random_data, 0, PIN_AUTH_LENGTH);
|
let pin_hash_1 = *array_ref!(random_data, 0, PIN_AUTH_LENGTH);
|
||||||
let pin_hash_2 = array_ref!(random_data, PIN_AUTH_LENGTH, PIN_AUTH_LENGTH);
|
let pin_hash_2 = *array_ref!(random_data, PIN_AUTH_LENGTH, PIN_AUTH_LENGTH);
|
||||||
persistent_store.set_pin_hash(&pin_hash_1).unwrap();
|
persistent_store.set_pin_hash(&pin_hash_1).unwrap();
|
||||||
assert_eq!(persistent_store.pin_hash().unwrap().unwrap(), pin_hash_1);
|
assert_eq!(persistent_store.pin_hash().unwrap(), Some(pin_hash_1));
|
||||||
assert_eq!(persistent_store.pin_hash().unwrap().unwrap(), pin_hash_1);
|
assert_eq!(persistent_store.pin_hash().unwrap(), Some(pin_hash_1));
|
||||||
persistent_store.set_pin_hash(&pin_hash_2).unwrap();
|
persistent_store.set_pin_hash(&pin_hash_2).unwrap();
|
||||||
assert_eq!(persistent_store.pin_hash().unwrap().unwrap(), pin_hash_2);
|
assert_eq!(persistent_store.pin_hash().unwrap(), Some(pin_hash_2));
|
||||||
assert_eq!(persistent_store.pin_hash().unwrap().unwrap(), pin_hash_2);
|
assert_eq!(persistent_store.pin_hash().unwrap(), Some(pin_hash_2));
|
||||||
|
|
||||||
// Resetting the storage resets the pin hash.
|
// Resetting the storage resets the pin hash.
|
||||||
persistent_store.reset(&mut rng).unwrap();
|
persistent_store.reset(&mut rng).unwrap();
|
||||||
@@ -1013,7 +1013,7 @@ mod test {
|
|||||||
persistent_store
|
persistent_store
|
||||||
.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE)
|
.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(persistent_store.aaguid().unwrap(), key_material::AAGUID);
|
assert_eq!(&persistent_store.aaguid().unwrap(), key_material::AAGUID);
|
||||||
|
|
||||||
// The persistent keys stay initialized and preserve their value after a reset.
|
// The persistent keys stay initialized and preserve their value after a reset.
|
||||||
persistent_store.reset(&mut rng).unwrap();
|
persistent_store.reset(&mut rng).unwrap();
|
||||||
@@ -1025,7 +1025,7 @@ mod test {
|
|||||||
persistent_store.attestation_certificate().unwrap().unwrap(),
|
persistent_store.attestation_certificate().unwrap().unwrap(),
|
||||||
key_material::ATTESTATION_CERTIFICATE
|
key_material::ATTESTATION_CERTIFICATE
|
||||||
);
|
);
|
||||||
assert_eq!(persistent_store.aaguid().unwrap(), key_material::AAGUID);
|
assert_eq!(&persistent_store.aaguid().unwrap(), key_material::AAGUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "with_ctap2_1")]
|
#[cfg(feature = "with_ctap2_1")]
|
||||||
|
|||||||
Reference in New Issue
Block a user