diff --git a/CHANGELOG.md b/CHANGELOG.md index dc575b4..4aaf040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Mark CTAP2 request and response types as non-exhaustive where possible - Use references where possible - Put uncommon fields in `get_info` behind `get-info-full` feature flag and add fields for CTAP 2.1 +- Use byte arrays instead of slices or Bytes<_> where possible [#8]: https://github.com/trussed-dev/ctap-types/pull/8 [#9]: https://github.com/solokeys/ctap-types/issues/9 diff --git a/src/ctap1.rs b/src/ctap1.rs index ede7de1..def7486 100644 --- a/src/ctap1.rs +++ b/src/ctap1.rs @@ -15,8 +15,8 @@ pub mod authenticate { #[derive(Clone, Debug, Eq, PartialEq)] pub struct Request<'a> { pub control_byte: ControlByte, - pub challenge: &'a [u8], - pub app_id: &'a [u8], + pub challenge: &'a [u8; 32], + pub app_id: &'a [u8; 32], pub key_handle: &'a [u8], } @@ -33,8 +33,8 @@ pub mod register { #[derive(Clone, Debug, Eq, PartialEq)] pub struct Request<'a> { - pub challenge: &'a [u8], - pub app_id: &'a [u8], + pub challenge: &'a [u8; 32], + pub app_id: &'a [u8; 32], } #[derive(Clone, Debug, Eq, PartialEq)] @@ -50,33 +50,20 @@ pub mod register { pub fn new( header_byte: u8, public_key: &cosey::EcdhEsHkdf256PublicKey, - key_handle: &[u8], + key_handle: Bytes<255>, signature: Bytes<72>, - attestation_certificate: &[u8], + attestation_certificate: Bytes<1024>, ) -> Self { - 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(); - let mut cert_bytes = Bytes::new(); - public_key_bytes.push(0x04).unwrap(); public_key_bytes.extend_from_slice(&public_key.x).unwrap(); public_key_bytes.extend_from_slice(&public_key.y).unwrap(); - key_handle_bytes.extend_from_slice(key_handle).unwrap(); - - cert_bytes - .extend_from_slice(attestation_certificate) - .unwrap(); - Self { header_byte, public_key: public_key_bytes, - key_handle: key_handle_bytes, - attestation_certificate: cert_bytes, + key_handle, + attestation_certificate, signature, } } @@ -196,8 +183,8 @@ impl<'a, const S: usize> TryFrom<&'a iso7816::Command> for Request<'a> { return Err(Error::IncorrectDataParameter); } Ok(Request::Register(Register { - challenge: &request[..32], - app_id: &request[32..], + challenge: (&request[..32]).try_into().unwrap(), + app_id: (&request[32..]).try_into().unwrap(), })) } @@ -213,8 +200,8 @@ impl<'a, const S: usize> TryFrom<&'a iso7816::Command> for Request<'a> { } Ok(Request::Authenticate(Authenticate { control_byte, - challenge: &request[..32], - app_id: &request[32..64], + challenge: (&request[..32]).try_into().unwrap(), + app_id: (&request[32..64]).try_into().unwrap(), key_handle: &request[65..], })) } diff --git a/src/ctap2.rs b/src/ctap2.rs index 8c9c4dd..54e3c12 100644 --- a/src/ctap2.rs +++ b/src/ctap2.rs @@ -206,7 +206,7 @@ pub trait SerializeAttestedCredentialData { #[derive(Clone, Debug, Eq, PartialEq)] pub struct AuthenticatorData<'a, A, E> { - pub rp_id_hash: &'a [u8], + pub rp_id_hash: &'a [u8; 32], pub flags: AuthenticatorDataFlags, pub sign_count: u32, pub attested_credential_data: Option, diff --git a/src/ctap2/credential_management.rs b/src/ctap2/credential_management.rs index 08cc767..8241b78 100644 --- a/src/ctap2/credential_management.rs +++ b/src/ctap2/credential_management.rs @@ -1,17 +1,13 @@ use cosey::PublicKey; +use serde_bytes::ByteArray; use serde_indexed::{DeserializeIndexed, SerializeIndexed}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::{ - webauthn::{ - PublicKeyCredentialDescriptor, PublicKeyCredentialDescriptorRef, - PublicKeyCredentialRpEntity, PublicKeyCredentialUserEntity, - }, - Bytes, +use crate::webauthn::{ + PublicKeyCredentialDescriptor, PublicKeyCredentialDescriptorRef, PublicKeyCredentialRpEntity, + PublicKeyCredentialUserEntity, }; -type Bytes32 = Bytes<32>; - #[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Serialize_repr, Deserialize_repr)] #[repr(u8)] pub enum CredentialProtectionPolicy { @@ -40,7 +36,7 @@ pub enum Subcommand { pub struct SubcommandParameters<'a> { // 0x01 #[serde(skip_serializing_if = "Option::is_none")] - pub rp_id_hash: Option<&'a serde_bytes::Bytes>, + pub rp_id_hash: Option<&'a serde_bytes::ByteArray<32>>, // 0x02 #[serde(skip_serializing_if = "Option::is_none")] pub credential_id: Option>, @@ -86,7 +82,7 @@ pub struct Response { pub rp: Option, // 0x04 #[serde(skip_serializing_if = "Option::is_none")] - pub rp_id_hash: Option, + pub rp_id_hash: Option>, // 0x05 #[serde(skip_serializing_if = "Option::is_none")] pub total_rps: Option, @@ -110,5 +106,5 @@ pub struct Response { pub cred_protect: Option, // 0x0B #[serde(skip_serializing_if = "Option::is_none")] - pub large_blob_key: Option>, + pub large_blob_key: Option>, } diff --git a/src/ctap2/get_assertion.rs b/src/ctap2/get_assertion.rs index 5609861..213bb58 100644 --- a/src/ctap2/get_assertion.rs +++ b/src/ctap2/get_assertion.rs @@ -1,6 +1,7 @@ use crate::{Bytes, Vec}; use cosey::EcdhEsHkdf256PublicKey; use serde::{Deserialize, Serialize}; +use serde_bytes::ByteArray; use serde_indexed::{DeserializeIndexed, SerializeIndexed}; use super::{AuthenticatorOptions, Result}; @@ -90,7 +91,7 @@ pub struct Response { /// A key that can be used to encrypt and decrypt large blob data. /// See https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-getAssert-authnr-alg #[serde(skip_serializing_if = "Option::is_none")] - pub large_blob_key: Option>, + pub large_blob_key: Option>, } #[derive(Debug)] diff --git a/src/ctap2/make_credential.rs b/src/ctap2/make_credential.rs index 1f9e2f1..a3d03ae 100644 --- a/src/ctap2/make_credential.rs +++ b/src/ctap2/make_credential.rs @@ -1,6 +1,7 @@ use crate::{Bytes, String, Vec}; use serde::{Deserialize, Serialize}; +use serde_bytes::ByteArray; use serde_indexed::{DeserializeIndexed, SerializeIndexed}; use super::{AuthenticatorOptions, Error}; @@ -108,7 +109,7 @@ pub struct Response { #[serde(skip_serializing_if = "Option::is_none")] pub ep_att: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub large_blob_key: Option>, + pub large_blob_key: Option>, } #[derive(Debug)] diff --git a/src/lib.rs b/src/lib.rs index 13f91f2..6763da2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ pub use heapless; pub use heapless::{String, Vec}; pub use heapless_bytes; pub use heapless_bytes::Bytes; +pub use serde_bytes::ByteArray; pub mod authenticator; pub mod ctap1;