Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client pin features #127

Merged
merged 22 commits into from
Aug 20, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a4becf9
new error codes and enum cleanups
kaczmarczyck Jun 18, 2020
63aef3b
new client pin subcommands
kaczmarczyck Jun 18, 2020
9ff988d
refactors the client PIN implementation into a new module
kaczmarczyck Jun 24, 2020
033f544
adding tests to pin_protocol_v1
kaczmarczyck Jun 26, 2020
26595db
adds new client Pin subcommand minPinLength implementation
kaczmarczyck Jun 26, 2020
216a6a0
adds permissions and adapts clientPin 2.1 subcommands
kaczmarczyck Jul 2, 2020
3b66155
adds clarifications, improvements and tests
kaczmarczyck Jul 6, 2020
04278d9
adds code style improvements, including a new enum for permissions
kaczmarczyck Jul 8, 2020
131f876
use the enum-iterator crate for better testing of enums
kaczmarczyck Jul 8, 2020
25b6756
improved documentation for the PinPermission enum
kaczmarczyck Jul 8, 2020
950d90f
moves enum-iterator dependency to dev and updates binary reference va…
kaczmarczyck Jul 9, 2020
cc0e2bb
updates reproducible binary hashes and sizes
kaczmarczyck Jul 9, 2020
9c67384
improved documentation, especially with regards to the extension
kaczmarczyck Jul 9, 2020
a398c40
improves documentation to address comments
kaczmarczyck Jul 27, 2020
4e4ed12
Merge branch 'master' into client-pin-features
kaczmarczyck Jul 28, 2020
d5fefa2
improved code consistency and documentation
kaczmarczyck Aug 4, 2020
0aabf82
improved testing in pin_protocol_v1.rs
kaczmarczyck Aug 13, 2020
bbcff48
unifying the use instructions to another standard
kaczmarczyck Aug 17, 2020
77b21e9
improved documentation
kaczmarczyck Aug 19, 2020
fe57be2
Merge branch 'master' into client-pin-features
kaczmarczyck Aug 19, 2020
9259102
makes tests more readable
kaczmarczyck Aug 20, 2020
6902115
updates reproducible references
kaczmarczyck Aug 20, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ crypto = { path = "libraries/crypto" }
byteorder = { version = "1", default-features = false }
arrayref = "0.3.6"
subtle = { version = "2.2", default-features = false, features = ["nightly"] }
enum-iterator = "0.6.0"
kaczmarczyck marked this conversation as resolved.
Show resolved Hide resolved

[features]
debug_allocations = ["libtock/debug_allocations"]
Expand Down
40 changes: 18 additions & 22 deletions src/ctap/data_formats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use alloc::string::String;
use alloc::vec::Vec;
use core::convert::TryFrom;
use crypto::{ecdh, ecdsa};
#[cfg(test)]
use enum_iterator::IntoEnumIterator;

// https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrpentity
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))]
Expand Down Expand Up @@ -167,6 +169,7 @@ impl From<PublicKeyCredentialParameter> for cbor::Value {

// https://www.w3.org/TR/webauthn/#enumdef-authenticatortransport
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Clone, Debug, PartialEq))]
#[cfg_attr(test, derive(IntoEnumIterator))]
pub enum AuthenticatorTransport {
Usb,
Nfc,
Expand Down Expand Up @@ -455,6 +458,7 @@ impl TryFrom<cbor::Value> for SignatureAlgorithm {

#[derive(Clone, Copy, PartialEq, PartialOrd)]
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug))]
#[cfg_attr(test, derive(IntoEnumIterator))]
pub enum CredentialProtectionPolicy {
UserVerificationOptional = 0x01,
UserVerificationOptionalWithCredentialIdList = 0x02,
Expand Down Expand Up @@ -684,7 +688,8 @@ impl TryFrom<CoseKey> for ecdh::PubKey {
}
}

