diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d69e649..703193d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: - name: Check library run: | cargo check + cargo check --features arbitrary cargo check --features get-info-full cargo check --features large-blobs cargo check --all-features diff --git a/Cargo.toml b/Cargo.toml index 98eff84..df6e8dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ description = "no_std friendly types for FIDO CTAP" repository = "https://github.com/trussed-dev/ctap-types" [dependencies] +arbitrary = { version = "1.3.2", features = ["derive"], optional = true } bitflags = "1.3" cbor-smol = "0.4" cosey = "0.3" @@ -21,6 +22,10 @@ serde_bytes = { version = "0.11.14", default-features = false } serde_repr = "0.1" [features] +std = [] + +# implements arbitrary::Arbitrary for requests +arbitrary = ["dep:arbitrary", "std"] # enables all fields for ctap2::get_info get-info-full = [] # enables support for implementing the large-blobs extension, see src/sizes.rs diff --git a/src/arbitrary.rs b/src/arbitrary.rs new file mode 100644 index 0000000..8a619a4 --- /dev/null +++ b/src/arbitrary.rs @@ -0,0 +1,31 @@ +use arbitrary::{Arbitrary, Unstructured, Result}; + +use crate::ctap1; + +// cannot be derived because of missing impl for &[T; N] +impl<'a> Arbitrary<'a> for ctap1::authenticate::Request<'a> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let control_byte = Arbitrary::arbitrary(u)?; + let challenge = u.bytes(32)?.try_into().unwrap(); + let app_id = u.bytes(32)?.try_into().unwrap(); + let key_handle = Arbitrary::arbitrary(u)?; + Ok(Self { + control_byte, + challenge, + app_id, + key_handle, + }) + } +} + +// cannot be derived because of missing impl for &[T; N] +impl<'a> Arbitrary<'a> for ctap1::register::Request<'a> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result { + let challenge = u.bytes(32)?.try_into().unwrap(); + let app_id = u.bytes(32)?.try_into().unwrap(); + Ok(Self { + challenge, + app_id, + }) + } +} diff --git a/src/ctap1.rs b/src/ctap1.rs index def7486..81d9f9b 100644 --- a/src/ctap1.rs +++ b/src/ctap1.rs @@ -72,6 +72,7 @@ pub mod register { #[repr(u8)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] pub enum ControlByte { // Conor: // I think U2F check-only maps to FIDO2 MakeCredential with the credID in the excludeList, @@ -109,6 +110,7 @@ pub type RegisterResponse = register::Response; pub type AuthenticateResponse = authenticate::Response; #[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))] #[allow(clippy::large_enum_variant)] /// Enum of all CTAP1 requests. pub enum Request<'a> { diff --git a/src/lib.rs b/src/lib.rs index 6763da2..da6cbc0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg_attr(not(test), no_std)] +#![cfg_attr(all(not(test), not(feature = "std")), no_std)] // #![no_std] //! `ctap-types` maps the various types involved in the FIDO CTAP protocol @@ -25,6 +25,8 @@ pub use heapless_bytes; pub use heapless_bytes::Bytes; pub use serde_bytes::ByteArray; +#[cfg(feature = "arbitrary")] +mod arbitrary; pub mod authenticator; pub mod ctap1; pub mod ctap2;