diff --git a/Cargo.toml b/Cargo.toml index 10bdd9b..9462210 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,23 +2,24 @@ name = "ctap-types" version = "0.1.0" authors = ["Nicolas Stalder "] -edition = "2018" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bitflags = "1.2.1" +bitflags = "1.3" cbor-smol = "0.4" -cosey = "0.3.0" -delog = "0.1.0" +cosey = "0.3" +delog = "0.1" heapless = { version = "0.7", default-features = false, features = ["serde"] } -heapless-bytes = "0.3.0" -interchange = "0.2.0" -serde = { version = "1.0", default-features = false, features = ["derive"] } -serde-indexed = "0.1.0" +heapless-bytes = "0.3" +interchange = "0.2.1" +serde = { version = "1", default-features = false, features = ["derive"] } +serde-indexed = "0.1" serde_repr = "0.1" -iso7816 = { git = "https://github.com/ycrypto/iso7816" } +# iso7816 = { git = "https://github.com/ycrypto/iso7816" } +iso7816 = "0.1.0-alpha.1" [features] log-all = ["cbor-smol/log-all"] diff --git a/src/authenticator.rs b/src/authenticator.rs index b0fbc5f..178c279 100644 --- a/src/authenticator.rs +++ b/src/authenticator.rs @@ -7,14 +7,20 @@ // } #[derive(Clone, Debug, PartialEq)] +// clippy says (2022-02-26): large size difference +// - first is 88 bytes +// - second is 10456 bytes +#[allow(clippy::large_enum_variant)] pub enum Request { Ctap1(ctap1::Request), Ctap2(ctap2::Request), } -// see below #[derive(Clone, Debug, PartialEq)] -// #[derive(Debug)] +// clippy says...large size difference +// - first is 0 bytes +// - second is 1880 bytes +#[allow(clippy::large_enum_variant)] pub enum Response { Ctap1(ctap1::Response), Ctap2(ctap2::Response), @@ -36,12 +42,13 @@ pub mod ctap1 { #[allow(non_camel_case_types)] _unused, } - } pub mod ctap2 { pub use crate::ctap2::*; #[derive(Clone, Debug, PartialEq)] + #[allow(clippy::large_enum_variant)] + // clippy says...large size difference pub enum Request { // 0x1 MakeCredential(make_credential::Parameters), @@ -74,12 +81,11 @@ pub mod ctap2 { // Q: how to handle the associated CBOR structures Vendor, } - } // pub type Result = core::result::Result; -#[derive(Clone,Copy,Debug, Eq,PartialEq)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Error { Success = 0x00, InvalidCommand = 0x01, diff --git a/src/cose.rs b/src/cose.rs index b9cae9e..9a5c042 100644 --- a/src/cose.rs +++ b/src/cose.rs @@ -2,18 +2,18 @@ //! //! Data types and serde for public COSE_Keys //! -//! https://tools.ietf.org/html/rfc8152#section-7 +//! //! //! A COSE Key structure is built on a CBOR map object. The set of //! common parameters that can appear in a COSE Key can be found in the //! IANA "COSE Key Common Parameters" registry (Section 16.5). //! -//! https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters +//! //! //! Additional parameters defined for specific key types can be found in //! the IANA "COSE Key Type Parameters" registry (Section 16.6). //! -//! https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters +//! //! //! //! Key Type 1 (OKP) diff --git a/src/ctap1.rs b/src/ctap1.rs index 1a5061c..079bc39 100644 --- a/src/ctap1.rs +++ b/src/ctap1.rs @@ -1,7 +1,4 @@ -use iso7816::{ - Command as ApduCommand, - Instruction, -}; +use iso7816::{Command as ApduCommand, Instruction}; use crate::Bytes; @@ -10,13 +7,13 @@ pub const NO_ERROR: u16 = 0x9000; pub use iso7816::Status as Error; #[repr(u8)] -#[derive(Copy,Clone,Debug, Eq,PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum ControlByte { - // Conor: + // Conor: // I think U2F check-only maps to FIDO2 MakeCredential with the credID in the excludeList, // and pinAuth="" so the request will fail before UP check. // I think this is what the windows hello API does to silently check if a credential is - // on an authenticator + // on an authenticator CheckOnly = 0x07, EnforceUserPresenceAndSign = 0x03, DontEnforceUserPresenceAndSign = 0x08, @@ -37,13 +34,13 @@ impl core::convert::TryFrom for ControlByte { pub type Result = core::result::Result; -#[derive(Clone,Debug, Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Register { pub challenge: Bytes<32>, pub app_id: Bytes<32>, } -#[derive(Clone,Debug, Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct RegisterResponse { pub header_byte: u8, pub public_key: Bytes<65>, @@ -52,7 +49,7 @@ pub struct RegisterResponse { pub signature: Bytes<72>, } -#[derive(Clone,Debug, Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Authenticate { pub control_byte: ControlByte, pub challenge: Bytes<32>, @@ -60,21 +57,23 @@ pub struct Authenticate { pub key_handle: Bytes<255>, } -#[derive(Clone,Debug, Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct AuthenticateResponse { user_presence: u8, count: u32, signature: Bytes<72>, } -#[derive(Clone,Debug, Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[allow(clippy::large_enum_variant)] pub enum Command { Register(Register), Authenticate(Authenticate), Version, } -#[derive(Clone,Debug, Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] +#[allow(clippy::large_enum_variant)] pub enum Response { Register(RegisterResponse), Authenticate(AuthenticateResponse), @@ -89,10 +88,9 @@ impl RegisterResponse { signature: Bytes<72>, attestation_certificate: &[u8], ) -> Self { - - debug_assert!(key_handle.len()<=255); - debug_assert!(attestation_certificate.len()<=1024); - debug_assert!(signature.len()<=72); + debug_assert!(key_handle.len() <= 255); + debug_assert!(attestation_certificate.len() <= 1024); + debug_assert!(signature.len() <= 72); let mut public_key_bytes = Bytes::new(); let mut key_handle_bytes = Bytes::new(); @@ -104,52 +102,51 @@ impl RegisterResponse { key_handle_bytes.extend_from_slice(key_handle).unwrap(); - cert_bytes.extend_from_slice(attestation_certificate).unwrap(); + cert_bytes + .extend_from_slice(attestation_certificate) + .unwrap(); Self { - header_byte: header_byte, + header_byte, public_key: public_key_bytes, key_handle: key_handle_bytes, attestation_certificate: cert_bytes, - signature: signature, + signature, } } } impl AuthenticateResponse { - pub fn new( - user_presence: u8, - count: u32, - signature: Bytes<72>, - ) -> Self { + pub fn new(user_presence: u8, count: u32, signature: Bytes<72>) -> Self { Self { - user_presence: user_presence, - count: count, - signature: signature, + user_presence, + count, + signature, } } } impl Response { - pub fn serialize(&self, buf: &mut iso7816::Data) -> core::result::Result<(),()> - { + #[allow(clippy::result_unit_err)] + pub fn serialize( + &self, + buf: &mut iso7816::Data, + ) -> core::result::Result<(), ()> { match self { Response::Register(reg) => { - buf.push(reg.header_byte).ok(); - buf.extend_from_slice(®.public_key).ok(); - buf.push(reg.key_handle.len() as u8).ok(); - buf.extend_from_slice(®.key_handle).ok(); - buf.extend_from_slice(®.attestation_certificate).ok(); + buf.push(reg.header_byte).map_err(drop)?; + buf.extend_from_slice(®.public_key)?; + buf.push(reg.key_handle.len() as u8).map_err(drop)?; + buf.extend_from_slice(®.key_handle)?; + buf.extend_from_slice(®.attestation_certificate)?; buf.extend_from_slice(®.signature) - }, - Response::Authenticate(auth) => { - buf.push(auth.user_presence).ok(); - buf.extend_from_slice(&auth.count.to_be_bytes()).ok(); - buf.extend_from_slice(&auth.signature) - }, - Response::Version(version) => { - buf.extend_from_slice(version) } + Response::Authenticate(auth) => { + buf.push(auth.user_presence).map_err(drop)?; + buf.extend_from_slice(&auth.count.to_be_bytes())?; + buf.extend_from_slice(&auth.signature) + } + Response::Version(version) => buf.extend_from_slice(version), } } } @@ -186,7 +183,7 @@ impl core::convert::TryFrom<&ApduCommand> for Command { challenge: Bytes::from_slice(&request[..32]).unwrap(), app_id: Bytes::from_slice(&request[32..]).unwrap(), })) - }, + } // authenticate 0x2 => { @@ -204,12 +201,10 @@ impl core::convert::TryFrom<&ApduCommand> for Command { app_id: Bytes::from_slice(&request[32..64]).unwrap(), key_handle: Bytes::from_slice(&request[65..]).unwrap(), })) - }, + } // version - 0x3 => { - Ok(Command::Version) - } + 0x3 => Ok(Command::Version), _ => Err(Error::InstructionNotSupportedOrInvalid), } diff --git a/src/ctap2.rs b/src/ctap2.rs index 597a799..597b0e7 100644 --- a/src/ctap2.rs +++ b/src/ctap2.rs @@ -1,14 +1,14 @@ use bitflags::bitflags; use serde::{Deserialize, Serialize}; -use crate::Bytes; use crate::sizes::*; +use crate::Bytes; pub mod client_pin; pub mod credential_management; pub mod get_assertion; -pub mod get_next_assertion; pub mod get_info; +pub mod get_next_assertion; pub mod make_credential; // TODO: this is a bit weird to model... @@ -27,7 +27,7 @@ pub mod make_credential; // // pub cred_protect: // } -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct AuthenticatorOptions { #[serde(skip_serializing_if = "Option::is_none")] pub rk: Option, @@ -131,7 +131,7 @@ pub trait SerializeAttestedCredentialData { fn serialize(&self) -> Bytes; } -#[derive(Clone,Debug,Eq,PartialEq)] +#[derive(Clone, Debug, Eq, PartialEq)] // #[serde(rename_all = "camelCase")] pub struct AuthenticatorData { pub rp_id_hash: Bytes<32>, @@ -140,7 +140,7 @@ pub struct AuthenticatorData { // this can get pretty long // pub attested_credential_data: Option>, pub attested_credential_data: Option, - pub extensions: Option + pub extensions: Option, } pub type SerializedAuthenticatorData = Bytes; @@ -157,11 +157,15 @@ impl AuthenticatorData< // flags bytes.push(self.flags.bits()).unwrap(); // signature counts as 32-bit unsigned big-endian integer. - bytes.extend_from_slice(&self.sign_count.to_be_bytes()).unwrap(); + bytes + .extend_from_slice(&self.sign_count.to_be_bytes()) + .unwrap(); // the attested credential data if let Some(ref attested_credential_data) = &self.attested_credential_data { - bytes.extend_from_slice(&attested_credential_data.serialize()).unwrap(); + bytes + .extend_from_slice(&attested_credential_data.serialize()) + .unwrap(); } // the extensions data @@ -175,7 +179,6 @@ impl AuthenticatorData< } } - // // TODO: add Default and builder // #[derive(Clone,Debug,Eq,PartialEq,Serialize)] // pub struct AuthenticatorInfo<'l> { diff --git a/src/ctap2/client_pin.rs b/src/ctap2/client_pin.rs index b978e89..f7bdf7c 100644 --- a/src/ctap2/client_pin.rs +++ b/src/ctap2/client_pin.rs @@ -4,7 +4,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::cose::EcdhEsHkdf256PublicKey; -#[derive(Clone,Debug, Eq,PartialEq,Serialize_repr,Deserialize_repr)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum PinV1Subcommand { GetRetries = 0x01, @@ -21,7 +21,7 @@ pub enum PinV1Subcommand { // maximum PIN length: UTF-8 represented by <= 63 bytes // maximum consecutive incorrect PIN attempts: 8 -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct Parameters { // 0x01 @@ -55,10 +55,9 @@ pub struct Parameters { // Encrypted first 16 bytes of SHA-256 of PIN using `sharedSecret`. #[serde(skip_serializing_if = "Option::is_none")] pub pin_hash_enc: Option>, - } -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct Response { // 0x01, like ClientPinParameters::key_agreement @@ -72,7 +71,6 @@ pub struct Response { // 0x03, number of PIN attempts remaining before lockout #[serde(skip_serializing_if = "Option::is_none")] pub retries: Option, - } #[cfg(test)] diff --git a/src/ctap2/credential_management.rs b/src/ctap2/credential_management.rs index 9f25a70..164867d 100644 --- a/src/ctap2/credential_management.rs +++ b/src/ctap2/credential_management.rs @@ -5,13 +5,11 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::{ cose::PublicKey, webauthn::{ - PublicKeyCredentialDescriptor, - PublicKeyCredentialRpEntity, - PublicKeyCredentialUserEntity, - } + PublicKeyCredentialDescriptor, PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, + }, }; - #[derive(Copy,Clone,Debug, Eq,PartialEq,Serialize_repr,Deserialize_repr)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)] // #[derive(Clone,Debug,Eq,PartialEq,Serialize, Deserialize)] // #[serde(tag = "credProtect")] #[repr(u8)] @@ -30,21 +28,18 @@ impl core::default::Default for CredentialProtectionPolicy { } } - - -#[derive(Clone,Copy,Debug, Eq,PartialEq,Serialize_repr,Deserialize_repr)] +#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)] #[repr(u8)] -pub enum Subcommand { - GetCredsMetadata = 0x01, // 1, 2 - EnumerateRpsBegin = 0x02, // 3, 4, 5 - EnumerateRpsGetNextRp = 0x03, // 3, 4 - EnumerateCredentialsBegin = 0x04, // 6, 7, 8 ,9, A +pub enum Subcommand { + GetCredsMetadata = 0x01, // 1, 2 + EnumerateRpsBegin = 0x02, // 3, 4, 5 + EnumerateRpsGetNextRp = 0x03, // 3, 4 + EnumerateCredentialsBegin = 0x04, // 6, 7, 8 ,9, A EnumerateCredentialsGetNextCredential = 0x05, // 6, 7, 8, A - DeleteCredential = 0x06, // - + DeleteCredential = 0x06, // - } - -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct SubcommandParameters { // 0x01 @@ -55,7 +50,7 @@ pub struct SubcommandParameters { pub credential_id: Option, } -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct Parameters { // 0x01 @@ -71,11 +66,10 @@ pub struct Parameters { pub pin_auth: Option, } -#[derive(Clone,Debug, Default,Eq,PartialEq,SerializeIndexed)] +#[derive(Clone, Debug, Default, Eq, PartialEq, SerializeIndexed)] #[serde_indexed(offset = 1)] // #[derive(Clone,Debug, Default,Eq,PartialEq,Serialize,Deserialize)] pub struct Response { - // Metadata // 0x01 diff --git a/src/ctap2/get_assertion.rs b/src/ctap2/get_assertion.rs index d5e6947..22801eb 100644 --- a/src/ctap2/get_assertion.rs +++ b/src/ctap2/get_assertion.rs @@ -14,7 +14,7 @@ use crate::webauthn::*; // pub hmac_secret: Option, // } -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct HmacSecretInput { pub key_agreement: EcdhEsHkdf256PublicKey, @@ -22,17 +22,17 @@ pub struct HmacSecretInput { pub salt_enc: Bytes<64>, pub salt_auth: Bytes<16>, #[serde(skip_serializing_if = "Option::is_none")] - pub pin_protocol: Option + pub pin_protocol: Option, } -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct ExtensionsInput { #[serde(rename = "hmac-secret")] #[serde(skip_serializing_if = "Option::is_none")] pub hmac_secret: Option, } -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize,Default)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)] pub struct ExtensionsOutput { #[serde(rename = "hmac-secret")] #[serde(skip_serializing_if = "Option::is_none")] @@ -40,7 +40,7 @@ pub struct ExtensionsOutput { pub hmac_secret: Option>, } -pub struct NoAttestedCredentialData (core::marker::PhantomData<()>); +pub struct NoAttestedCredentialData(core::marker::PhantomData<()>); impl super::SerializeAttestedCredentialData for NoAttestedCredentialData { fn serialize(&self) -> Bytes { @@ -52,7 +52,7 @@ pub type AuthenticatorData = super::AuthenticatorData; -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] // #[serde(rename_all = "camelCase")] #[serde_indexed(offset = 1)] pub struct Parameters { @@ -73,7 +73,7 @@ pub struct Parameters { // NB: attn object definition / order at end of // https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#authenticatorMakeCredential // does not coincide with what python-fido2 expects in AttestationObject.__init__ *at all* :'-) -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct Response { #[serde(skip_serializing_if = "Option::is_none")] diff --git a/src/ctap2/get_info.rs b/src/ctap2/get_info.rs index 45e76ea..6c2ca62 100644 --- a/src/ctap2/get_info.rs +++ b/src/ctap2/get_info.rs @@ -1,14 +1,13 @@ +use crate::webauthn::PublicKeyCredentialParameters; use crate::{Bytes, String, Vec}; use serde::{Deserialize, Serialize}; use serde_indexed::{DeserializeIndexed, SerializeIndexed}; -use crate::webauthn::PublicKeyCredentialParameters; pub type AuthenticatorInfo = Response; -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] #[serde_indexed(offset = 1)] pub struct Response { - // 0x01 pub versions: Vec, 4>, @@ -55,7 +54,6 @@ pub struct Response { // FIDO_2_1 #[serde(skip_serializing_if = "Option::is_none")] pub algorithms: Option>, - // #[serde(skip_serializing_if = "Option::is_none")] // pub(crate) algorithms: Option<&'l[u8]>, } @@ -69,8 +67,7 @@ impl Default for Response { Self { versions: Vec::new(), extensions: None, - aaguid: aaguid, - // options: None, + aaguid, options: Some(CtapOptions::default()), max_msg_size: None, //Some(MESSAGE_SIZE), pin_protocols: None, @@ -82,7 +79,7 @@ impl Default for Response { } } -#[derive(Copy,Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct CtapOptions { pub rk: bool, diff --git a/src/ctap2/make_credential.rs b/src/ctap2/make_credential.rs index 8587a79..38cb413 100644 --- a/src/ctap2/make_credential.rs +++ b/src/ctap2/make_credential.rs @@ -4,9 +4,9 @@ use serde::{Deserialize, Serialize}; use serde_indexed::{DeserializeIndexed, SerializeIndexed}; use super::{AuthenticatorOptions, PinAuth}; +use crate::ctap2::credential_management::CredentialProtectionPolicy; use crate::sizes::*; use crate::webauthn::*; -use crate::ctap2::credential_management::CredentialProtectionPolicy; // // Approach 1: // pub type AuthenticatorExtensions = heapless::LinearMap, bool, 2>; @@ -19,7 +19,7 @@ use crate::ctap2::credential_management::CredentialProtectionPolicy; // "userVerificationOptional" => CredentialProtectionPolicy::Optional, // "userVerificationOptionalWithCredentialIDList" => CredentialProtectionPolicy::OptionalWithCredentialIdList, // "userVerificationRequired" => CredentialProtectionPolicy::Required, -// _ => { return Err(Self::Error::InvalidParameter); } +// _ => return Err(Self::Error::InvalidParameter), // }) // } // } @@ -32,13 +32,13 @@ impl core::convert::TryFrom for CredentialProtectionPolicy { 1 => CredentialProtectionPolicy::Optional, 2 => CredentialProtectionPolicy::OptionalWithCredentialIdList, 3 => CredentialProtectionPolicy::Required, - _ => { return Err(Self::Error::InvalidParameter); } + _ => return Err(Self::Error::InvalidParameter), }) } } // Approach 2: -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct Extensions { #[serde(rename = "credProtect")] #[serde(skip_serializing_if = "Option::is_none")] @@ -46,11 +46,9 @@ pub struct Extensions { pub cred_protect: Option, // #[serde(serialize_with = "u8::from")] // pub cred_protect: Option, - #[serde(rename = "hmac-secret")] #[serde(skip_serializing_if = "Option::is_none")] pub hmac_secret: Option, - } // // Approach 3: @@ -68,7 +66,7 @@ pub struct Extensions { // pub extensions: Vec, // } -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed,DeserializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed, DeserializeIndexed)] // #[serde(rename_all = "camelCase")] #[serde_indexed(offset = 1)] pub struct Parameters { @@ -151,9 +149,9 @@ pub type AuthenticatorData = super::AuthenticatorData, + pub aaguid: Bytes<16>, // this is where "unlimited non-resident keys" get stored // TODO: Model as actual credential ID, with ser/de to bytes (format is up to authenticator) pub credential_id: Bytes, @@ -168,9 +166,13 @@ impl super::SerializeAttestedCredentialData for AttestedCredentialData { bytes.extend_from_slice(&self.aaguid).unwrap(); // byte length of credential ID as 16-bit unsigned big-endian integer. - bytes.extend_from_slice(&(self.credential_id.len() as u16).to_be_bytes()).unwrap(); + bytes + .extend_from_slice(&(self.credential_id.len() as u16).to_be_bytes()) + .unwrap(); // raw bytes of credential ID - bytes.extend_from_slice(&self.credential_id[..self.credential_id.len()]).unwrap(); + bytes + .extend_from_slice(&self.credential_id[..self.credential_id.len()]) + .unwrap(); // use existing `bytes` buffer // let mut cbor_key = [0u8; 128]; @@ -178,13 +180,15 @@ impl super::SerializeAttestedCredentialData for AttestedCredentialData { // CHANGE this back if credential_public_key is not serialized again // let l = crate::serde::cbor_serialize(&self.credential_public_key, &mut cbor_key).unwrap(); // bytes.extend_from_slice(&cbor_key[..l]).unwrap(); - bytes.extend_from_slice(&self.credential_public_key).unwrap(); + bytes + .extend_from_slice(&self.credential_public_key) + .unwrap(); Bytes::from(bytes) } } -#[derive(Clone,Debug, Eq,PartialEq,SerializeIndexed)] +#[derive(Clone, Debug, Eq, PartialEq, SerializeIndexed)] #[serde_indexed(offset = 1)] pub struct Response { pub fmt: String<32>, @@ -193,14 +197,15 @@ pub struct Response { pub att_stmt: AttestationStatement, } -#[derive(Clone,Debug, Eq,PartialEq,Serialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] #[serde(untagged)] +#[allow(clippy::large_enum_variant)] pub enum AttestationStatement { None(NoneAttestationStatement), Packed(PackedAttestationStatement), } -#[derive(Clone,Debug,Eq,PartialEq,Serialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] #[serde(untagged)] pub enum AttestationStatementFormat { None, @@ -211,10 +216,10 @@ pub enum AttestationStatementFormat { // FidoU2f, } -#[derive(Clone,Debug, Eq,PartialEq,Serialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct NoneAttestationStatement {} -#[derive(Clone,Debug, Eq,PartialEq,Serialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub struct PackedAttestationStatement { pub alg: i32, pub sig: Bytes, diff --git a/src/lib.rs b/src/lib.rs index 7a5b172..6d3282b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,9 +19,9 @@ extern crate delog; generate_macros!(); -pub use heapless::{String, Vec}; pub use heapless::spsc::{Consumer, Producer, Queue}; -pub use heapless_bytes::Bytes as Bytes; +pub use heapless::{String, Vec}; +pub use heapless_bytes::Bytes; pub type Bytes16 = Bytes<16>; pub type Bytes32 = Bytes<32>; @@ -37,5 +37,4 @@ pub mod sizes; pub mod webauthn; #[cfg(test)] -mod tests { -} +mod tests {} diff --git a/src/operation.rs b/src/operation.rs index f908edc..b83b8f6 100644 --- a/src/operation.rs +++ b/src/operation.rs @@ -1,7 +1,7 @@ use core::convert::TryFrom; /// the authenticator API, consisting of "operations" -#[derive(Copy,Clone,Debug, Eq,PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Operation { MakeCredential, GetAssertion, @@ -21,10 +21,10 @@ pub enum Operation { Vendor(VendorOperation), } -impl Into for Operation { - fn into(self) -> u8 { +impl From for u8 { + fn from(operation: Operation) -> u8 { use Operation::*; - match self { + match operation { MakeCredential => 0x01, GetAssertion => 0x02, GetNextAssertion => 0x08, @@ -50,7 +50,7 @@ impl Operation { } /// Vendor CTAP2 operations, from 0x40 to 0x7f. -#[derive(Copy,Clone,Debug, Eq,PartialEq)] +#[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct VendorOperation(u8); impl VendorOperation { @@ -70,9 +70,9 @@ impl TryFrom for VendorOperation { } } -impl Into for VendorOperation { - fn into(self) -> u8 { - self.0 +impl From for u8 { + fn from(operation: VendorOperation) -> u8 { + operation.0 } } @@ -95,10 +95,10 @@ impl TryFrom for Operation { 0x0D => Config, 0x40 => PreviewBioEnrollment, 0x41 => PreviewCredentialManagement, - code @ VendorOperation::FIRST..=VendorOperation::LAST - => Vendor(VendorOperation::try_from(code)?), + code @ VendorOperation::FIRST..=VendorOperation::LAST => { + Vendor(VendorOperation::try_from(code)?) + } _ => return Err(()), }) } } - diff --git a/src/rpc.rs b/src/rpc.rs index 1c9f9cc..c2fee6e 100644 --- a/src/rpc.rs +++ b/src/rpc.rs @@ -1,3 +1,4 @@ +#![allow(clippy::declare_interior_mutable_const)] use crate::authenticator::{Error, Request, Response}; // PRIOR ART: @@ -7,4 +8,3 @@ use crate::authenticator::{Error, Request, Response}; interchange::interchange! { CtapInterchange: (Request, Result) } - diff --git a/src/sizes.rs b/src/sizes.rs index 8a3cf94..c48b6e0 100644 --- a/src/sizes.rs +++ b/src/sizes.rs @@ -1,18 +1,18 @@ -pub const ATTESTED_CREDENTIAL_DATA_LENGTH: usize = 612; +pub const ATTESTED_CREDENTIAL_DATA_LENGTH: usize = 612; // // not sure why i can't use `::to_usize()` here? // pub const ATTESTED_CREDENTIAL_DATA_LENGTH_BYTES: usize = 512; -pub const AUTHENTICATOR_DATA_LENGTH: usize = 676; +pub const AUTHENTICATOR_DATA_LENGTH: usize = 676; // pub const AUTHENTICATOR_DATA_LENGTH_BYTES: usize = 512; -pub const ASN1_SIGNATURE_LENGTH: usize = 77; +pub const ASN1_SIGNATURE_LENGTH: usize = 77; // pub const ASN1_SIGNATURE_LENGTH_BYTES: usize = 72; pub const COSE_KEY_LENGTH: usize = 256; // pub const COSE_KEY_LENGTH_BYTES: usize = 256; -pub const MAX_CREDENTIAL_ID_LENGTH : usize = 512; -pub const MAX_CREDENTIAL_ID_LENGTH_PLUS_256 : usize = 768; +pub const MAX_CREDENTIAL_ID_LENGTH: usize = 512; +pub const MAX_CREDENTIAL_ID_LENGTH_PLUS_256: usize = 768; pub const MAX_CREDENTIAL_COUNT_IN_LIST: usize = 10; pub const PACKET_SIZE: usize = 64; diff --git a/src/webauthn.rs b/src/webauthn.rs index 68beb30..b88fda3 100644 --- a/src/webauthn.rs +++ b/src/webauthn.rs @@ -1,8 +1,8 @@ -use serde::{Deserialize, Serialize}; -use crate::{Bytes, String}; use crate::sizes::*; +use crate::{Bytes, String}; +use serde::{Deserialize, Serialize}; -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct PublicKeyCredentialRpEntity { pub id: String<256>, #[serde(skip_serializing_if = "Option::is_none")] @@ -11,11 +11,14 @@ pub struct PublicKeyCredentialRpEntity { pub url: Option>, } -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PublicKeyCredentialUserEntity { pub id: Bytes<64>, - #[serde(default, deserialize_with = "deserialize_from_str_and_skip_if_too_long")] + #[serde( + default, + deserialize_with = "deserialize_from_str_and_skip_if_too_long" + )] #[serde(skip_serializing_if = "Option::is_none")] pub icon: Option>, #[serde(skip_serializing_if = "Option::is_none")] @@ -24,15 +27,15 @@ pub struct PublicKeyCredentialUserEntity { pub display_name: Option>, } -fn deserialize_from_str_and_skip_if_too_long<'de, D, const L: usize>(deserializer: D) -> Result>, D::Error> +fn deserialize_from_str_and_skip_if_too_long<'de, D, const L: usize>( + deserializer: D, +) -> Result>, D::Error> where D: serde::Deserializer<'de>, { let result: Result, D::Error> = serde::Deserialize::deserialize(deserializer); match result { - Ok(string) => { - Ok(Some(string)) - }, + Ok(string) => Ok(Some(string)), Err(_err) => { info_now!("skipping field: {:?}", _err); Ok(None) @@ -40,14 +43,18 @@ where } } - impl PublicKeyCredentialUserEntity { pub fn from(id: Bytes<64>) -> Self { - Self { id, icon: None, name: None, display_name: None } + Self { + id, + icon: None, + name: None, + display_name: None, + } } } -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] pub struct PublicKeyCredentialParameters { pub alg: i32, #[serde(rename = "type")] @@ -56,11 +63,14 @@ pub struct PublicKeyCredentialParameters { impl PublicKeyCredentialParameters { pub fn public_key_with_alg(alg: i32) -> Self { - return Self { alg, key_type: String::from("public-key") } + Self { + alg, + key_type: String::from("public-key"), + } } } -#[derive(Clone,Debug, Eq,PartialEq,Serialize,Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PublicKeyCredentialDescriptor { // NB: if this is too small, get a nasty error diff --git a/tests/bennofs.rs b/tests/bennofs.rs index 138c28d..1034ff4 100644 --- a/tests/bennofs.rs +++ b/tests/bennofs.rs @@ -1,5 +1,5 @@ -use serde::{Serialize, Deserialize}; -use ctap_types::serde::{cbor_serialize, cbor_deserialize}; +use ctap_types::serde::{cbor_deserialize, cbor_serialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, PartialEq, Serialize, Deserialize)] struct Example { diff --git a/tests/get_assertion.rs b/tests/get_assertion.rs index 7183f35..8ba9d23 100644 --- a/tests/get_assertion.rs +++ b/tests/get_assertion.rs @@ -46,13 +46,11 @@ fn test_extensions_hmac_secret_input_key_agreement() { #[test] fn test_extensions_hmac_secret_salt_enc() { test::>( - b"X \xb9.\xb6\xaa\xdcS6;r'q\x93j\xb5~3\x1eN\xa1\xcc%\x0f\x8dVV\n\x87o\t\xc0\xb1\xcb" + b"X \xb9.\xb6\xaa\xdcS6;r'q\x93j\xb5~3\x1eN\xa1\xcc%\x0f\x8dVV\n\x87o\t\xc0\xb1\xcb", ); } #[test] fn test_extensions_hmac_secret_salt_auth() { - test::>( - b"PaU/RA\xb9\x1a\x935\x8d<\xfd8\xabXs" - ); + test::>(b"PaU/RA\xb9\x1a\x935\x8d<\xfd8\xabXs"); }