#[cfg_attr(any(test, feature = "debug_ctap"), derive(Debug, PartialEq))]
#[cfg_attr(any(test, feature = "debug_ctap"), derive(Clone, Debug, PartialEq))]
#[cfg_attr(test, derive(IntoEnumIterator))]
pub enum ClientPinSubCommand {
GetPinRetries = 0x01,
GetKeyAgreement = 0x02,
Expand Down Expand Up @@ -1167,11 +1172,10 @@ mod test {
let expected_error = Err(Ctap2StatusCode::CTAP2_ERR_CBOR_UNEXPECTED_TYPE);
assert_eq!(policy_error, expected_error);

for policy_literal in 1..=3 {
let cbor_policy: cbor::Value = cbor_int!(policy_literal);
let policy = CredentialProtectionPolicy::try_from(cbor_policy.clone());
let created_cbor: cbor::Value = policy.unwrap().into();
assert_eq!(created_cbor, cbor_policy);
for policy in CredentialProtectionPolicy::into_enum_iter() {
let created_cbor: cbor::Value = policy.into();
let reconstructed = CredentialProtectionPolicy::try_from(created_cbor).unwrap();
assert_eq!(policy, reconstructed);
}
}

Expand All @@ -1188,13 +1192,10 @@ mod test {
let created_cbor: cbor::Value = authenticator_transport.unwrap().into();
assert_eq!(created_cbor, cbor_authenticator_transport);

let transports = ["usb", "nfc", "ble", "internal"];
for transport in transports.iter() {
let cbor_authenticator_transport: cbor::Value = cbor_text!(*transport);
let authenticator_transport =
AuthenticatorTransport::try_from(cbor_authenticator_transport.clone());
let created_cbor: cbor::Value = authenticator_transport.unwrap().into();
assert_eq!(created_cbor, cbor_authenticator_transport);
for transport in AuthenticatorTransport::into_enum_iter() {
let created_cbor: cbor::Value = transport.clone().into();
let reconstructed = AuthenticatorTransport::try_from(created_cbor).unwrap();
assert_eq!(transport, reconstructed);
}
}

Expand Down Expand Up @@ -1339,15 +1340,10 @@ mod test {
let created_cbor: cbor::Value = sub_command.unwrap().into();
assert_eq!(created_cbor, cbor_sub_command);

#[cfg(not(feature = "with_ctap2_1"))]
let last_literal = 0x05;
#[cfg(feature = "with_ctap2_1")]
let last_literal = 0x09;
for command_literal in 1..=last_literal {
let cbor_sub_command: cbor::Value = cbor_int!(command_literal);
let sub_command = ClientPinSubCommand::try_from(cbor_sub_command.clone());
let created_cbor: cbor::Value = sub_command.unwrap().into();
assert_eq!(created_cbor, cbor_sub_command);
for command in ClientPinSubCommand::into_enum_iter() {
let created_cbor: cbor::Value = command.clone().into();
let reconstructed = ClientPinSubCommand::try_from(created_cbor).unwrap();
assert_eq!(command, reconstructed);
}
}

Expand Down
60 changes: 12 additions & 48 deletions src/ctap/pin_protocol_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ use crypto::hmac::{hmac_256, verify_hmac_256_first_128bits};
use crypto::rng256::Rng256;
use crypto::sha256::Sha256;
use crypto::Hash256;
#[cfg(all(test, feature = "with_ctap2_1"))]
use enum_iterator::IntoEnumIterator;
use subtle::ConstantTimeEq;

// Those constants have to be multiples of 16, the AES block size.
Expand Down Expand Up @@ -143,6 +145,7 @@ fn check_and_store_new_pin(
}

#[cfg(feature = "with_ctap2_1")]
#[cfg_attr(test, derive(IntoEnumIterator))]
// TODO remove when all variants are used
#[allow(dead_code)]
pub enum PinPermission {
Expand Down Expand Up @@ -1102,55 +1105,16 @@ mod test {
let mut rng = ThreadRng256 {};
let mut pin_protocol_v1 = PinProtocolV1::new(&mut rng);
pin_protocol_v1.permissions = 0x7F;
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::MakeCredential),
Ok(())
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::GetAssertion),
Ok(())
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::CredentialManagement),
Ok(())
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::BioEnrollment),
Ok(())
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::PlatformConfiguration),
Ok(())
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::AuthenticatorConfiguration),
Ok(())
);
for permission in PinPermission::into_enum_iter() {
assert_eq!(pin_protocol_v1.has_permission(permission), Ok(()));
}
pin_protocol_v1.permissions = 0x00;
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::MakeCredential),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::GetAssertion),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::CredentialManagement),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::BioEnrollment),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::PlatformConfiguration),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
assert_eq!(
pin_protocol_v1.has_permission(PinPermission::AuthenticatorConfiguration),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
for permission in PinPermission::into_enum_iter() {
assert_eq!(
pin_protocol_v1.has_permission(permission),
Err(Ctap2StatusCode::CTAP2_ERR_PIN_AUTH_INVALID)
);
}
}

#[cfg(feature = "with_ctap2_1")]
Expand Down