From 98a558a5021b8bfb249e55e1466548ca7c6a2691 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Sat, 30 May 2020 20:15:59 +0200 Subject: [PATCH 01/24] Access the persistent keys through the store This permits to set them using a vendor command and thus not embed their value in the application. --- src/ctap/mod.rs | 18 +++---- src/ctap/status_code.rs | 6 +++ src/ctap/storage.rs | 113 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 11 deletions(-) diff --git a/src/ctap/mod.rs b/src/ctap/mod.rs index a39a983..758f94a 100644 --- a/src/ctap/mod.rs +++ b/src/ctap/mod.rs @@ -37,7 +37,6 @@ use self::data_formats::{ PublicKeyCredentialType, PublicKeyCredentialUserEntity, SignatureAlgorithm, }; use self::hid::ChannelID; -use self::key_material::{AAGUID, ATTESTATION_CERTIFICATE, ATTESTATION_PRIVATE_KEY}; use self::response::{ AuthenticatorClientPinResponse, AuthenticatorGetAssertionResponse, AuthenticatorGetInfoResponse, AuthenticatorMakeCredentialResponse, ResponseData, @@ -509,7 +508,7 @@ where }; let mut auth_data = self.generate_auth_data(&rp_id_hash, flags); - auth_data.extend(AAGUID); + auth_data.extend(self.persistent_store.aaguid()?); // The length is fixed to 0x20 or 0x70 and fits one byte. if credential_id.len() > 0xFF { return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG); @@ -534,10 +533,11 @@ where signature_data.extend(client_data_hash); let (signature, x5c) = if USE_BATCH_ATTESTATION { let attestation_key = - crypto::ecdsa::SecKey::from_bytes(ATTESTATION_PRIVATE_KEY).unwrap(); + crypto::ecdsa::SecKey::from_bytes(self.persistent_store.attestation_private_key()?) + .unwrap(); ( attestation_key.sign_rfc6979::(&signature_data), - Some(vec![ATTESTATION_CERTIFICATE.to_vec()]), + Some(vec![self.persistent_store.attestation_certificate()?]), ) } else { ( @@ -769,7 +769,7 @@ where String::from(FIDO2_VERSION_STRING), ], extensions: Some(vec![String::from("hmac-secret")]), - aaguid: *AAGUID, + aaguid: *self.persistent_store.aaguid()?, options: Some(options_map), max_msg_size: Some(1024), pin_protocols: Some(vec![ @@ -1124,7 +1124,7 @@ mod test { 0x02, 0x81, 0x6B, 0x68, 0x6D, 0x61, 0x63, 0x2D, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x03, 0x50, ]); - expected_response.extend(AAGUID); + expected_response.extend(ctap_state.persistent_store.aaguid().unwrap()); expected_response.extend(&[ 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, @@ -1197,7 +1197,7 @@ mod test { 0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2, 0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00, ]; - expected_auth_data.extend(AAGUID); + expected_auth_data.extend(ctap_state.persistent_store.aaguid().unwrap()); expected_auth_data.extend(&[0x00, 0x20]); assert_eq!( auth_data[0..expected_auth_data.len()], @@ -1234,7 +1234,7 @@ mod test { 0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2, 0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0x41, 0x00, 0x00, 0x00, 0x00, ]; - expected_auth_data.extend(AAGUID); + expected_auth_data.extend(ctap_state.persistent_store.aaguid().unwrap()); expected_auth_data.extend(&[0x00, ENCRYPTED_CREDENTIAL_ID_SIZE as u8]); assert_eq!( auth_data[0..expected_auth_data.len()], @@ -1330,7 +1330,7 @@ mod test { 0x34, 0xE2, 0x75, 0x1E, 0x68, 0x2F, 0xAB, 0x9F, 0x2D, 0x30, 0xAB, 0x13, 0xD2, 0x12, 0x55, 0x86, 0xCE, 0x19, 0x47, 0xC1, 0x00, 0x00, 0x00, 0x00, ]; - expected_auth_data.extend(AAGUID); + expected_auth_data.extend(ctap_state.persistent_store.aaguid().unwrap()); expected_auth_data.extend(&[0x00, 0x20]); assert_eq!( auth_data[0..expected_auth_data.len()], diff --git a/src/ctap/status_code.rs b/src/ctap/status_code.rs index 1e0c2bf..b58b8d0 100644 --- a/src/ctap/status_code.rs +++ b/src/ctap/status_code.rs @@ -67,5 +67,11 @@ pub enum Ctap2StatusCode { // CTAP2_ERR_VENDOR_FIRST = 0xF0, CTAP2_ERR_VENDOR_RESPONSE_TOO_LONG = 0xF0, CTAP2_ERR_VENDOR_RESPONSE_CANNOT_WRITE_CBOR = 0xF1, + + /// An internal invariant is broken. + /// + /// This type of error is unexpected and the current state is undefined. + CTAP2_ERR_VENDOR_INTERNAL_ERROR = 0xF2, + CTAP2_ERR_VENDOR_LAST = 0xFF, } diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index f0a2ca4..b8cfa37 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -14,6 +14,7 @@ use crate::crypto::rng256::Rng256; use crate::ctap::data_formats::PublicKeyCredentialSource; +use crate::ctap::key_material; use crate::ctap::status_code::Ctap2StatusCode; use crate::ctap::PIN_AUTH_LENGTH; use alloc::string::String; @@ -56,9 +57,14 @@ const GLOBAL_SIGNATURE_COUNTER: usize = 1; const MASTER_KEYS: usize = 2; const PIN_HASH: usize = 3; const PIN_RETRIES: usize = 4; -const NUM_TAGS: usize = 5; +const ATTESTATION_PRIVATE_KEY: usize = 5; +const ATTESTATION_CERTIFICATE: usize = 6; +const AAGUID: usize = 7; +const NUM_TAGS: usize = 8; const MAX_PIN_RETRIES: u8 = 6; +const ATTESTATION_PRIVATE_KEY_LENGTH: usize = 32; +const AAGUID_LENGTH: usize = 16; #[derive(PartialEq, Eq, PartialOrd, Ord)] enum Key { @@ -73,6 +79,9 @@ enum Key { MasterKeys, PinHash, PinRetries, + AttestationPrivateKey, + AttestationCertificate, + Aaguid, } pub struct MasterKeys<'a> { @@ -124,6 +133,9 @@ impl StoreConfig for Config { MASTER_KEYS => add(Key::MasterKeys), PIN_HASH => add(Key::PinHash), PIN_RETRIES => add(Key::PinRetries), + ATTESTATION_PRIVATE_KEY => add(Key::AttestationPrivateKey), + ATTESTATION_CERTIFICATE => add(Key::AttestationCertificate), + AAGUID => add(Key::Aaguid), _ => debug_assert!(false), } } @@ -211,6 +223,33 @@ impl PersistentStore { }) .unwrap(); } + if self.store.find_one(&Key::AttestationPrivateKey).is_none() { + self.store + .insert(StoreEntry { + tag: ATTESTATION_PRIVATE_KEY, + data: key_material::ATTESTATION_PRIVATE_KEY, + sensitive: false, + }) + .unwrap(); + } + if self.store.find_one(&Key::AttestationCertificate).is_none() { + self.store + .insert(StoreEntry { + tag: ATTESTATION_CERTIFICATE, + data: key_material::ATTESTATION_CERTIFICATE, + sensitive: false, + }) + .unwrap(); + } + if self.store.find_one(&Key::Aaguid).is_none() { + self.store + .insert(StoreEntry { + tag: AAGUID, + data: key_material::AAGUID, + sensitive: false, + }) + .unwrap(); + } } pub fn find_credential( @@ -394,10 +433,44 @@ impl PersistentStore { .unwrap(); } + pub fn attestation_private_key( + &self, + ) -> Result<&[u8; ATTESTATION_PRIVATE_KEY_LENGTH], Ctap2StatusCode> { + let (_, entry) = self + .store + .find_one(&Key::AttestationPrivateKey) + .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?; + let data = entry.data; + if data.len() != ATTESTATION_PRIVATE_KEY_LENGTH { + return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR); + } + Ok(array_ref!(data, 0, ATTESTATION_PRIVATE_KEY_LENGTH)) + } + + pub fn attestation_certificate(&self) -> Result, Ctap2StatusCode> { + let (_, entry) = self + .store + .find_one(&Key::AttestationCertificate) + .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?; + Ok(entry.data.to_vec()) + } + + pub fn aaguid(&self) -> Result<&[u8; AAGUID_LENGTH], Ctap2StatusCode> { + let (_, entry) = self + .store + .find_one(&Key::Aaguid) + .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?; + let data = entry.data; + if data.len() != AAGUID_LENGTH { + return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR); + } + Ok(array_ref!(data, 0, AAGUID_LENGTH)) + } + pub fn reset(&mut self, rng: &mut impl Rng256) { loop { let index = { - let mut iter = self.store.iter(); + let mut iter = self.store.iter().filter(|(_, entry)| should_reset(entry)); match iter.next() { None => break, Some((index, _)) => index, @@ -419,6 +492,13 @@ impl From for Ctap2StatusCode { } } +fn should_reset<'a>(entry: &StoreEntry<'a>) -> bool { + match entry.tag { + ATTESTATION_PRIVATE_KEY | ATTESTATION_CERTIFICATE | AAGUID => false, + _ => true, + } +} + fn deserialize_credential(data: &[u8]) -> Option { let cbor = cbor::read(data).ok()?; cbor.try_into().ok() @@ -696,4 +776,33 @@ mod test { persistent_store.reset_pin_retries(); assert_eq!(persistent_store.pin_retries(), MAX_PIN_RETRIES); } + + #[test] + fn test_persistent_keys() { + let mut rng = ThreadRng256 {}; + let mut persistent_store = PersistentStore::new(&mut rng); + + // The persistent keys are initialized on a fresh store. + assert_eq!( + persistent_store.attestation_private_key().unwrap(), + key_material::ATTESTATION_PRIVATE_KEY + ); + assert_eq!( + persistent_store.attestation_certificate().unwrap(), + key_material::ATTESTATION_CERTIFICATE + ); + assert_eq!(persistent_store.aaguid().unwrap(), key_material::AAGUID); + + // The persistent keys stay initialized and preserve their value after a reset. + persistent_store.reset(&mut rng); + assert_eq!( + persistent_store.attestation_private_key().unwrap(), + key_material::ATTESTATION_PRIVATE_KEY + ); + assert_eq!( + persistent_store.attestation_certificate().unwrap(), + key_material::ATTESTATION_CERTIFICATE + ); + assert_eq!(persistent_store.aaguid().unwrap(), key_material::AAGUID); + } } From a195cfec02ed9fcf237a4e92827543f52bcefbdc Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Sat, 30 May 2020 20:29:50 +0200 Subject: [PATCH 02/24] Update reproducible hashes --- reproducible/reference_binaries_macos-10.15.sha256sum | 10 +++++----- reproducible/reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index cf4fea0..f299ed1 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ b113945b033eb229e3821542f5889769e5fd2e2ae3cb85c6d13a4e05a44a9866 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -13d923f9efad028c9fa5d14920f940ad0108b290088a84ca82f08a3e09a4e569 target/nrf52840dk_merged.hex +89a36f326b7e2db764315f976c8a26644ab3fd11fd03ca5edfc308c833fe7576 target/nrf52840dk_merged.hex 346016903ddf244a239162b7c703aafe7ec70a115175e2204892e874f930f6be third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -f1f0de2e54c0dc88fd503271322a985f9c769fc26a72e651f84b834cd623c09c target/nrf52840_dongle_merged.hex +a146c240423bb72ccd1046b90dbc52ef23bd1b14996f54754b64af849590c487 target/nrf52840_dongle_merged.hex adcc4caaea86f7b0d54111d3080802e7389a4e69a8f17945d026ee732ea8daa4 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -d080c9267370b4a69e64e6098391cded7d3532feaa123c6331b12608aacd0112 target/nrf52840_dongle_dfu_merged.hex +d8ed0d7f3bfce18ebe512c7a7d884de8e006508611e7f8055a9beff38e50287b target/nrf52840_dongle_dfu_merged.hex 97a7dbdb7c3caa345307d5ff7f7607dad5c2cdc523b43c68d3b741ddce318e92 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -5bdcfa69ff5e86cd8175e0d78912e54e803c284502e035416333a8da2eaa1616 target/nrf52840_mdk_dfu_merged.hex -c68c723d21264b54a7167d999ad18294d10b05d48412595ccbe596865e166e5d target/tab/ctap2.tab +aca4e384a86b81cd9c1f35bc8201957c4a3e5733411d54bda59cb9086d002d79 target/nrf52840_mdk_dfu_merged.hex +7a8811f32efcd4ce81a586837dd44edfe770dbb2980fd1d73ac6b2d579850cec target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index 8e87cac..82dd546 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ 921d6fc31f7235456dd41abc7e634a37ee87b5016b80c979d20ac5d3fcfc6b6b third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -e8e6b802722bf41eb5054ec94e87332fa996e954aad7d02db09beb798d7e381c target/nrf52840dk_merged.hex +35017137a06dc2e65e13037b3ac269252eafea13e6790976ea31fa1b36870651 target/nrf52840dk_merged.hex aab5bdc406b1e874b83872c9358d310070b3ce948ec0e20c054fb923ec879249 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -aab3193acc08bc38c4219968da5e9d99f6f73b78fe91d74e8cbc3b94166c7dd3 target/nrf52840_dongle_merged.hex +f0ff3e88c0935f832084e0c39cc65fe2278336424c9e970d42b5f5f270838b3a target/nrf52840_dongle_merged.hex 26b8513e76058e86a01a4b408411ce429834eb2843993eb1671f2487b160bc9a third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -99a71cc0622f7cc0abdce686ff6581ec8b9fee6075b7cd771a68c08717e4198f target/nrf52840_dongle_dfu_merged.hex +a8374b73fbcd7f807831f0ca558d64e93d5670e51d570dcf8da22c7db9c914fe target/nrf52840_dongle_dfu_merged.hex 7cc558a66505e8cf8170aab50e6ddcb28f349fd7ced35ce841ccec33a533bea1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -810f3ef6353177742bba06618bdc865efd819e97cbed605769f12f9d66831671 target/nrf52840_mdk_dfu_merged.hex -54e05927ab650c2ccf10cde165e992e48869888609cc6e8b4429a5c7a420f145 target/tab/ctap2.tab +395dea574ef660102a80446c8d1b0d56c76f9a0e0f75327547b54595676cfaf4 target/nrf52840_mdk_dfu_merged.hex +35cbaa5af951807a0f9a73e11e3604565cf5a015925fba41009dcfa092358d64 target/tab/ctap2.tab From 5f8cb116a5f50dca899c3e2e200c9b3d07b96961 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Tue, 2 Jun 2020 11:00:26 +0200 Subject: [PATCH 03/24] Only write attestation if compiled with batch attestation --- src/ctap/mod.rs | 28 +++++++++++-------- src/ctap/storage.rs | 65 +++++++++++++++++++++++---------------------- 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/src/ctap/mod.rs b/src/ctap/mod.rs index 758f94a..bd1db51 100644 --- a/src/ctap/mod.rs +++ b/src/ctap/mod.rs @@ -531,19 +531,25 @@ where let mut signature_data = auth_data.clone(); signature_data.extend(client_data_hash); - let (signature, x5c) = if USE_BATCH_ATTESTATION { - let attestation_key = - crypto::ecdsa::SecKey::from_bytes(self.persistent_store.attestation_private_key()?) - .unwrap(); - ( - attestation_key.sign_rfc6979::(&signature_data), - Some(vec![self.persistent_store.attestation_certificate()?]), - ) - } else { - ( + // We currently use the presence of the attestation private key in the persistent storage to + // decide whether batch attestation is needed. + let (signature, x5c) = match self.persistent_store.attestation_private_key()? { + Some(attestation_private_key) => { + let attestation_key = + crypto::ecdsa::SecKey::from_bytes(attestation_private_key).unwrap(); + let attestation_certificate = self + .persistent_store + .attestation_certificate()? + .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?; + ( + attestation_key.sign_rfc6979::(&signature_data), + Some(vec![attestation_certificate]), + ) + } + None => ( sk.sign_rfc6979::(&signature_data), None, - ) + ), }; let attestation_statement = PackedAttestationStatement { alg: SignatureAlgorithm::ES256 as i64, diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index b8cfa37..e3fef55 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -14,9 +14,8 @@ use crate::crypto::rng256::Rng256; use crate::ctap::data_formats::PublicKeyCredentialSource; -use crate::ctap::key_material; use crate::ctap::status_code::Ctap2StatusCode; -use crate::ctap::PIN_AUTH_LENGTH; +use crate::ctap::{key_material, PIN_AUTH_LENGTH, USE_BATCH_ATTESTATION}; use alloc::string::String; use alloc::vec::Vec; use core::convert::TryInto; @@ -223,23 +222,26 @@ impl PersistentStore { }) .unwrap(); } - if self.store.find_one(&Key::AttestationPrivateKey).is_none() { - self.store - .insert(StoreEntry { - tag: ATTESTATION_PRIVATE_KEY, - data: key_material::ATTESTATION_PRIVATE_KEY, - sensitive: false, - }) - .unwrap(); - } - if self.store.find_one(&Key::AttestationCertificate).is_none() { - self.store - .insert(StoreEntry { - tag: ATTESTATION_CERTIFICATE, - data: key_material::ATTESTATION_CERTIFICATE, - sensitive: false, - }) - .unwrap(); + // The following 3 entries are meant to be written by vendor-specific commands. + if USE_BATCH_ATTESTATION { + if self.store.find_one(&Key::AttestationPrivateKey).is_none() { + self.store + .insert(StoreEntry { + tag: ATTESTATION_PRIVATE_KEY, + data: key_material::ATTESTATION_PRIVATE_KEY, + sensitive: false, + }) + .unwrap(); + } + if self.store.find_one(&Key::AttestationCertificate).is_none() { + self.store + .insert(StoreEntry { + tag: ATTESTATION_CERTIFICATE, + data: key_material::ATTESTATION_CERTIFICATE, + sensitive: false, + }) + .unwrap(); + } } if self.store.find_one(&Key::Aaguid).is_none() { self.store @@ -435,24 +437,23 @@ impl PersistentStore { pub fn attestation_private_key( &self, - ) -> Result<&[u8; ATTESTATION_PRIVATE_KEY_LENGTH], Ctap2StatusCode> { - let (_, entry) = self - .store - .find_one(&Key::AttestationPrivateKey) - .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?; - let data = entry.data; + ) -> Result, Ctap2StatusCode> { + let data = match self.store.find_one(&Key::AttestationPrivateKey) { + None => return Ok(None), + Some((_, entry)) => entry.data, + }; if data.len() != ATTESTATION_PRIVATE_KEY_LENGTH { return Err(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR); } - Ok(array_ref!(data, 0, ATTESTATION_PRIVATE_KEY_LENGTH)) + Ok(Some(array_ref!(data, 0, ATTESTATION_PRIVATE_KEY_LENGTH))) } - pub fn attestation_certificate(&self) -> Result, Ctap2StatusCode> { - let (_, entry) = self - .store - .find_one(&Key::AttestationCertificate) - .ok_or(Ctap2StatusCode::CTAP2_ERR_VENDOR_INTERNAL_ERROR)?; - Ok(entry.data.to_vec()) + pub fn attestation_certificate(&self) -> Result>, Ctap2StatusCode> { + let data = match self.store.find_one(&Key::AttestationCertificate) { + None => return Ok(None), + Some((_, entry)) => entry.data, + }; + Ok(Some(data.to_vec())) } pub fn aaguid(&self) -> Result<&[u8; AAGUID_LENGTH], Ctap2StatusCode> { From d74a5e8894e8b43c41ad597cf2532e7f727b344c Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Tue, 2 Jun 2020 11:35:17 +0200 Subject: [PATCH 04/24] Add setter functions and fix tests --- src/ctap/storage.rs | 97 +++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index e3fef55..f4a2786 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -225,32 +225,16 @@ impl PersistentStore { // The following 3 entries are meant to be written by vendor-specific commands. if USE_BATCH_ATTESTATION { if self.store.find_one(&Key::AttestationPrivateKey).is_none() { - self.store - .insert(StoreEntry { - tag: ATTESTATION_PRIVATE_KEY, - data: key_material::ATTESTATION_PRIVATE_KEY, - sensitive: false, - }) + self.set_attestation_private_key(key_material::ATTESTATION_PRIVATE_KEY) .unwrap(); } if self.store.find_one(&Key::AttestationCertificate).is_none() { - self.store - .insert(StoreEntry { - tag: ATTESTATION_CERTIFICATE, - data: key_material::ATTESTATION_CERTIFICATE, - sensitive: false, - }) + self.set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE) .unwrap(); } } if self.store.find_one(&Key::Aaguid).is_none() { - self.store - .insert(StoreEntry { - tag: AAGUID, - data: key_material::AAGUID, - sensitive: false, - }) - .unwrap(); + self.set_aaguid(key_material::AAGUID).unwrap(); } } @@ -448,6 +432,22 @@ impl PersistentStore { Ok(Some(array_ref!(data, 0, ATTESTATION_PRIVATE_KEY_LENGTH))) } + pub fn set_attestation_private_key( + &mut self, + attestation_private_key: &[u8; ATTESTATION_PRIVATE_KEY_LENGTH], + ) -> Result<(), Ctap2StatusCode> { + let entry = StoreEntry { + tag: ATTESTATION_PRIVATE_KEY, + data: attestation_private_key, + sensitive: false, + }; + match self.store.find_one(&Key::AttestationPrivateKey) { + None => self.store.insert(entry)?, + Some((index, _)) => self.store.replace(index, entry)?, + } + Ok(()) + } + pub fn attestation_certificate(&self) -> Result>, Ctap2StatusCode> { let data = match self.store.find_one(&Key::AttestationCertificate) { None => return Ok(None), @@ -456,6 +456,22 @@ impl PersistentStore { Ok(Some(data.to_vec())) } + pub fn set_attestation_certificate( + &mut self, + attestation_certificate: &[u8], + ) -> Result<(), Ctap2StatusCode> { + let entry = StoreEntry { + tag: ATTESTATION_CERTIFICATE, + data: attestation_certificate, + sensitive: false, + }; + match self.store.find_one(&Key::AttestationCertificate) { + None => self.store.insert(entry)?, + Some((index, _)) => self.store.replace(index, entry)?, + } + Ok(()) + } + pub fn aaguid(&self) -> Result<&[u8; AAGUID_LENGTH], Ctap2StatusCode> { let (_, entry) = self .store @@ -468,6 +484,19 @@ impl PersistentStore { Ok(array_ref!(data, 0, AAGUID_LENGTH)) } + pub fn set_aaguid(&mut self, aaguid: &[u8; AAGUID_LENGTH]) -> Result<(), Ctap2StatusCode> { + let entry = StoreEntry { + tag: AAGUID, + data: aaguid, + sensitive: false, + }; + match self.store.find_one(&Key::Aaguid) { + None => self.store.insert(entry)?, + Some((index, _)) => self.store.replace(index, entry)?, + } + Ok(()) + } + pub fn reset(&mut self, rng: &mut impl Rng256) { loop { let index = { @@ -783,25 +812,33 @@ mod test { let mut rng = ThreadRng256 {}; let mut persistent_store = PersistentStore::new(&mut rng); - // The persistent keys are initialized on a fresh store. - assert_eq!( - persistent_store.attestation_private_key().unwrap(), - key_material::ATTESTATION_PRIVATE_KEY - ); - assert_eq!( - persistent_store.attestation_certificate().unwrap(), - key_material::ATTESTATION_CERTIFICATE - ); + // Make sure the attestation are absent. There is no batch attestation in tests. + assert!(persistent_store + .attestation_private_key() + .unwrap() + .is_none()); + assert!(persistent_store + .attestation_certificate() + .unwrap() + .is_none()); + + // Make sure the persistent keys are initialized. + persistent_store + .set_attestation_private_key(key_material::ATTESTATION_PRIVATE_KEY) + .unwrap(); + persistent_store + .set_attestation_certificate(key_material::ATTESTATION_CERTIFICATE) + .unwrap(); assert_eq!(persistent_store.aaguid().unwrap(), key_material::AAGUID); // The persistent keys stay initialized and preserve their value after a reset. persistent_store.reset(&mut rng); assert_eq!( - persistent_store.attestation_private_key().unwrap(), + persistent_store.attestation_private_key().unwrap().unwrap(), key_material::ATTESTATION_PRIVATE_KEY ); assert_eq!( - persistent_store.attestation_certificate().unwrap(), + persistent_store.attestation_certificate().unwrap().unwrap(), key_material::ATTESTATION_CERTIFICATE ); assert_eq!(persistent_store.aaguid().unwrap(), key_material::AAGUID); From 7ba4a21632371a8a0c503f4dae5bf86b7f64052d Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Tue, 2 Jun 2020 11:47:48 +0200 Subject: [PATCH 05/24] Update reproducible hashes --- reproducible/reference_binaries_macos-10.15.sha256sum | 10 +++++----- reproducible/reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index f299ed1..ca790b0 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ b113945b033eb229e3821542f5889769e5fd2e2ae3cb85c6d13a4e05a44a9866 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -89a36f326b7e2db764315f976c8a26644ab3fd11fd03ca5edfc308c833fe7576 target/nrf52840dk_merged.hex +53df92ff658b43fd56f53a7ddf67dd8e63dd9401ba840ea86f9805a23e1ee29b target/nrf52840dk_merged.hex 346016903ddf244a239162b7c703aafe7ec70a115175e2204892e874f930f6be third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -a146c240423bb72ccd1046b90dbc52ef23bd1b14996f54754b64af849590c487 target/nrf52840_dongle_merged.hex +e366d9aeff8aa202be78490932b03b5d87188ec38c674f5891d38f58f7e9b83a target/nrf52840_dongle_merged.hex adcc4caaea86f7b0d54111d3080802e7389a4e69a8f17945d026ee732ea8daa4 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -d8ed0d7f3bfce18ebe512c7a7d884de8e006508611e7f8055a9beff38e50287b target/nrf52840_dongle_dfu_merged.hex +6bd5cfd1069eef2a2bc9f37add964b3e43e4e7e13bad7925612811ea8bc1f7ca target/nrf52840_dongle_dfu_merged.hex 97a7dbdb7c3caa345307d5ff7f7607dad5c2cdc523b43c68d3b741ddce318e92 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -aca4e384a86b81cd9c1f35bc8201957c4a3e5733411d54bda59cb9086d002d79 target/nrf52840_mdk_dfu_merged.hex -7a8811f32efcd4ce81a586837dd44edfe770dbb2980fd1d73ac6b2d579850cec target/tab/ctap2.tab +1a03451ad6cf068b3426f6f62d9dc9cc9fd0a511869e145c00badc325f010c1c target/nrf52840_mdk_dfu_merged.hex +c3d596f942135d6d2919f4641ad761f464b7f6a119fbd2a914314244cfd92bbf target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index 82dd546..1242d5b 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ 921d6fc31f7235456dd41abc7e634a37ee87b5016b80c979d20ac5d3fcfc6b6b third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -35017137a06dc2e65e13037b3ac269252eafea13e6790976ea31fa1b36870651 target/nrf52840dk_merged.hex +ba37efda1b1b20cb248a7465fca0b2a3c37a892320b35245d87946f4360026ef target/nrf52840dk_merged.hex aab5bdc406b1e874b83872c9358d310070b3ce948ec0e20c054fb923ec879249 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -f0ff3e88c0935f832084e0c39cc65fe2278336424c9e970d42b5f5f270838b3a target/nrf52840_dongle_merged.hex +449273c24167ecc17a264dd3d5be30a81d434846bbf762249ddec1539da9d07f target/nrf52840_dongle_merged.hex 26b8513e76058e86a01a4b408411ce429834eb2843993eb1671f2487b160bc9a third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -a8374b73fbcd7f807831f0ca558d64e93d5670e51d570dcf8da22c7db9c914fe target/nrf52840_dongle_dfu_merged.hex +14a71aaac9ec8940bafcaaa162075ee1d9cc1b5c0406692a496205a8ac987f79 target/nrf52840_dongle_dfu_merged.hex 7cc558a66505e8cf8170aab50e6ddcb28f349fd7ced35ce841ccec33a533bea1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -395dea574ef660102a80446c8d1b0d56c76f9a0e0f75327547b54595676cfaf4 target/nrf52840_mdk_dfu_merged.hex -35cbaa5af951807a0f9a73e11e3604565cf5a015925fba41009dcfa092358d64 target/tab/ctap2.tab +f30a0cad73d9fc664324585f07cecb40981d67413d9ebeef1e97334afb0363f3 target/nrf52840_mdk_dfu_merged.hex +d75a1f5468a4b838efa7602607f5178e042ad41891c53a230dc91a7b464018de target/tab/ctap2.tab From 3d2de2b02a0abdee6226880dd2726bfd1c294c92 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Wed, 3 Jun 2020 11:45:05 +0200 Subject: [PATCH 06/24] Update reproducible hashes --- reproducible/reference_binaries_macos-10.15.sha256sum | 10 +++++----- reproducible/reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index 98b20af..3b0dabe 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ 1003863864e06553e730eec6df4bf8d30c99f697ef9380efdc35eba679b4db78 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -84d97929d7592d89c7f321ffccafa4148263607e28918e53d9286be8ca55c209 target/nrf52840dk_merged.hex +7ffc52ea6bfd1c3fde3398da4e894b5659770a74b466e052b4c3999436f9d78e target/nrf52840dk_merged.hex 88f00a5e1dae6ab3f7571c254ac75f5f3e29ebea7f3ca46c16cfdc3708e804fc third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -02009688b6ef8583f78f9b94ba8af65dfa3749b20516972cdb0d8ea7ac409268 target/nrf52840_dongle_merged.hex +a0cd9144582b616a51d4f097713cbd697d418c19d031906f58fc630d7286ed85 target/nrf52840_dongle_merged.hex 1bc69b48a2c48da55db8b322902e1fe3f2e095c0dd8517db28837d86e0addc85 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -a24e7459b93eea1fc7557ecd9e4271a2ed729425990d6198be6791f364b1384b target/nrf52840_dongle_dfu_merged.hex +5879d90971a7429e8890ce4a5db694499f391ffd7c6707c6820538ee8126ff5f target/nrf52840_dongle_dfu_merged.hex f38ee31d3a09e7e11848e78b5318f95517b6dcd076afcb37e6e3d3e5e9995cc7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -5315b77b997952de10e239289e54b44c24105646f2411074332bb46f4b686ae6 target/nrf52840_mdk_dfu_merged.hex -9012744b93f8bac122fa18916cf8c22d1b8f729a284366802ed222bbc985e3f0 target/tab/ctap2.tab +a4e7451174ee75a27acfb9bdd3c977f5cf3e756e40219b706c97eab3a21c7ac0 target/nrf52840_mdk_dfu_merged.hex +f364a923a4c56b5bbba8b590c8c296b29f4448f3117cedf433d4752867fac6ef target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index 3171ce7..c597106 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ c182bb4902fff51b2f56810fc2a27df3646cd66ba21359162354d53445623ab8 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -805ca30b898b41a091cc136ab9b78b4e566e10c5469902d18c326c132ed4193e target/nrf52840dk_merged.hex +9624888f52510e1e7a13681a959ecb9dd0e325b3856422b48d28abadc6546211 target/nrf52840dk_merged.hex 0a9929ba8fa57e8a502a49fc7c53177397202e1b11f4c7c3cb6ed68b2b99dd46 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -960dce1eb78f34a3c4cfdb543314da8ce211dced41f34da053669c8773926e1d target/nrf52840_dongle_merged.hex +31b41cc1010c621765a4385ecd678950ddb2e1eaa11e0efaa9df818a1abfd022 target/nrf52840_dongle_merged.hex cca9086c9149c607589b23ffa599a5e4c26db7c20bd3700b79528bd3a5df991d third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -1755746cb3a28162a0bbd0b994332fa9ffaedca684803dfd9ef584040cea73ca target/nrf52840_dongle_dfu_merged.hex +0a9c92d56b02b42c7d783606f7711c474fc73518a32b9c7e244c078011a67e6d target/nrf52840_dongle_dfu_merged.hex 8857488ba6a69e366f0da229bbfc012a2ad291d3a88d9494247d600c10bb19b7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -04b94cd65bf83fa12030c4deaa831e0251f5f8b9684ec972d03a46e8f32e98b4 target/nrf52840_mdk_dfu_merged.hex -69dd51b947013b77e3577784384c935ed76930d1fb3ba46e9a5b6b5d71941057 target/tab/ctap2.tab +a5fb5ebcf475f88be0273a4679975bcfee72014102a6191370a80120ca287f11 target/nrf52840_mdk_dfu_merged.hex +7940a87663cf40941ea8c50ad1d99abf2ccbcacfcd157c1b0449dd3ed78e180e target/tab/ctap2.tab From 0073c153d257986e3260cac181bea80b50af789b Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Thu, 4 Jun 2020 14:32:04 +0200 Subject: [PATCH 07/24] Propagate the NBYTES constant from Int256 to SecKey --- libraries/crypto/src/ecdsa.rs | 6 ++++-- src/ctap/storage.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/crypto/src/ecdsa.rs b/libraries/crypto/src/ecdsa.rs index 966552d..8b4329a 100644 --- a/libraries/crypto/src/ecdsa.rs +++ b/libraries/crypto/src/ecdsa.rs @@ -22,6 +22,8 @@ use super::{Hash256, HashBlockSize64Bytes}; use alloc::vec::Vec; use core::marker::PhantomData; +pub use super::ec::int256::NBYTES; + #[derive(Clone, PartialEq)] #[cfg_attr(feature = "derive_debug", derive(Debug))] pub struct SecKey { @@ -140,7 +142,7 @@ impl SecKey { } } - pub fn from_bytes(bytes: &[u8; 32]) -> Option { + pub fn from_bytes(bytes: &[u8; NBYTES]) -> Option { let k = NonZeroExponentP256::from_int_checked(Int256::from_bin(bytes)); // The branching here is fine because all this reveals is whether the key was invalid. if bool::from(k.is_none()) { @@ -150,7 +152,7 @@ impl SecKey { Some(SecKey { k }) } - pub fn to_bytes(&self, bytes: &mut [u8; 32]) { + pub fn to_bytes(&self, bytes: &mut [u8; NBYTES]) { self.k.to_int().to_bin(bytes); } } diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index 452bff6..c138660 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -62,7 +62,7 @@ const AAGUID: usize = 7; const NUM_TAGS: usize = 8; const MAX_PIN_RETRIES: u8 = 6; -const ATTESTATION_PRIVATE_KEY_LENGTH: usize = 32; +const ATTESTATION_PRIVATE_KEY_LENGTH: usize = crypto::ecdsa::NBYTES; const AAGUID_LENGTH: usize = 16; #[derive(PartialEq, Eq, PartialOrd, Ord)] From 935ccf366865c4c0055be67127222177fe2f5cda Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Tue, 9 Jun 2020 11:55:36 +0200 Subject: [PATCH 08/24] Revert "Propagate the NBYTES constant from Int256 to SecKey" This reverts commit 0073c153d257986e3260cac181bea80b50af789b. --- libraries/crypto/src/ecdsa.rs | 6 ++---- src/ctap/storage.rs | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/crypto/src/ecdsa.rs b/libraries/crypto/src/ecdsa.rs index 8b4329a..966552d 100644 --- a/libraries/crypto/src/ecdsa.rs +++ b/libraries/crypto/src/ecdsa.rs @@ -22,8 +22,6 @@ use super::{Hash256, HashBlockSize64Bytes}; use alloc::vec::Vec; use core::marker::PhantomData; -pub use super::ec::int256::NBYTES; - #[derive(Clone, PartialEq)] #[cfg_attr(feature = "derive_debug", derive(Debug))] pub struct SecKey { @@ -142,7 +140,7 @@ impl SecKey { } } - pub fn from_bytes(bytes: &[u8; NBYTES]) -> Option { + pub fn from_bytes(bytes: &[u8; 32]) -> Option { let k = NonZeroExponentP256::from_int_checked(Int256::from_bin(bytes)); // The branching here is fine because all this reveals is whether the key was invalid. if bool::from(k.is_none()) { @@ -152,7 +150,7 @@ impl SecKey { Some(SecKey { k }) } - pub fn to_bytes(&self, bytes: &mut [u8; NBYTES]) { + pub fn to_bytes(&self, bytes: &mut [u8; 32]) { self.k.to_int().to_bin(bytes); } } diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index c138660..452bff6 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -62,7 +62,7 @@ const AAGUID: usize = 7; const NUM_TAGS: usize = 8; const MAX_PIN_RETRIES: u8 = 6; -const ATTESTATION_PRIVATE_KEY_LENGTH: usize = crypto::ecdsa::NBYTES; +const ATTESTATION_PRIVATE_KEY_LENGTH: usize = 32; const AAGUID_LENGTH: usize = 16; #[derive(PartialEq, Eq, PartialOrd, Ord)] From 87394f5a1a3322ce19e723bc67511f7fc79a2b2b Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Tue, 9 Jun 2020 12:06:19 +0200 Subject: [PATCH 09/24] Update reproducible hashes --- reproducible/reference_binaries_macos-10.15.sha256sum | 10 +++++----- reproducible/reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index 0228740..82cd7fc 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ 1003863864e06553e730eec6df4bf8d30c99f697ef9380efdc35eba679b4db78 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -022268c93fa8bbd9e54e082982b87c10a0e7c0486704de8219d1bb374304636a target/nrf52840dk_merged.hex +6b0a7402c38a37fc729644a4a92bfba8bc4431ad21f3a16d1527f2258e2231d1 target/nrf52840dk_merged.hex 88f00a5e1dae6ab3f7571c254ac75f5f3e29ebea7f3ca46c16cfdc3708e804fc third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -8d68ecc700527789b8edf318f0872ca8fc3b72fa73236f4e06bec89a3682fcf8 target/nrf52840_dongle_merged.hex +454ac8d360dec8705e243840df3807526b2383810a77573e9d4409dba96f43df target/nrf52840_dongle_merged.hex 1bc69b48a2c48da55db8b322902e1fe3f2e095c0dd8517db28837d86e0addc85 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -af5465e4209914aaf74ee878d03e883a717827119e47b9295aa279ee21f0c5f4 target/nrf52840_dongle_dfu_merged.hex +9efeed7965ba491a468640bd47b53010403244562b9ade71e0090b211888274c target/nrf52840_dongle_dfu_merged.hex f38ee31d3a09e7e11848e78b5318f95517b6dcd076afcb37e6e3d3e5e9995cc7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -23603386a615e4e8cb2173c5ce4762110e6cbb979efdbb6e8bef9bc1e3988de4 target/nrf52840_mdk_dfu_merged.hex -c2cbcc28b835934be4c3d3e3c5bdaba642a5811d760c1d2cb73d26b6474e4219 target/tab/ctap2.tab +911aa4f4f748910394c9f16d2e36dd06e71e311b2f9fee3f40522a13a2e4b671 target/nrf52840_mdk_dfu_merged.hex +529ac9aef3941b45e7e480810ae4e821da433985b149028aa6a33f33e0dc1685 target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index 666eecd..466282e 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ c182bb4902fff51b2f56810fc2a27df3646cd66ba21359162354d53445623ab8 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -d8b62ece387a77cc21f2c10a5f5d65d0d57bf4739b47fd86d2c9ecdd90fbfd7e target/nrf52840dk_merged.hex +bebc884aa49b79359b22916ca3d20eca3cddc3d4283ff6d0da1f0d46e1b6a1fb target/nrf52840dk_merged.hex 0a9929ba8fa57e8a502a49fc7c53177397202e1b11f4c7c3cb6ed68b2b99dd46 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -380de1a910b4d9eeb0c814b11b074b2e66334968cc99a4bd34d52a1fce3c5a79 target/nrf52840_dongle_merged.hex +8dca8415a01411d5f5589ec9688c9c6d229ca5a50fc27457060d001d90087c4b target/nrf52840_dongle_merged.hex cca9086c9149c607589b23ffa599a5e4c26db7c20bd3700b79528bd3a5df991d third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -4edd988b3e37991f1e58fc520e41f7666f8ae3e8d3993e1bb2fb71657a71fa50 target/nrf52840_dongle_dfu_merged.hex +64b36280f65508f5a6ca9a1708cc5cbd71663eb8068221434edf1c0201b9a339 target/nrf52840_dongle_dfu_merged.hex 8857488ba6a69e366f0da229bbfc012a2ad291d3a88d9494247d600c10bb19b7 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -a51aba1cd12e55aa33fd9017af406583ebf14e1c690295b15cf147713dfe2561 target/nrf52840_mdk_dfu_merged.hex -40b413a8b645b4b47fae62a4311acb12cb0c57faff2757e45c18d9e5d441e52d target/tab/ctap2.tab +2673ba4581bd704ab55f148b361ac530d07329106c3dc2d5594be90106764095 target/nrf52840_mdk_dfu_merged.hex +ba0e11a0036f167a56864de43db3602a8a855b38be8a53afc3a97fcaa40f2201 target/tab/ctap2.tab From c90e5d5db1592e0663afd15408e716c91457a98f Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Wed, 17 Jun 2020 13:01:45 +0200 Subject: [PATCH 10/24] Update reproducible hashes --- reproducible/reference_binaries_macos-10.15.sha256sum | 10 +++++----- reproducible/reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- reproducible/reference_elf2tab_macos-10.15.txt | 8 ++++---- reproducible/reference_elf2tab_ubuntu-18.04.txt | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index fce6c5d..578e88a 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ 1003863864e06553e730eec6df4bf8d30c99f697ef9380efdc35eba679b4db78 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -022268c93fa8bbd9e54e082982b87c10a0e7c0486704de8219d1bb374304636a target/nrf52840dk_merged.hex +6b0a7402c38a37fc729644a4a92bfba8bc4431ad21f3a16d1527f2258e2231d1 target/nrf52840dk_merged.hex 052eec0ae526038352b9f7573468d0cf7fb5ec331d4dc1a2df75fdbd514ea5ca third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -d2373ac9df2ba8feff88f19e67ec87a58e635b94f0a0f759b6fcf4c750b256c9 target/nrf52840_dongle_merged.hex +b35ac62a490c62d4b23dddf1d8e6946badb32b5b35b40bbd75587815530094c9 target/nrf52840_dongle_merged.hex 908d7f4f40936d968b91ab6e19b2406612fe8c2c273d9c0b71ef1f55116780e0 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -3c6f18ad1e1ceedeb622f39cd00ae3328ea5ad1557a9042c1b4bf831d5e1fb0d target/nrf52840_dongle_dfu_merged.hex +1adb9f71697947109020b25ad2b3fb3b03e6a07945dee14351ad67341241205e target/nrf52840_dongle_dfu_merged.hex 34ecbecaebf1188277f2310fe769c8c60310d8576493242712854deb4ba1036e third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -d1320adfcec35099ade04988111a947c05d14c43851fc5800d17d7a83bdba033 target/nrf52840_mdk_dfu_merged.hex -c2cbcc28b835934be4c3d3e3c5bdaba642a5811d760c1d2cb73d26b6474e4219 target/tab/ctap2.tab +1661fb4da7cbaf01529e593600f47c4613446a37f400cb0b238249d100a3d9f1 target/nrf52840_mdk_dfu_merged.hex +529ac9aef3941b45e7e480810ae4e821da433985b149028aa6a33f33e0dc1685 target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index b1ef07f..b8b0305 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ c182bb4902fff51b2f56810fc2a27df3646cd66ba21359162354d53445623ab8 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -d8b62ece387a77cc21f2c10a5f5d65d0d57bf4739b47fd86d2c9ecdd90fbfd7e target/nrf52840dk_merged.hex +bebc884aa49b79359b22916ca3d20eca3cddc3d4283ff6d0da1f0d46e1b6a1fb target/nrf52840dk_merged.hex 30f239390ae9bef0825731e4c82d40470fc5e9bded2bf0d942e92dbb5d4faba1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -c9349bd480b30e28214bb8d58d10938889050b92d34fbeb70e3110919b3a2601 target/nrf52840_dongle_merged.hex +1bf5219f7b096b4ade330e9b02544b09d10972ddf253c7fdfbd6241b03e98f31 target/nrf52840_dongle_merged.hex e3acf15d5ae3a22aecff6cc58db5fc311f538f47328d348b7ad7db7f9ab5e72c third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -08f3ca1bb79e13e83149324244929b68f8d7583630d9a62a8ffdedb710c95d8b target/nrf52840_dongle_dfu_merged.hex +b83edda1b2588e3eff019fc8b2e16097e159f8a43fa5fc62a6e23497882c8dca target/nrf52840_dongle_dfu_merged.hex cae312a26a513ada6c198fdc59b2bba3860c51726b817a9fd17a4331ee12c882 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -849c67c811da8d359d4e55d81d2587b3efa2f6065d72e4db09c3e571af8fef94 target/nrf52840_mdk_dfu_merged.hex -40b413a8b645b4b47fae62a4311acb12cb0c57faff2757e45c18d9e5d441e52d target/tab/ctap2.tab +d376cb19e672ab80b9dd25e9df40af7ac833d03ede32f4a2ae21fdfd4e31d365 target/nrf52840_mdk_dfu_merged.hex +ba0e11a0036f167a56864de43db3602a8a855b38be8a53afc3a97fcaa40f2201 target/tab/ctap2.tab diff --git a/reproducible/reference_elf2tab_macos-10.15.txt b/reproducible/reference_elf2tab_macos-10.15.txt index 94273d9..ab8a85c 100644 --- a/reproducible/reference_elf2tab_macos-10.15.txt +++ b/reproducible/reference_elf2tab_macos-10.15.txt @@ -5,8 +5,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -24,8 +24,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 diff --git a/reproducible/reference_elf2tab_ubuntu-18.04.txt b/reproducible/reference_elf2tab_ubuntu-18.04.txt index fd00e16..122e103 100644 --- a/reproducible/reference_elf2tab_ubuntu-18.04.txt +++ b/reproducible/reference_elf2tab_ubuntu-18.04.txt @@ -5,8 +5,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -24,8 +24,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 From d2247d94826a816529277904db8355813c07b76d Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Wed, 17 Jun 2020 14:06:39 +0200 Subject: [PATCH 11/24] Update reproducible hashes --- reproducible/reference_elf2tab_macos-10.15.txt | 8 ++++---- reproducible/reference_elf2tab_ubuntu-18.04.txt | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/reproducible/reference_elf2tab_macos-10.15.txt b/reproducible/reference_elf2tab_macos-10.15.txt index ab8a85c..e701412 100644 --- a/reproducible/reference_elf2tab_macos-10.15.txt +++ b/reproducible/reference_elf2tab_macos-10.15.txt @@ -43,8 +43,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -62,8 +62,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 diff --git a/reproducible/reference_elf2tab_ubuntu-18.04.txt b/reproducible/reference_elf2tab_ubuntu-18.04.txt index 122e103..4810644 100644 --- a/reproducible/reference_elf2tab_ubuntu-18.04.txt +++ b/reproducible/reference_elf2tab_ubuntu-18.04.txt @@ -43,8 +43,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -62,8 +62,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 From 46df22fa7cf58228194bc9fa05f0834b2332914d Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Fri, 19 Jun 2020 17:40:24 +0200 Subject: [PATCH 12/24] Remove unnecessary lifetime name --- src/ctap/storage.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index 5613b19..60dd99d 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -523,7 +523,7 @@ impl From for Ctap2StatusCode { } } -fn should_reset<'a>(entry: &StoreEntry<'a>) -> bool { +fn should_reset(entry: &StoreEntry<'_>) -> bool { match entry.tag { ATTESTATION_PRIVATE_KEY | ATTESTATION_CERTIFICATE | AAGUID => false, _ => true, From 60ead603471c9ce347497b88805853dff174ed84 Mon Sep 17 00:00:00 2001 From: Julien Cretin Date: Mon, 22 Jun 2020 10:29:25 +0200 Subject: [PATCH 13/24] Update reproducible hashes --- .../reference_binaries_macos-10.15.sha256sum | 10 +++++----- .../reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- reproducible/reference_elf2tab_macos-10.15.txt | 16 ++++++++-------- reproducible/reference_elf2tab_ubuntu-18.04.txt | 16 ++++++++-------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index 6d3272e..ab2e9a3 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ 0b54df6d548849e24d67b9b022ca09cb33c51f078ce85d0c9c4635ffc69902e1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -9ff63684ca08375e643f14f33dc6dc8131681bb562fb0df18f9c7f637e90cc73 target/nrf52840dk_merged.hex +f49e2205136159671f8291b284fc02300cf659f088a2ca301d74111e0e96849a target/nrf52840dk_merged.hex 052eec0ae526038352b9f7573468d0cf7fb5ec331d4dc1a2df75fdbd514ea5ca third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -d2373ac9df2ba8feff88f19e67ec87a58e635b94f0a0f759b6fcf4c750b256c9 target/nrf52840_dongle_merged.hex +b35ac62a490c62d4b23dddf1d8e6946badb32b5b35b40bbd75587815530094c9 target/nrf52840_dongle_merged.hex 908d7f4f40936d968b91ab6e19b2406612fe8c2c273d9c0b71ef1f55116780e0 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -3c6f18ad1e1ceedeb622f39cd00ae3328ea5ad1557a9042c1b4bf831d5e1fb0d target/nrf52840_dongle_dfu_merged.hex +1adb9f71697947109020b25ad2b3fb3b03e6a07945dee14351ad67341241205e target/nrf52840_dongle_dfu_merged.hex 34ecbecaebf1188277f2310fe769c8c60310d8576493242712854deb4ba1036e third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -d1320adfcec35099ade04988111a947c05d14c43851fc5800d17d7a83bdba033 target/nrf52840_mdk_dfu_merged.hex -c2cbcc28b835934be4c3d3e3c5bdaba642a5811d760c1d2cb73d26b6474e4219 target/tab/ctap2.tab +1661fb4da7cbaf01529e593600f47c4613446a37f400cb0b238249d100a3d9f1 target/nrf52840_mdk_dfu_merged.hex +529ac9aef3941b45e7e480810ae4e821da433985b149028aa6a33f33e0dc1685 target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index ea64676..5e3e757 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ 29382e72d0f3c6a72ce9517211952ff29ea270193d7f0ddc48ca69009ee29925 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -bb2fbf0d9dab2b489a49d1dc3db8923086ab109d14f1f1aa8296f086a03b75dd target/nrf52840dk_merged.hex +e446a94d67f77d5346be6e476641f4ff50561f5a77bfa8bc49262f89e7399893 target/nrf52840dk_merged.hex 30f239390ae9bef0825731e4c82d40470fc5e9bded2bf0d942e92dbb5d4faba1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -c9349bd480b30e28214bb8d58d10938889050b92d34fbeb70e3110919b3a2601 target/nrf52840_dongle_merged.hex +1bf5219f7b096b4ade330e9b02544b09d10972ddf253c7fdfbd6241b03e98f31 target/nrf52840_dongle_merged.hex e3acf15d5ae3a22aecff6cc58db5fc311f538f47328d348b7ad7db7f9ab5e72c third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -08f3ca1bb79e13e83149324244929b68f8d7583630d9a62a8ffdedb710c95d8b target/nrf52840_dongle_dfu_merged.hex +b83edda1b2588e3eff019fc8b2e16097e159f8a43fa5fc62a6e23497882c8dca target/nrf52840_dongle_dfu_merged.hex cae312a26a513ada6c198fdc59b2bba3860c51726b817a9fd17a4331ee12c882 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -849c67c811da8d359d4e55d81d2587b3efa2f6065d72e4db09c3e571af8fef94 target/nrf52840_mdk_dfu_merged.hex -40b413a8b645b4b47fae62a4311acb12cb0c57faff2757e45c18d9e5d441e52d target/tab/ctap2.tab +d376cb19e672ab80b9dd25e9df40af7ac833d03ede32f4a2ae21fdfd4e31d365 target/nrf52840_mdk_dfu_merged.hex +ba0e11a0036f167a56864de43db3602a8a855b38be8a53afc3a97fcaa40f2201 target/tab/ctap2.tab diff --git a/reproducible/reference_elf2tab_macos-10.15.txt b/reproducible/reference_elf2tab_macos-10.15.txt index 94273d9..e701412 100644 --- a/reproducible/reference_elf2tab_macos-10.15.txt +++ b/reproducible/reference_elf2tab_macos-10.15.txt @@ -5,8 +5,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -24,8 +24,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -43,8 +43,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -62,8 +62,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175636 (0x2ae14) bytes. - Adding .stack section. Offset: 175764 (0x2ae94). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. + Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 diff --git a/reproducible/reference_elf2tab_ubuntu-18.04.txt b/reproducible/reference_elf2tab_ubuntu-18.04.txt index fd00e16..4810644 100644 --- a/reproducible/reference_elf2tab_ubuntu-18.04.txt +++ b/reproducible/reference_elf2tab_ubuntu-18.04.txt @@ -5,8 +5,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -24,8 +24,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -43,8 +43,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -62,8 +62,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 175252 (0x2ac94) bytes. - Adding .stack section. Offset: 175380 (0x2ad14). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. + Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 From 97fb22245598537e1d0bb294becb88086e05cc54 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Tue, 9 Jun 2020 14:36:16 +0200 Subject: [PATCH 14/24] Add a read_cbor_map macro to avoid the overhead of removing values on-by-one in BTreeMap. --- libraries/cbor/src/macros.rs | 151 +++++++++++++++++++++++++++++++ src/ctap/command.rs | 119 +++++++++++-------------- src/ctap/data_formats.rs | 166 +++++++++++++++++++++-------------- 3 files changed, 306 insertions(+), 130 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 5a3d8f5..708fea6 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -12,6 +12,68 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[macro_export] +macro_rules! read_cbor_map { + ( $map:expr, $( $variable:ident @ $key:expr, )+ ) => { + // A pre-requisite for this algorithm to work is that the keys to extract from the map are + // sorted. + #[cfg(test)] + test_ordered_keys!($( $key, )+); + + use $crate::values::{KeyType, Value}; + use ::core::cmp::Ordering; + use ::core::iter::Peekable; + use ::alloc::collections::btree_map::IntoIter; + + let mut it: Peekable> = $map.into_iter().peekable(); + $( + let $variable: Option = { + let needle: KeyType = $key; + loop { + match it.peek() { + None => break None, + Some(item) => { + let key: &KeyType = &item.0; + match key.cmp(&needle) { + Ordering::Less => { + it.next(); + continue + }, + Ordering::Equal => { + let value: Value = it.next().unwrap().1; + break Some(value) + }, + Ordering::Greater => break None, + } + } + } + } + }; + )+ + }; +} + +#[macro_export] +macro_rules! test_ordered_keys { + // Last key + ( $key:expr, ) => { + }; + + ( $key1:expr, $key2:expr, $( $keys:expr, )* ) => { + { + let k1: $crate::values::KeyType = $key1; + let k2: $crate::values::KeyType = $key2; + assert!( + k1 < k2, + "{:?} < {:?} failed. The read_cbor_map! macro requires keys in sorted order.", + k1, + k2, + ); + } + test_ordered_keys!($key2, $( $keys, )*); + }; +} + #[macro_export] macro_rules! cbor_map { // trailing comma case @@ -497,4 +559,93 @@ mod test { ); assert_eq!(a, b); } + + fn extract_map(cbor_value: Value) -> BTreeMap { + match cbor_value { + Value::Map(map) => map, + _ => panic!("Expected CBOR map."), + } + } + + #[test] + fn test_read_cbor_map_simple() { + let map = cbor_map! { + 1 => 10, + 2 => 20, + }; + + read_cbor_map! { + extract_map(map), + x1 @ cbor_unsigned!(1), + x2 @ cbor_unsigned!(2), + }; + + assert_eq!(x1, Some(cbor_unsigned!(10))); + assert_eq!(x2, Some(cbor_unsigned!(20))); + } + + #[test] + #[should_panic] + fn test_read_cbor_map_unordered() { + let map = cbor_map! { + 1 => 10, + 2 => 20, + }; + + read_cbor_map! { + extract_map(map), + _x2 @ cbor_unsigned!(2), + _x1 @ cbor_unsigned!(1), + }; + } + + #[test] + fn test_read_cbor_map_partial() { + let map = cbor_map! { + 1 => 10, + 2 => 20, + 3 => 30, + 4 => 40, + 5 => 50, + 6 => 60, + 7 => 70, + 8 => 80, + 9 => 90, + }; + + read_cbor_map! { + extract_map(map), + x3 @ cbor_unsigned!(3), + x7 @ cbor_unsigned!(7), + }; + + assert_eq!(x3, Some(cbor_unsigned!(30))); + assert_eq!(x7, Some(cbor_unsigned!(70))); + } + + #[test] + fn test_read_cbor_map_missing() { + let map = cbor_map! { + 1 => 10, + 3 => 30, + 4 => 40, + }; + + read_cbor_map! { + extract_map(map), + x0 @ cbor_unsigned!(0), + x1 @ cbor_unsigned!(1), + x2 @ cbor_unsigned!(2), + x3 @ cbor_unsigned!(3), + x4 @ cbor_unsigned!(4), + x5 @ cbor_unsigned!(5), + }; + + assert_eq!(x0, None); + assert_eq!(x1, Some(cbor_unsigned!(10))); + assert_eq!(x2, None); + assert_eq!(x3, Some(cbor_unsigned!(30))); + assert_eq!(x4, Some(cbor_unsigned!(40))); + assert_eq!(x5, None); + } } diff --git a/src/ctap/command.rs b/src/ctap/command.rs index d6dd0fa..03f38eb 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -124,26 +124,30 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut param_map = extract_map(cbor_value)?; + read_cbor_map! { + extract_map(cbor_value)?, + client_data_hash @ cbor_unsigned!(1), + rp @ cbor_unsigned!(2), + user @ cbor_unsigned!(3), + cred_param_vec @ cbor_unsigned!(4), + exclude_list @ cbor_unsigned!(5), + extensions @ cbor_unsigned!(6), + options @ cbor_unsigned!(7), + pin_uv_auth_param @ cbor_unsigned!(8), + pin_uv_auth_protocol @ cbor_unsigned!(9), + }; - let client_data_hash = - extract_byte_string(ok_or_missing(param_map.remove(&cbor_unsigned!(1)))?)?; + let client_data_hash = extract_byte_string(ok_or_missing(client_data_hash)?)?; + let rp = PublicKeyCredentialRpEntity::try_from(ok_or_missing(rp)?)?; + let user = PublicKeyCredentialUserEntity::try_from(ok_or_missing(user)?)?; - let rp = PublicKeyCredentialRpEntity::try_from(ok_or_missing( - param_map.remove(&cbor_unsigned!(2)), - )?)?; - - let user = PublicKeyCredentialUserEntity::try_from(ok_or_missing( - param_map.remove(&cbor_unsigned!(3)), - )?)?; - - let cred_param_vec = extract_array(ok_or_missing(param_map.remove(&cbor_unsigned!(4)))?)?; + let cred_param_vec = extract_array(ok_or_missing(cred_param_vec)?)?; let pub_key_cred_params = cred_param_vec .into_iter() .map(PublicKeyCredentialParameter::try_from) .collect::, Ctap2StatusCode>>()?; - let exclude_list = match param_map.remove(&cbor_unsigned!(5)) { + let exclude_list = match exclude_list { Some(entry) => { let exclude_list_vec = extract_array(entry)?; let list_len = MAX_CREDENTIAL_COUNT_IN_LIST.unwrap_or(exclude_list_vec.len()); @@ -157,12 +161,11 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { None => None, }; - let extensions = param_map - .remove(&cbor_unsigned!(6)) + let extensions = extensions .map(MakeCredentialExtensions::try_from) .transpose()?; - let options = match param_map.remove(&cbor_unsigned!(7)) { + let options = match options { Some(entry) => MakeCredentialOptions::try_from(entry)?, None => MakeCredentialOptions { rk: false, @@ -170,15 +173,8 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { }, }; - let pin_uv_auth_param = param_map - .remove(&cbor_unsigned!(8)) - .map(extract_byte_string) - .transpose()?; - - let pin_uv_auth_protocol = param_map - .remove(&cbor_unsigned!(9)) - .map(extract_unsigned) - .transpose()?; + let pin_uv_auth_param = pin_uv_auth_param.map(extract_byte_string).transpose()?; + let pin_uv_auth_protocol = pin_uv_auth_protocol.map(extract_unsigned).transpose()?; Ok(AuthenticatorMakeCredentialParameters { client_data_hash, @@ -210,14 +206,21 @@ impl TryFrom for AuthenticatorGetAssertionParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut param_map = extract_map(cbor_value)?; + read_cbor_map! { + extract_map(cbor_value)?, + rp_id @ cbor_unsigned!(1), + client_data_hash @ cbor_unsigned!(2), + allow_list @ cbor_unsigned!(3), + extensions @ cbor_unsigned!(4), + options @ cbor_unsigned!(5), + pin_uv_auth_param @ cbor_unsigned!(6), + pin_uv_auth_protocol @ cbor_unsigned!(7), + }; - let rp_id = extract_text_string(ok_or_missing(param_map.remove(&cbor_unsigned!(1)))?)?; + let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; + let client_data_hash = extract_byte_string(ok_or_missing(client_data_hash)?)?; - let client_data_hash = - extract_byte_string(ok_or_missing(param_map.remove(&cbor_unsigned!(2)))?)?; - - let allow_list = match param_map.remove(&cbor_unsigned!(3)) { + let allow_list = match allow_list { Some(entry) => { let allow_list_vec = extract_array(entry)?; let list_len = MAX_CREDENTIAL_COUNT_IN_LIST.unwrap_or(allow_list_vec.len()); @@ -231,12 +234,11 @@ impl TryFrom for AuthenticatorGetAssertionParameters { None => None, }; - let extensions = param_map - .remove(&cbor_unsigned!(4)) + let extensions = extensions .map(GetAssertionExtensions::try_from) .transpose()?; - let options = match param_map.remove(&cbor_unsigned!(5)) { + let options = match options { Some(entry) => GetAssertionOptions::try_from(entry)?, None => GetAssertionOptions { up: true, @@ -244,15 +246,8 @@ impl TryFrom for AuthenticatorGetAssertionParameters { }, }; - let pin_uv_auth_param = param_map - .remove(&cbor_unsigned!(6)) - .map(extract_byte_string) - .transpose()?; - - let pin_uv_auth_protocol = param_map - .remove(&cbor_unsigned!(7)) - .map(extract_unsigned) - .transpose()?; + let pin_uv_auth_param = pin_uv_auth_param.map(extract_byte_string).transpose()?; + let pin_uv_auth_protocol = pin_uv_auth_protocol.map(extract_unsigned).transpose()?; Ok(AuthenticatorGetAssertionParameters { rp_id, @@ -280,33 +275,25 @@ impl TryFrom for AuthenticatorClientPinParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut param_map = extract_map(cbor_value)?; + read_cbor_map! { + extract_map(cbor_value)?, + pin_protocol @ cbor_unsigned!(1), + sub_command @ cbor_unsigned!(2), + key_agreement @ cbor_unsigned!(3), + pin_auth @ cbor_unsigned!(4), + new_pin_enc @ cbor_unsigned!(5), + pin_hash_enc @ cbor_unsigned!(6), + }; - let pin_protocol = extract_unsigned(ok_or_missing(param_map.remove(&cbor_unsigned!(1)))?)?; - - let sub_command = - ClientPinSubCommand::try_from(ok_or_missing(param_map.remove(&cbor_unsigned!(2)))?)?; - - let key_agreement = param_map - .remove(&cbor_unsigned!(3)) + let pin_protocol = extract_unsigned(ok_or_missing(pin_protocol)?)?; + let sub_command = ClientPinSubCommand::try_from(ok_or_missing(sub_command)?)?; + let key_agreement = key_agreement .map(extract_map) .transpose()? .map(|x| CoseKey(x)); - - let pin_auth = param_map - .remove(&cbor_unsigned!(4)) - .map(extract_byte_string) - .transpose()?; - - let new_pin_enc = param_map - .remove(&cbor_unsigned!(5)) - .map(extract_byte_string) - .transpose()?; - - let pin_hash_enc = param_map - .remove(&cbor_unsigned!(6)) - .map(extract_byte_string) - .transpose()?; + let pin_auth = pin_auth.map(extract_byte_string).transpose()?; + let new_pin_enc = new_pin_enc.map(extract_byte_string).transpose()?; + let pin_hash_enc = pin_hash_enc.map(extract_byte_string).transpose()?; Ok(AuthenticatorClientPinParameters { pin_protocol, diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index 33dec12..0a5cab5 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -31,16 +31,17 @@ impl TryFrom for PublicKeyCredentialRpEntity { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut rp_map = extract_map(cbor_value)?; - let rp_id = extract_text_string(ok_or_missing(rp_map.remove(&cbor_text!("id")))?)?; - let rp_name = rp_map - .remove(&cbor_text!("name")) - .map(extract_text_string) - .transpose()?; - let rp_icon = rp_map - .remove(&cbor_text!("icon")) - .map(extract_text_string) - .transpose()?; + read_cbor_map! { + extract_map(cbor_value)?, + rp_id @ cbor_text!("id"), + rp_icon @ cbor_text!("icon"), + rp_name @ cbor_text!("name"), + }; + + let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; + let rp_name = rp_name.map(extract_text_string).transpose()?; + let rp_icon = rp_icon.map(extract_text_string).transpose()?; + Ok(Self { rp_id, rp_name, @@ -62,20 +63,19 @@ impl TryFrom for PublicKeyCredentialUserEntity { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut user_map = extract_map(cbor_value)?; - let user_id = extract_byte_string(ok_or_missing(user_map.remove(&cbor_text!("id")))?)?; - let user_name = user_map - .remove(&cbor_text!("name")) - .map(extract_text_string) - .transpose()?; - let user_display_name = user_map - .remove(&cbor_text!("displayName")) - .map(extract_text_string) - .transpose()?; - let user_icon = user_map - .remove(&cbor_text!("icon")) - .map(extract_text_string) - .transpose()?; + read_cbor_map! { + extract_map(cbor_value)?, + user_id @ cbor_text!("id"), + user_icon @ cbor_text!("icon"), + user_name @ cbor_text!("name"), + user_display_name @ cbor_text!("displayName"), + }; + + let user_id = extract_byte_string(ok_or_missing(user_id)?)?; + let user_name = user_name.map(extract_text_string).transpose()?; + let user_display_name = user_display_name.map(extract_text_string).transpose()?; + let user_icon = user_icon.map(extract_text_string).transpose()?; + Ok(Self { user_id, user_name, @@ -141,13 +141,14 @@ impl TryFrom for PublicKeyCredentialParameter { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut cred_param_map = extract_map(cbor_value)?; - let cred_type = PublicKeyCredentialType::try_from(ok_or_missing( - cred_param_map.remove(&cbor_text!("type")), - )?)?; - let alg = SignatureAlgorithm::try_from(ok_or_missing( - cred_param_map.remove(&cbor_text!("alg")), - )?)?; + read_cbor_map! { + extract_map(cbor_value)?, + alg @ cbor_text!("alg"), + cred_type @ cbor_text!("type"), + }; + + let cred_type = PublicKeyCredentialType::try_from(ok_or_missing(cred_type)?)?; + let alg = SignatureAlgorithm::try_from(ok_or_missing(alg)?)?; Ok(Self { cred_type, alg }) } } @@ -209,12 +210,16 @@ impl TryFrom for PublicKeyCredentialDescriptor { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut cred_desc_map = extract_map(cbor_value)?; - let key_type = PublicKeyCredentialType::try_from(ok_or_missing( - cred_desc_map.remove(&cbor_text!("type")), - )?)?; - let key_id = extract_byte_string(ok_or_missing(cred_desc_map.remove(&cbor_text!("id")))?)?; - let transports = match cred_desc_map.remove(&cbor_text!("transports")) { + read_cbor_map! { + extract_map(cbor_value)?, + key_id @ cbor_text!("id"), + key_type @ cbor_text!("type"), + transports @ cbor_text!("transports"), + }; + + let key_type = PublicKeyCredentialType::try_from(ok_or_missing(key_type)?)?; + let key_id = extract_byte_string(ok_or_missing(key_id)?)?; + let transports = match transports { Some(exclude_entry) => { let transport_vec = extract_array(exclude_entry)?; let transports = transport_vec @@ -225,6 +230,7 @@ impl TryFrom for PublicKeyCredentialDescriptor { } None => None, }; + Ok(Self { key_type, key_id, @@ -253,12 +259,14 @@ impl TryFrom for MakeCredentialExtensions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut extensions_map = extract_map(cbor_value)?; - let hmac_secret = extensions_map - .remove(&cbor_text!("hmac-secret")) - .map_or(Ok(false), extract_bool)?; - let cred_protect = extensions_map - .remove(&cbor_text!("credProtect")) + read_cbor_map! { + extract_map(cbor_value)?, + cred_protect @ cbor_text!("credProtect"), + hmac_secret @ cbor_text!("hmac-secret"), + }; + + let hmac_secret = hmac_secret.map_or(Ok(false), extract_bool)?; + let cred_protect = cred_protect .map(CredentialProtectionPolicy::try_from) .transpose()?; Ok(Self { @@ -277,9 +285,12 @@ impl TryFrom for GetAssertionExtensions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut extensions_map = extract_map(cbor_value)?; - let hmac_secret = extensions_map - .remove(&cbor_text!("hmac-secret")) + read_cbor_map! { + extract_map(cbor_value)?, + hmac_secret @ cbor_text!("hmac-secret"), + }; + + let hmac_secret = hmac_secret .map(GetAssertionHmacSecretInput::try_from) .transpose()?; Ok(Self { hmac_secret }) @@ -297,10 +308,16 @@ impl TryFrom for GetAssertionHmacSecretInput { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut input_map = extract_map(cbor_value)?; - let cose_key = extract_map(ok_or_missing(input_map.remove(&cbor_unsigned!(1)))?)?; - let salt_enc = extract_byte_string(ok_or_missing(input_map.remove(&cbor_unsigned!(2)))?)?; - let salt_auth = extract_byte_string(ok_or_missing(input_map.remove(&cbor_unsigned!(3)))?)?; + read_cbor_map! { + extract_map(cbor_value)?, + cose_key @ cbor_unsigned!(1), + salt_enc @ cbor_unsigned!(2), + salt_auth @ cbor_unsigned!(3), + }; + + let cose_key = extract_map(ok_or_missing(cose_key)?)?; + let salt_enc = extract_byte_string(ok_or_missing(salt_enc)?)?; + let salt_auth = extract_byte_string(ok_or_missing(salt_auth)?)?; Ok(Self { key_agreement: CoseKey(cose_key), salt_enc, @@ -320,17 +337,23 @@ impl TryFrom for MakeCredentialOptions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut options_map = extract_map(cbor_value)?; - let rk = match options_map.remove(&cbor_text!("rk")) { + read_cbor_map! { + extract_map(cbor_value)?, + rk @ cbor_text!("rk"), + up @ cbor_text!("up"), + uv @ cbor_text!("uv"), + }; + + let rk = match rk { Some(options_entry) => extract_bool(options_entry)?, None => false, }; - if let Some(options_entry) = options_map.remove(&cbor_text!("up")) { + if let Some(options_entry) = up { if !extract_bool(options_entry)? { return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); } } - let uv = match options_map.remove(&cbor_text!("uv")) { + let uv = match uv { Some(options_entry) => extract_bool(options_entry)?, None => false, }; @@ -348,17 +371,23 @@ impl TryFrom for GetAssertionOptions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - let mut options_map = extract_map(cbor_value)?; - if let Some(options_entry) = options_map.remove(&cbor_text!("rk")) { + read_cbor_map! { + extract_map(cbor_value)?, + rk @ cbor_text!("rk"), + up @ cbor_text!("up"), + uv @ cbor_text!("uv"), + }; + + if let Some(options_entry) = rk { // This is only for returning the correct status code. extract_bool(options_entry)?; return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_OPTION); } - let up = match options_map.remove(&cbor_text!("up")) { + let up = match up { Some(options_entry) => extract_bool(options_entry)?, None => true, }; - let uv = match options_map.remove(&cbor_text!("uv")) { + let uv = match uv { Some(options_entry) => extract_bool(options_entry)?, None => false, }; @@ -599,27 +628,36 @@ impl TryFrom for ecdh::PubKey { type Error = Ctap2StatusCode; fn try_from(cose_key: CoseKey) -> Result { - let mut cose_map = cose_key.0; - let key_type = extract_integer(ok_or_missing(cose_map.remove(&cbor_int!(1)))?)?; + read_cbor_map! { + cose_key.0, + key_type @ cbor_int!(1), + algorithm @ cbor_int!(3), + curve @ cbor_int!(-1), + x_bytes @ cbor_int!(-2), + y_bytes @ cbor_int!(-3), + }; + + let key_type = extract_integer(ok_or_missing(key_type)?)?; if key_type != EC2_KEY_TYPE { return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); } - let algorithm = extract_integer(ok_or_missing(cose_map.remove(&cbor_int!(3)))?)?; + let algorithm = extract_integer(ok_or_missing(algorithm)?)?; if algorithm != ECDH_ALGORITHM && algorithm != ES256_ALGORITHM { return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); } - let curve = extract_integer(ok_or_missing(cose_map.remove(&cbor_int!(-1)))?)?; + let curve = extract_integer(ok_or_missing(curve)?)?; if curve != P_256_CURVE { return Err(Ctap2StatusCode::CTAP2_ERR_UNSUPPORTED_ALGORITHM); } - let x_bytes = extract_byte_string(ok_or_missing(cose_map.remove(&cbor_int!(-2)))?)?; + let x_bytes = extract_byte_string(ok_or_missing(x_bytes)?)?; if x_bytes.len() != ecdh::NBYTES { return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); } - let y_bytes = extract_byte_string(ok_or_missing(cose_map.remove(&cbor_int!(-3)))?)?; + let y_bytes = extract_byte_string(ok_or_missing(y_bytes)?)?; if y_bytes.len() != ecdh::NBYTES { return Err(Ctap2StatusCode::CTAP1_ERR_INVALID_PARAMETER); } + let x_array_ref = array_ref![x_bytes.as_slice(), 0, ecdh::NBYTES]; let y_array_ref = array_ref![y_bytes.as_slice(), 0, ecdh::NBYTES]; ecdh::PubKey::from_coordinates(x_array_ref, y_array_ref) From 2c4bf7d42284907693f314940103fc5e833f34f5 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Tue, 9 Jun 2020 15:12:05 +0200 Subject: [PATCH 15/24] Add documentation for read_cbor_map! macro. --- libraries/cbor/src/macros.rs | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 708fea6..c6b5499 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -12,6 +12,51 @@ // See the License for the specific language governing permissions and // limitations under the License. +/// This macro generates code to extract multiple values from a `BTreeMap` at once +/// in an optimized manner, consuming the input map. +/// +/// It takes as input a `BTreeMap` as well as a list of identifiers and keys, and generates code +/// that assigns the corresponding values to new variables using the given identifiers. Each of +/// these variables has type `Option`, to account for the case where keys aren't found. +/// +/// **Important:** Keys passed to the `read_cbor_map!` macro **must be sorted** in increasing order. +/// If not, the algorithm can yield incorrect results, such a assigning `None` to a variable even if +/// the corresponding key existed in the map. **No runtime checks** are made for this in the +/// `read_cbor_map!` macro, in order to avoid overhead at runtime. However, assertions that keys are +/// sorted are added in `cfg(test)` mode, so that unit tests can verify ahead of time that the keys +/// are indeed sorted. This macro is therefore **not suitable for dynamic keys** that can change at +/// runtime. +/// +/// Semantically, provided that the keys are sorted as specified above, the following two snippets +/// of code are equivalent, but the `read_cbor_map!` version is more optimized, as it doesn't +/// re-balance the `BTreeMap` for each key, contrary to the `BTreeMap::remove` operations. +/// +/// ```rust +/// # extern crate alloc; +/// # #[macro_use] +/// # extern crate cbor; +/// # +/// # fn main() { +/// # let map = alloc::collections::BTreeMap::new(); +/// read_cbor_map! { +/// map, +/// x @ cbor_unsigned!(1), +/// y @ cbor_unsigned!(2), +/// }; +/// # } +/// ``` +/// +/// ```rust +/// # extern crate alloc; +/// # #[macro_use] +/// # extern crate cbor; +/// # +/// # fn main() { +/// # let mut map = alloc::collections::BTreeMap::::new(); +/// let x: Option = map.remove(&cbor_unsigned!(1)); +/// let y: Option = map.remove(&cbor_unsigned!(2)); +/// # } +/// ``` #[macro_export] macro_rules! read_cbor_map { ( $map:expr, $( $variable:ident @ $key:expr, )+ ) => { From 2124511913b3990beee2561509f13b2731190632 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Tue, 9 Jun 2020 15:26:55 +0200 Subject: [PATCH 16/24] Simplify syntax of the read_cbor_map! macro, to align it with cbor_map. --- libraries/cbor/src/macros.rs | 37 ++++++++++++----------- src/ctap/command.rs | 44 +++++++++++++-------------- src/ctap/data_formats.rs | 58 ++++++++++++++++++------------------ 3 files changed, 70 insertions(+), 69 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index c6b5499..5814a2a 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -40,8 +40,8 @@ /// # let map = alloc::collections::BTreeMap::new(); /// read_cbor_map! { /// map, -/// x @ cbor_unsigned!(1), -/// y @ cbor_unsigned!(2), +/// x @ 1, +/// y @ 2, /// }; /// # } /// ``` @@ -65,7 +65,7 @@ macro_rules! read_cbor_map { #[cfg(test)] test_ordered_keys!($( $key, )+); - use $crate::values::{KeyType, Value}; + use $crate::values::{IntoCborKey, KeyType, Value}; use ::core::cmp::Ordering; use ::core::iter::Peekable; use ::alloc::collections::btree_map::IntoIter; @@ -73,7 +73,7 @@ macro_rules! read_cbor_map { let mut it: Peekable> = $map.into_iter().peekable(); $( let $variable: Option = { - let needle: KeyType = $key; + let needle: KeyType = $key.into_cbor_key(); loop { match it.peek() { None => break None, @@ -106,8 +106,9 @@ macro_rules! test_ordered_keys { ( $key1:expr, $key2:expr, $( $keys:expr, )* ) => { { - let k1: $crate::values::KeyType = $key1; - let k2: $crate::values::KeyType = $key2; + use $crate::values::{IntoCborKey, KeyType}; + let k1: KeyType = $key1.into_cbor_key(); + let k2: KeyType = $key2.into_cbor_key(); assert!( k1 < k2, "{:?} < {:?} failed. The read_cbor_map! macro requires keys in sorted order.", @@ -621,8 +622,8 @@ mod test { read_cbor_map! { extract_map(map), - x1 @ cbor_unsigned!(1), - x2 @ cbor_unsigned!(2), + x1 @ 1, + x2 @ 2, }; assert_eq!(x1, Some(cbor_unsigned!(10))); @@ -639,8 +640,8 @@ mod test { read_cbor_map! { extract_map(map), - _x2 @ cbor_unsigned!(2), - _x1 @ cbor_unsigned!(1), + _x2 @ 2, + _x1 @ 1, }; } @@ -660,8 +661,8 @@ mod test { read_cbor_map! { extract_map(map), - x3 @ cbor_unsigned!(3), - x7 @ cbor_unsigned!(7), + x3 @ 3, + x7 @ 7, }; assert_eq!(x3, Some(cbor_unsigned!(30))); @@ -678,12 +679,12 @@ mod test { read_cbor_map! { extract_map(map), - x0 @ cbor_unsigned!(0), - x1 @ cbor_unsigned!(1), - x2 @ cbor_unsigned!(2), - x3 @ cbor_unsigned!(3), - x4 @ cbor_unsigned!(4), - x5 @ cbor_unsigned!(5), + x0 @ 0, + x1 @ 1, + x2 @ 2, + x3 @ 3, + x4 @ 4, + x5 @ 5, }; assert_eq!(x0, None); diff --git a/src/ctap/command.rs b/src/ctap/command.rs index 03f38eb..7307c40 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -126,15 +126,15 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - client_data_hash @ cbor_unsigned!(1), - rp @ cbor_unsigned!(2), - user @ cbor_unsigned!(3), - cred_param_vec @ cbor_unsigned!(4), - exclude_list @ cbor_unsigned!(5), - extensions @ cbor_unsigned!(6), - options @ cbor_unsigned!(7), - pin_uv_auth_param @ cbor_unsigned!(8), - pin_uv_auth_protocol @ cbor_unsigned!(9), + client_data_hash @ 1, + rp @ 2, + user @ 3, + cred_param_vec @ 4, + exclude_list @ 5, + extensions @ 6, + options @ 7, + pin_uv_auth_param @ 8, + pin_uv_auth_protocol @ 9, }; let client_data_hash = extract_byte_string(ok_or_missing(client_data_hash)?)?; @@ -208,13 +208,13 @@ impl TryFrom for AuthenticatorGetAssertionParameters { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - rp_id @ cbor_unsigned!(1), - client_data_hash @ cbor_unsigned!(2), - allow_list @ cbor_unsigned!(3), - extensions @ cbor_unsigned!(4), - options @ cbor_unsigned!(5), - pin_uv_auth_param @ cbor_unsigned!(6), - pin_uv_auth_protocol @ cbor_unsigned!(7), + rp_id @ 1, + client_data_hash @ 2, + allow_list @ 3, + extensions @ 4, + options @ 5, + pin_uv_auth_param @ 6, + pin_uv_auth_protocol @ 7, }; let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; @@ -277,12 +277,12 @@ impl TryFrom for AuthenticatorClientPinParameters { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - pin_protocol @ cbor_unsigned!(1), - sub_command @ cbor_unsigned!(2), - key_agreement @ cbor_unsigned!(3), - pin_auth @ cbor_unsigned!(4), - new_pin_enc @ cbor_unsigned!(5), - pin_hash_enc @ cbor_unsigned!(6), + pin_protocol @ 1, + sub_command @ 2, + key_agreement @ 3, + pin_auth @ 4, + new_pin_enc @ 5, + pin_hash_enc @ 6, }; let pin_protocol = extract_unsigned(ok_or_missing(pin_protocol)?)?; diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index 0a5cab5..b34a709 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -33,9 +33,9 @@ impl TryFrom for PublicKeyCredentialRpEntity { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - rp_id @ cbor_text!("id"), - rp_icon @ cbor_text!("icon"), - rp_name @ cbor_text!("name"), + rp_id @ "id", + rp_icon @ "icon", + rp_name @ "name", }; let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; @@ -65,10 +65,10 @@ impl TryFrom for PublicKeyCredentialUserEntity { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - user_id @ cbor_text!("id"), - user_icon @ cbor_text!("icon"), - user_name @ cbor_text!("name"), - user_display_name @ cbor_text!("displayName"), + user_id @ "id", + user_icon @ "icon", + user_name @ "name", + user_display_name @ "displayName", }; let user_id = extract_byte_string(ok_or_missing(user_id)?)?; @@ -143,8 +143,8 @@ impl TryFrom for PublicKeyCredentialParameter { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - alg @ cbor_text!("alg"), - cred_type @ cbor_text!("type"), + alg @ "alg", + cred_type @ "type", }; let cred_type = PublicKeyCredentialType::try_from(ok_or_missing(cred_type)?)?; @@ -212,9 +212,9 @@ impl TryFrom for PublicKeyCredentialDescriptor { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - key_id @ cbor_text!("id"), - key_type @ cbor_text!("type"), - transports @ cbor_text!("transports"), + key_id @ "id", + key_type @ "type", + transports @ "transports", }; let key_type = PublicKeyCredentialType::try_from(ok_or_missing(key_type)?)?; @@ -261,8 +261,8 @@ impl TryFrom for MakeCredentialExtensions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - cred_protect @ cbor_text!("credProtect"), - hmac_secret @ cbor_text!("hmac-secret"), + cred_protect @ "credProtect", + hmac_secret @ "hmac-secret", }; let hmac_secret = hmac_secret.map_or(Ok(false), extract_bool)?; @@ -287,7 +287,7 @@ impl TryFrom for GetAssertionExtensions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - hmac_secret @ cbor_text!("hmac-secret"), + hmac_secret @ "hmac-secret", }; let hmac_secret = hmac_secret @@ -310,9 +310,9 @@ impl TryFrom for GetAssertionHmacSecretInput { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - cose_key @ cbor_unsigned!(1), - salt_enc @ cbor_unsigned!(2), - salt_auth @ cbor_unsigned!(3), + cose_key @ 1, + salt_enc @ 2, + salt_auth @ 3, }; let cose_key = extract_map(ok_or_missing(cose_key)?)?; @@ -339,9 +339,9 @@ impl TryFrom for MakeCredentialOptions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - rk @ cbor_text!("rk"), - up @ cbor_text!("up"), - uv @ cbor_text!("uv"), + rk @ "rk", + up @ "up", + uv @ "uv", }; let rk = match rk { @@ -373,9 +373,9 @@ impl TryFrom for GetAssertionOptions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { extract_map(cbor_value)?, - rk @ cbor_text!("rk"), - up @ cbor_text!("up"), - uv @ cbor_text!("uv"), + rk @ "rk", + up @ "up", + uv @ "uv", }; if let Some(options_entry) = rk { @@ -630,11 +630,11 @@ impl TryFrom for ecdh::PubKey { fn try_from(cose_key: CoseKey) -> Result { read_cbor_map! { cose_key.0, - key_type @ cbor_int!(1), - algorithm @ cbor_int!(3), - curve @ cbor_int!(-1), - x_bytes @ cbor_int!(-2), - y_bytes @ cbor_int!(-3), + key_type @ 1, + algorithm @ 3, + curve @ -1, + x_bytes @ -2, + y_bytes @ -3, }; let key_type = extract_integer(ok_or_missing(key_type)?)?; From c8864666e0160870c328d0c2b6cb2c7e85661298 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Tue, 9 Jun 2020 17:41:42 +0200 Subject: [PATCH 17/24] Extract some logic to a separate function, to reduce binary size overhead of read_cbor_map. --- libraries/cbor/src/macros.rs | 67 +++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 5814a2a..29d76b1 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -12,6 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::values::{KeyType, Value}; +use alloc::collections::btree_map; +use core::cmp::Ordering; +use core::iter::Peekable; + /// This macro generates code to extract multiple values from a `BTreeMap` at once /// in an optimized manner, consuming the input map. /// @@ -65,39 +70,47 @@ macro_rules! read_cbor_map { #[cfg(test)] test_ordered_keys!($( $key, )+); - use $crate::values::{IntoCborKey, KeyType, Value}; - use ::core::cmp::Ordering; - use ::core::iter::Peekable; - use ::alloc::collections::btree_map::IntoIter; + use $crate::values::{IntoCborKey, Value}; + use $crate::macros::read_cbor_map_peek_value; - let mut it: Peekable> = $map.into_iter().peekable(); + let mut it = $map.into_iter().peekable(); $( - let $variable: Option = { - let needle: KeyType = $key.into_cbor_key(); - loop { - match it.peek() { - None => break None, - Some(item) => { - let key: &KeyType = &item.0; - match key.cmp(&needle) { - Ordering::Less => { - it.next(); - continue - }, - Ordering::Equal => { - let value: Value = it.next().unwrap().1; - break Some(value) - }, - Ordering::Greater => break None, - } - } - } - } - }; + let $variable: Option = read_cbor_map_peek_value(&mut it, $key.into_cbor_key()); )+ }; } +/// This function is an internal detail of the `read_cbor_map!` macro, but has public visibility so +/// that users of the macro can use it. +/// +/// The logic is separated into its own function to reduce binary size, as otherwise the logic +/// would be inlined for every use case. As of June 2020, this saves ~40KB of binary size for the +/// CTAP2 application of OpenSK. +pub fn read_cbor_map_peek_value( + it: &mut Peekable>, + needle: KeyType, +) -> Option { + loop { + match it.peek() { + None => return None, + Some(item) => { + let key: &KeyType = &item.0; + match key.cmp(&needle) { + Ordering::Less => { + it.next(); + continue; + } + Ordering::Equal => { + let value: Value = it.next().unwrap().1; + return Some(value); + } + Ordering::Greater => return None, + } + } + } + } +} + #[macro_export] macro_rules! test_ordered_keys { // Last key From b0321f6b4ffa55f180300ffe1ce11a6502d06cb4 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Tue, 9 Jun 2020 17:51:46 +0200 Subject: [PATCH 18/24] Migrate PublicKeyCredentialSource to read_cbor_map. I didn't realize that the values were actually constants, as discriminants of an enum. --- src/ctap/data_formats.rs | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index b34a709..114e0d6 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -530,27 +530,32 @@ impl TryFrom for PublicKeyCredentialSource { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - use PublicKeyCredentialSourceField::*; - let mut map = extract_map(cbor_value)?; - let credential_id = extract_byte_string(ok_or_missing(map.remove(&CredentialId.into()))?)?; - let private_key = extract_byte_string(ok_or_missing(map.remove(&PrivateKey.into()))?)?; + use PublicKeyCredentialSourceField::{ + CredProtectPolicy, CredRandom, CredentialId, OtherUi, PrivateKey, RpId, UserHandle, + }; + read_cbor_map! { + extract_map(cbor_value)?, + credential_id @ CredentialId, + private_key @ PrivateKey, + rp_id @ RpId, + user_handle @ UserHandle, + other_ui @ OtherUi, + cred_random @ CredRandom, + cred_protect_policy @ CredProtectPolicy, + }; + + let credential_id = extract_byte_string(ok_or_missing(credential_id)?)?; + let private_key = extract_byte_string(ok_or_missing(private_key)?)?; if private_key.len() != 32 { return Err(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR); } let private_key = ecdsa::SecKey::from_bytes(array_ref!(private_key, 0, 32)) .ok_or(Ctap2StatusCode::CTAP2_ERR_INVALID_CBOR)?; - let rp_id = extract_text_string(ok_or_missing(map.remove(&RpId.into()))?)?; - let user_handle = extract_byte_string(ok_or_missing(map.remove(&UserHandle.into()))?)?; - let other_ui = map - .remove(&OtherUi.into()) - .map(extract_text_string) - .transpose()?; - let cred_random = map - .remove(&CredRandom.into()) - .map(extract_byte_string) - .transpose()?; - let cred_protect_policy = map - .remove(&CredProtectPolicy.into()) + let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; + let user_handle = extract_byte_string(ok_or_missing(user_handle)?)?; + let other_ui = other_ui.map(extract_text_string).transpose()?; + let cred_random = cred_random.map(extract_byte_string).transpose()?; + let cred_protect_policy = cred_protect_policy .map(CredentialProtectionPolicy::try_from) .transpose()?; // We don't return whether there were unknown fields in the CBOR value. This means that From 493efa9b2588bdabeac236a82984de70c34e10be Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Mon, 15 Jun 2020 16:55:07 +0200 Subject: [PATCH 19/24] Apply syntax suggestion to read_cbor_map! macro. --- libraries/cbor/src/macros.rs | 46 ++++++++------- src/ctap/command.rs | 53 +++++++++--------- src/ctap/data_formats.rs | 105 +++++++++++++++++++---------------- 3 files changed, 111 insertions(+), 93 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 29d76b1..d8dc860 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -44,9 +44,10 @@ use core::iter::Peekable; /// # fn main() { /// # let map = alloc::collections::BTreeMap::new(); /// read_cbor_map! { -/// map, -/// x @ 1, -/// y @ 2, +/// let { +/// 1 => x, +/// 2 => y, +/// } = map; /// }; /// # } /// ``` @@ -64,7 +65,7 @@ use core::iter::Peekable; /// ``` #[macro_export] macro_rules! read_cbor_map { - ( $map:expr, $( $variable:ident @ $key:expr, )+ ) => { + ( let { $( $key:expr => $variable:ident, )+ } = $map:expr; ) => { // A pre-requisite for this algorithm to work is that the keys to extract from the map are // sorted. #[cfg(test)] @@ -98,7 +99,6 @@ pub fn read_cbor_map_peek_value( match key.cmp(&needle) { Ordering::Less => { it.next(); - continue; } Ordering::Equal => { let value: Value = it.next().unwrap().1; @@ -634,9 +634,10 @@ mod test { }; read_cbor_map! { - extract_map(map), - x1 @ 1, - x2 @ 2, + let { + 1 => x1, + 2 => x2, + } = extract_map(map); }; assert_eq!(x1, Some(cbor_unsigned!(10))); @@ -652,9 +653,10 @@ mod test { }; read_cbor_map! { - extract_map(map), - _x2 @ 2, - _x1 @ 1, + let { + 2 => _x2, + 1 => _x1, + } = extract_map(map); }; } @@ -673,9 +675,10 @@ mod test { }; read_cbor_map! { - extract_map(map), - x3 @ 3, - x7 @ 7, + let { + 3 => x3, + 7 => x7, + } = extract_map(map); }; assert_eq!(x3, Some(cbor_unsigned!(30))); @@ -691,13 +694,14 @@ mod test { }; read_cbor_map! { - extract_map(map), - x0 @ 0, - x1 @ 1, - x2 @ 2, - x3 @ 3, - x4 @ 4, - x5 @ 5, + let { + 0 => x0, + 1 => x1, + 2 => x2, + 3 => x3, + 4 => x4, + 5 => x5, + } = extract_map(map); }; assert_eq!(x0, None); diff --git a/src/ctap/command.rs b/src/ctap/command.rs index 7307c40..653e6da 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -125,16 +125,17 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - client_data_hash @ 1, - rp @ 2, - user @ 3, - cred_param_vec @ 4, - exclude_list @ 5, - extensions @ 6, - options @ 7, - pin_uv_auth_param @ 8, - pin_uv_auth_protocol @ 9, + let { + 1 => client_data_hash, + 2 => rp, + 3 => user, + 4 => cred_param_vec, + 5 => exclude_list, + 6 => extensions, + 7 => options, + 8 => pin_uv_auth_param, + 9 => pin_uv_auth_protocol, + } = extract_map(cbor_value)?; }; let client_data_hash = extract_byte_string(ok_or_missing(client_data_hash)?)?; @@ -207,14 +208,15 @@ impl TryFrom for AuthenticatorGetAssertionParameters { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - rp_id @ 1, - client_data_hash @ 2, - allow_list @ 3, - extensions @ 4, - options @ 5, - pin_uv_auth_param @ 6, - pin_uv_auth_protocol @ 7, + let { + 1 => rp_id, + 2 => client_data_hash, + 3 => allow_list, + 4 => extensions, + 5 => options, + 6 => pin_uv_auth_param, + 7 => pin_uv_auth_protocol, + } = extract_map(cbor_value)?; }; let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; @@ -276,13 +278,14 @@ impl TryFrom for AuthenticatorClientPinParameters { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - pin_protocol @ 1, - sub_command @ 2, - key_agreement @ 3, - pin_auth @ 4, - new_pin_enc @ 5, - pin_hash_enc @ 6, + let { + 1 => pin_protocol, + 2 => sub_command, + 3 => key_agreement, + 4 => pin_auth, + 5 => new_pin_enc, + 6 => pin_hash_enc, + } = extract_map(cbor_value)?; }; let pin_protocol = extract_unsigned(ok_or_missing(pin_protocol)?)?; diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index 114e0d6..942abc7 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -32,10 +32,11 @@ impl TryFrom for PublicKeyCredentialRpEntity { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - rp_id @ "id", - rp_icon @ "icon", - rp_name @ "name", + let { + "id" => rp_id, + "icon" => rp_icon, + "name" => rp_name, + } = extract_map(cbor_value)?; }; let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; @@ -64,11 +65,12 @@ impl TryFrom for PublicKeyCredentialUserEntity { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - user_id @ "id", - user_icon @ "icon", - user_name @ "name", - user_display_name @ "displayName", + let { + "id" => user_id, + "icon" => user_icon, + "name" => user_name, + "displayName" => user_display_name, + } = extract_map(cbor_value)?; }; let user_id = extract_byte_string(ok_or_missing(user_id)?)?; @@ -142,9 +144,10 @@ impl TryFrom for PublicKeyCredentialParameter { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - alg @ "alg", - cred_type @ "type", + let { + "alg" => alg, + "type" => cred_type, + } = extract_map(cbor_value)?; }; let cred_type = PublicKeyCredentialType::try_from(ok_or_missing(cred_type)?)?; @@ -211,10 +214,11 @@ impl TryFrom for PublicKeyCredentialDescriptor { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - key_id @ "id", - key_type @ "type", - transports @ "transports", + let { + "id" => key_id, + "type" => key_type, + "transports" => transports, + } = extract_map(cbor_value)?; }; let key_type = PublicKeyCredentialType::try_from(ok_or_missing(key_type)?)?; @@ -260,9 +264,10 @@ impl TryFrom for MakeCredentialExtensions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - cred_protect @ "credProtect", - hmac_secret @ "hmac-secret", + let { + "credProtect" => cred_protect, + "hmac-secret" => hmac_secret, + } = extract_map(cbor_value)?; }; let hmac_secret = hmac_secret.map_or(Ok(false), extract_bool)?; @@ -286,8 +291,9 @@ impl TryFrom for GetAssertionExtensions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - hmac_secret @ "hmac-secret", + let { + "hmac-secret" => hmac_secret, + } = extract_map(cbor_value)?; }; let hmac_secret = hmac_secret @@ -309,10 +315,11 @@ impl TryFrom for GetAssertionHmacSecretInput { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - cose_key @ 1, - salt_enc @ 2, - salt_auth @ 3, + let { + 1 => cose_key, + 2 => salt_enc, + 3 => salt_auth, + } = extract_map(cbor_value)?; }; let cose_key = extract_map(ok_or_missing(cose_key)?)?; @@ -338,10 +345,11 @@ impl TryFrom for MakeCredentialOptions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - rk @ "rk", - up @ "up", - uv @ "uv", + let { + "rk" => rk, + "up" => up, + "uv" => uv, + } = extract_map(cbor_value)?; }; let rk = match rk { @@ -372,10 +380,11 @@ impl TryFrom for GetAssertionOptions { fn try_from(cbor_value: cbor::Value) -> Result { read_cbor_map! { - extract_map(cbor_value)?, - rk @ "rk", - up @ "up", - uv @ "uv", + let { + "rk" => rk, + "up" => up, + "uv" => uv, + } = extract_map(cbor_value)?; }; if let Some(options_entry) = rk { @@ -534,14 +543,15 @@ impl TryFrom for PublicKeyCredentialSource { CredProtectPolicy, CredRandom, CredentialId, OtherUi, PrivateKey, RpId, UserHandle, }; read_cbor_map! { - extract_map(cbor_value)?, - credential_id @ CredentialId, - private_key @ PrivateKey, - rp_id @ RpId, - user_handle @ UserHandle, - other_ui @ OtherUi, - cred_random @ CredRandom, - cred_protect_policy @ CredProtectPolicy, + let { + CredentialId => credential_id, + PrivateKey => private_key, + RpId => rp_id, + UserHandle => user_handle, + OtherUi => other_ui, + CredRandom => cred_random, + CredProtectPolicy => cred_protect_policy, + } = extract_map(cbor_value)?; }; let credential_id = extract_byte_string(ok_or_missing(credential_id)?)?; @@ -634,12 +644,13 @@ impl TryFrom for ecdh::PubKey { fn try_from(cose_key: CoseKey) -> Result { read_cbor_map! { - cose_key.0, - key_type @ 1, - algorithm @ 3, - curve @ -1, - x_bytes @ -2, - y_bytes @ -3, + let { + 1 => key_type, + 3 => algorithm, + -1 => curve, + -2 => x_bytes, + -3 => y_bytes, + } = cose_key.0; }; let key_type = extract_integer(ok_or_missing(key_type)?)?; From 2589eb99b3b3daa1f48e37b742a76f53cccad9e6 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Mon, 15 Jun 2020 17:00:19 +0200 Subject: [PATCH 20/24] Update read_cbor_map example to use a text key as well. --- libraries/cbor/src/macros.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index d8dc860..9cf4178 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -46,7 +46,7 @@ use core::iter::Peekable; /// read_cbor_map! { /// let { /// 1 => x, -/// 2 => y, +/// "key" => y, /// } = map; /// }; /// # } @@ -59,8 +59,9 @@ use core::iter::Peekable; /// # /// # fn main() { /// # let mut map = alloc::collections::BTreeMap::::new(); -/// let x: Option = map.remove(&cbor_unsigned!(1)); -/// let y: Option = map.remove(&cbor_unsigned!(2)); +/// use cbor::values::IntoCborKey; +/// let x: Option = map.remove(&1.into_cbor_key()); +/// let y: Option = map.remove(&"key".into_cbor_key()); /// # } /// ``` #[macro_export] From db70c3e66dfe501dc07a45fadbe9d767af60f665 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Fri, 19 Jun 2020 11:14:42 +0200 Subject: [PATCH 21/24] s/read_cbor_map/destructure_cbor_map/g --- libraries/cbor/src/macros.rs | 48 ++++++++++++++++++------------------ src/ctap/command.rs | 6 ++--- src/ctap/data_formats.rs | 22 ++++++++--------- 3 files changed, 38 insertions(+), 38 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 9cf4178..0fe6955 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -24,16 +24,16 @@ use core::iter::Peekable; /// that assigns the corresponding values to new variables using the given identifiers. Each of /// these variables has type `Option`, to account for the case where keys aren't found. /// -/// **Important:** Keys passed to the `read_cbor_map!` macro **must be sorted** in increasing order. -/// If not, the algorithm can yield incorrect results, such a assigning `None` to a variable even if -/// the corresponding key existed in the map. **No runtime checks** are made for this in the -/// `read_cbor_map!` macro, in order to avoid overhead at runtime. However, assertions that keys are -/// sorted are added in `cfg(test)` mode, so that unit tests can verify ahead of time that the keys -/// are indeed sorted. This macro is therefore **not suitable for dynamic keys** that can change at -/// runtime. +/// **Important:** Keys passed to the `destructure_cbor_map!` macro **must be sorted** in increasing +/// order. If not, the algorithm can yield incorrect results, such a assigning `None` to a variable +/// even if the corresponding key existed in the map. **No runtime checks** are made for this in the +/// `destructure_cbor_map!` macro, in order to avoid overhead at runtime. However, assertions that +/// keys are sorted are added in `cfg(test)` mode, so that unit tests can verify ahead of time that +/// the keys are indeed sorted. This macro is therefore **not suitable for dynamic keys** that can +/// change at runtime. /// /// Semantically, provided that the keys are sorted as specified above, the following two snippets -/// of code are equivalent, but the `read_cbor_map!` version is more optimized, as it doesn't +/// of code are equivalent, but the `destructure_cbor_map!` version is more optimized, as it doesn't /// re-balance the `BTreeMap` for each key, contrary to the `BTreeMap::remove` operations. /// /// ```rust @@ -43,7 +43,7 @@ use core::iter::Peekable; /// # /// # fn main() { /// # let map = alloc::collections::BTreeMap::new(); -/// read_cbor_map! { +/// destructure_cbor_map! { /// let { /// 1 => x, /// "key" => y, @@ -65,7 +65,7 @@ use core::iter::Peekable; /// # } /// ``` #[macro_export] -macro_rules! read_cbor_map { +macro_rules! destructure_cbor_map { ( let { $( $key:expr => $variable:ident, )+ } = $map:expr; ) => { // A pre-requisite for this algorithm to work is that the keys to extract from the map are // sorted. @@ -73,22 +73,22 @@ macro_rules! read_cbor_map { test_ordered_keys!($( $key, )+); use $crate::values::{IntoCborKey, Value}; - use $crate::macros::read_cbor_map_peek_value; + use $crate::macros::destructure_cbor_map_peek_value; let mut it = $map.into_iter().peekable(); $( - let $variable: Option = read_cbor_map_peek_value(&mut it, $key.into_cbor_key()); + let $variable: Option = destructure_cbor_map_peek_value(&mut it, $key.into_cbor_key()); )+ }; } -/// This function is an internal detail of the `read_cbor_map!` macro, but has public visibility so -/// that users of the macro can use it. +/// This function is an internal detail of the `destructure_cbor_map!` macro, but has public +/// visibility so that users of the macro can use it. /// /// The logic is separated into its own function to reduce binary size, as otherwise the logic /// would be inlined for every use case. As of June 2020, this saves ~40KB of binary size for the /// CTAP2 application of OpenSK. -pub fn read_cbor_map_peek_value( +pub fn destructure_cbor_map_peek_value( it: &mut Peekable>, needle: KeyType, ) -> Option { @@ -125,7 +125,7 @@ macro_rules! test_ordered_keys { let k2: KeyType = $key2.into_cbor_key(); assert!( k1 < k2, - "{:?} < {:?} failed. The read_cbor_map! macro requires keys in sorted order.", + "{:?} < {:?} failed. The destructure_cbor_map! macro requires keys in sorted order.", k1, k2, ); @@ -628,13 +628,13 @@ mod test { } #[test] - fn test_read_cbor_map_simple() { + fn test_destructure_cbor_map_simple() { let map = cbor_map! { 1 => 10, 2 => 20, }; - read_cbor_map! { + destructure_cbor_map! { let { 1 => x1, 2 => x2, @@ -647,13 +647,13 @@ mod test { #[test] #[should_panic] - fn test_read_cbor_map_unordered() { + fn test_destructure_cbor_map_unordered() { let map = cbor_map! { 1 => 10, 2 => 20, }; - read_cbor_map! { + destructure_cbor_map! { let { 2 => _x2, 1 => _x1, @@ -662,7 +662,7 @@ mod test { } #[test] - fn test_read_cbor_map_partial() { + fn test_destructure_cbor_map_partial() { let map = cbor_map! { 1 => 10, 2 => 20, @@ -675,7 +675,7 @@ mod test { 9 => 90, }; - read_cbor_map! { + destructure_cbor_map! { let { 3 => x3, 7 => x7, @@ -687,14 +687,14 @@ mod test { } #[test] - fn test_read_cbor_map_missing() { + fn test_destructure_cbor_map_missing() { let map = cbor_map! { 1 => 10, 3 => 30, 4 => 40, }; - read_cbor_map! { + destructure_cbor_map! { let { 0 => x0, 1 => x1, diff --git a/src/ctap/command.rs b/src/ctap/command.rs index 653e6da..d993704 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -124,7 +124,7 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { 1 => client_data_hash, 2 => rp, @@ -207,7 +207,7 @@ impl TryFrom for AuthenticatorGetAssertionParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { 1 => rp_id, 2 => client_data_hash, @@ -277,7 +277,7 @@ impl TryFrom for AuthenticatorClientPinParameters { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { 1 => pin_protocol, 2 => sub_command, diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index 942abc7..e21e859 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -31,7 +31,7 @@ impl TryFrom for PublicKeyCredentialRpEntity { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "id" => rp_id, "icon" => rp_icon, @@ -64,7 +64,7 @@ impl TryFrom for PublicKeyCredentialUserEntity { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "id" => user_id, "icon" => user_icon, @@ -143,7 +143,7 @@ impl TryFrom for PublicKeyCredentialParameter { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "alg" => alg, "type" => cred_type, @@ -213,7 +213,7 @@ impl TryFrom for PublicKeyCredentialDescriptor { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "id" => key_id, "type" => key_type, @@ -263,7 +263,7 @@ impl TryFrom for MakeCredentialExtensions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "credProtect" => cred_protect, "hmac-secret" => hmac_secret, @@ -290,7 +290,7 @@ impl TryFrom for GetAssertionExtensions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "hmac-secret" => hmac_secret, } = extract_map(cbor_value)?; @@ -314,7 +314,7 @@ impl TryFrom for GetAssertionHmacSecretInput { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { 1 => cose_key, 2 => salt_enc, @@ -344,7 +344,7 @@ impl TryFrom for MakeCredentialOptions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "rk" => rk, "up" => up, @@ -379,7 +379,7 @@ impl TryFrom for GetAssertionOptions { type Error = Ctap2StatusCode; fn try_from(cbor_value: cbor::Value) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { "rk" => rk, "up" => up, @@ -542,7 +542,7 @@ impl TryFrom for PublicKeyCredentialSource { use PublicKeyCredentialSourceField::{ CredProtectPolicy, CredRandom, CredentialId, OtherUi, PrivateKey, RpId, UserHandle, }; - read_cbor_map! { + destructure_cbor_map! { let { CredentialId => credential_id, PrivateKey => private_key, @@ -643,7 +643,7 @@ impl TryFrom for ecdh::PubKey { type Error = Ctap2StatusCode; fn try_from(cose_key: CoseKey) -> Result { - read_cbor_map! { + destructure_cbor_map! { let { 1 => key_type, 3 => algorithm, From 240ba7580d734c26f43f06c09037e3d331df6e39 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Fri, 19 Jun 2020 11:59:23 +0200 Subject: [PATCH 22/24] Improve comments. --- libraries/cbor/src/macros.rs | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 0fe6955..1bc37e2 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -68,13 +68,22 @@ use core::iter::Peekable; macro_rules! destructure_cbor_map { ( let { $( $key:expr => $variable:ident, )+ } = $map:expr; ) => { // A pre-requisite for this algorithm to work is that the keys to extract from the map are - // sorted. + // sorted - the behavior is unspecified if the keys are not sorted. + // Therefore, in test mode we add assertions that the keys are indeed sorted. #[cfg(test)] - test_ordered_keys!($( $key, )+); + assert_sorted_keys!($( $key, )+); use $crate::values::{IntoCborKey, Value}; use $crate::macros::destructure_cbor_map_peek_value; + // This algorithm first converts the map into a peekable iterator - whose items are sorted + // in strictly increasing order of keys. Then, the repeated calls to the "peek value" + // helper function will consume this iterator and yield values (or `None`) when reaching + // the keys to extract. + // + // This is where the pre-requisite that keys to extract are sorted is important: the + // algorithm does a single linear scan over the iterator and therefore keys to extract have + // to come in the same order (i.e. sorted). let mut it = $map.into_iter().peekable(); $( let $variable: Option = destructure_cbor_map_peek_value(&mut it, $key.into_cbor_key()); @@ -85,6 +94,11 @@ macro_rules! destructure_cbor_map { /// This function is an internal detail of the `destructure_cbor_map!` macro, but has public /// visibility so that users of the macro can use it. /// +/// Given a peekable iterator of key-value pairs sorted in strictly increasing key order and a +/// needle key, this function consumes all items whose key compares less than or equal to the +/// needle, and returns `Some(value)` if the needle was present as the key in the iterator and +/// `None` otherwise. +/// /// The logic is separated into its own function to reduce binary size, as otherwise the logic /// would be inlined for every use case. As of June 2020, this saves ~40KB of binary size for the /// CTAP2 application of OpenSK. @@ -113,7 +127,7 @@ pub fn destructure_cbor_map_peek_value( } #[macro_export] -macro_rules! test_ordered_keys { +macro_rules! assert_sorted_keys { // Last key ( $key:expr, ) => { }; @@ -130,7 +144,7 @@ macro_rules! test_ordered_keys { k2, ); } - test_ordered_keys!($key2, $( $keys, )*); + assert_sorted_keys!($key2, $( $keys, )*); }; } @@ -647,13 +661,15 @@ mod test { #[test] #[should_panic] - fn test_destructure_cbor_map_unordered() { + fn test_destructure_cbor_map_unsorted() { let map = cbor_map! { 1 => 10, 2 => 20, }; destructure_cbor_map! { + // The keys are not sorted here, which violates the precondition of + // destructure_cbor_map. An assertion should catch that and make the test panic. let { 2 => _x2, 1 => _x1, From 09c9fb3a3e5bef0f6df2a6228d8bc716a33ce188 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Mon, 22 Jun 2020 10:43:36 +0200 Subject: [PATCH 23/24] Apply suggestion to remove additional semi-colons. --- libraries/cbor/src/macros.rs | 10 +++++----- src/ctap/command.rs | 6 +++--- src/ctap/data_formats.rs | 22 +++++++++++----------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/libraries/cbor/src/macros.rs b/libraries/cbor/src/macros.rs index 1bc37e2..d96354e 100644 --- a/libraries/cbor/src/macros.rs +++ b/libraries/cbor/src/macros.rs @@ -48,7 +48,7 @@ use core::iter::Peekable; /// 1 => x, /// "key" => y, /// } = map; -/// }; +/// } /// # } /// ``` /// @@ -653,7 +653,7 @@ mod test { 1 => x1, 2 => x2, } = extract_map(map); - }; + } assert_eq!(x1, Some(cbor_unsigned!(10))); assert_eq!(x2, Some(cbor_unsigned!(20))); @@ -674,7 +674,7 @@ mod test { 2 => _x2, 1 => _x1, } = extract_map(map); - }; + } } #[test] @@ -696,7 +696,7 @@ mod test { 3 => x3, 7 => x7, } = extract_map(map); - }; + } assert_eq!(x3, Some(cbor_unsigned!(30))); assert_eq!(x7, Some(cbor_unsigned!(70))); @@ -719,7 +719,7 @@ mod test { 4 => x4, 5 => x5, } = extract_map(map); - }; + } assert_eq!(x0, None); assert_eq!(x1, Some(cbor_unsigned!(10))); diff --git a/src/ctap/command.rs b/src/ctap/command.rs index d993704..9f0e20b 100644 --- a/src/ctap/command.rs +++ b/src/ctap/command.rs @@ -136,7 +136,7 @@ impl TryFrom for AuthenticatorMakeCredentialParameters { 8 => pin_uv_auth_param, 9 => pin_uv_auth_protocol, } = extract_map(cbor_value)?; - }; + } let client_data_hash = extract_byte_string(ok_or_missing(client_data_hash)?)?; let rp = PublicKeyCredentialRpEntity::try_from(ok_or_missing(rp)?)?; @@ -217,7 +217,7 @@ impl TryFrom for AuthenticatorGetAssertionParameters { 6 => pin_uv_auth_param, 7 => pin_uv_auth_protocol, } = extract_map(cbor_value)?; - }; + } let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; let client_data_hash = extract_byte_string(ok_or_missing(client_data_hash)?)?; @@ -286,7 +286,7 @@ impl TryFrom for AuthenticatorClientPinParameters { 5 => new_pin_enc, 6 => pin_hash_enc, } = extract_map(cbor_value)?; - }; + } let pin_protocol = extract_unsigned(ok_or_missing(pin_protocol)?)?; let sub_command = ClientPinSubCommand::try_from(ok_or_missing(sub_command)?)?; diff --git a/src/ctap/data_formats.rs b/src/ctap/data_formats.rs index e21e859..b5799b4 100644 --- a/src/ctap/data_formats.rs +++ b/src/ctap/data_formats.rs @@ -37,7 +37,7 @@ impl TryFrom for PublicKeyCredentialRpEntity { "icon" => rp_icon, "name" => rp_name, } = extract_map(cbor_value)?; - }; + } let rp_id = extract_text_string(ok_or_missing(rp_id)?)?; let rp_name = rp_name.map(extract_text_string).transpose()?; @@ -71,7 +71,7 @@ impl TryFrom for PublicKeyCredentialUserEntity { "name" => user_name, "displayName" => user_display_name, } = extract_map(cbor_value)?; - }; + } let user_id = extract_byte_string(ok_or_missing(user_id)?)?; let user_name = user_name.map(extract_text_string).transpose()?; @@ -148,7 +148,7 @@ impl TryFrom for PublicKeyCredentialParameter { "alg" => alg, "type" => cred_type, } = extract_map(cbor_value)?; - }; + } let cred_type = PublicKeyCredentialType::try_from(ok_or_missing(cred_type)?)?; let alg = SignatureAlgorithm::try_from(ok_or_missing(alg)?)?; @@ -219,7 +219,7 @@ impl TryFrom for PublicKeyCredentialDescriptor { "type" => key_type, "transports" => transports, } = extract_map(cbor_value)?; - }; + } let key_type = PublicKeyCredentialType::try_from(ok_or_missing(key_type)?)?; let key_id = extract_byte_string(ok_or_missing(key_id)?)?; @@ -268,7 +268,7 @@ impl TryFrom for MakeCredentialExtensions { "credProtect" => cred_protect, "hmac-secret" => hmac_secret, } = extract_map(cbor_value)?; - }; + } let hmac_secret = hmac_secret.map_or(Ok(false), extract_bool)?; let cred_protect = cred_protect @@ -294,7 +294,7 @@ impl TryFrom for GetAssertionExtensions { let { "hmac-secret" => hmac_secret, } = extract_map(cbor_value)?; - }; + } let hmac_secret = hmac_secret .map(GetAssertionHmacSecretInput::try_from) @@ -320,7 +320,7 @@ impl TryFrom for GetAssertionHmacSecretInput { 2 => salt_enc, 3 => salt_auth, } = extract_map(cbor_value)?; - }; + } let cose_key = extract_map(ok_or_missing(cose_key)?)?; let salt_enc = extract_byte_string(ok_or_missing(salt_enc)?)?; @@ -350,7 +350,7 @@ impl TryFrom for MakeCredentialOptions { "up" => up, "uv" => uv, } = extract_map(cbor_value)?; - }; + } let rk = match rk { Some(options_entry) => extract_bool(options_entry)?, @@ -385,7 +385,7 @@ impl TryFrom for GetAssertionOptions { "up" => up, "uv" => uv, } = extract_map(cbor_value)?; - }; + } if let Some(options_entry) = rk { // This is only for returning the correct status code. @@ -552,7 +552,7 @@ impl TryFrom for PublicKeyCredentialSource { CredRandom => cred_random, CredProtectPolicy => cred_protect_policy, } = extract_map(cbor_value)?; - }; + } let credential_id = extract_byte_string(ok_or_missing(credential_id)?)?; let private_key = extract_byte_string(ok_or_missing(private_key)?)?; @@ -651,7 +651,7 @@ impl TryFrom for ecdh::PubKey { -2 => x_bytes, -3 => y_bytes, } = cose_key.0; - }; + } let key_type = extract_integer(ok_or_missing(key_type)?)?; if key_type != EC2_KEY_TYPE { From ce5767efec94517d4a49b8af8bba520de0422d77 Mon Sep 17 00:00:00 2001 From: Guillaume Endignoux Date: Mon, 22 Jun 2020 11:57:37 +0200 Subject: [PATCH 24/24] Update reference binaries. --- .../reference_binaries_macos-10.15.sha256sum | 10 +++++----- .../reference_binaries_ubuntu-18.04.sha256sum | 10 +++++----- reproducible/reference_elf2tab_macos-10.15.txt | 16 ++++++++-------- reproducible/reference_elf2tab_ubuntu-18.04.txt | 16 ++++++++-------- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/reproducible/reference_binaries_macos-10.15.sha256sum b/reproducible/reference_binaries_macos-10.15.sha256sum index ab2e9a3..83e63ba 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ 0b54df6d548849e24d67b9b022ca09cb33c51f078ce85d0c9c4635ffc69902e1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -f49e2205136159671f8291b284fc02300cf659f088a2ca301d74111e0e96849a target/nrf52840dk_merged.hex +e93f56b4b6bb602ab37cf967f1c3fd3d253e05ccc85d4718762f68216c35d68c target/nrf52840dk_merged.hex 052eec0ae526038352b9f7573468d0cf7fb5ec331d4dc1a2df75fdbd514ea5ca third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -b35ac62a490c62d4b23dddf1d8e6946badb32b5b35b40bbd75587815530094c9 target/nrf52840_dongle_merged.hex +8cff9a4d513be338ba6a3fd91d3d4cfdd63bc066e8bf9dc22f64176114da08b8 target/nrf52840_dongle_merged.hex 908d7f4f40936d968b91ab6e19b2406612fe8c2c273d9c0b71ef1f55116780e0 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -1adb9f71697947109020b25ad2b3fb3b03e6a07945dee14351ad67341241205e target/nrf52840_dongle_dfu_merged.hex +94452673fb0022a07ac886d4ab74576f067c2d727aed30ed368f4e5af382238f target/nrf52840_dongle_dfu_merged.hex 34ecbecaebf1188277f2310fe769c8c60310d8576493242712854deb4ba1036e third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -1661fb4da7cbaf01529e593600f47c4613446a37f400cb0b238249d100a3d9f1 target/nrf52840_mdk_dfu_merged.hex -529ac9aef3941b45e7e480810ae4e821da433985b149028aa6a33f33e0dc1685 target/tab/ctap2.tab +414aaf7fcc3a0121ab02b1222d508ae503e268cb7da0df5795a6d6a01aeed345 target/nrf52840_mdk_dfu_merged.hex +212698e7c7919fa4542e1263d56f601632902f86bdf3d48cf6300b96ad452cb1 target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index 5e3e757..9f5f433 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ 29382e72d0f3c6a72ce9517211952ff29ea270193d7f0ddc48ca69009ee29925 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -e446a94d67f77d5346be6e476641f4ff50561f5a77bfa8bc49262f89e7399893 target/nrf52840dk_merged.hex +4d5165d8ff46148a585ade23d3030c8a95928a158d283ccd7c93e14902452b6f target/nrf52840dk_merged.hex 30f239390ae9bef0825731e4c82d40470fc5e9bded2bf0d942e92dbb5d4faba1 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -1bf5219f7b096b4ade330e9b02544b09d10972ddf253c7fdfbd6241b03e98f31 target/nrf52840_dongle_merged.hex +8204a87c9e93909ed79907f2d7b655d07397161ecd64bd213bc483630a38e8c9 target/nrf52840_dongle_merged.hex e3acf15d5ae3a22aecff6cc58db5fc311f538f47328d348b7ad7db7f9ab5e72c third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -b83edda1b2588e3eff019fc8b2e16097e159f8a43fa5fc62a6e23497882c8dca target/nrf52840_dongle_dfu_merged.hex +b937eaeea7ae9ca3c26bee082cb5af596942947c84171cb4d03cc66bc31d35da target/nrf52840_dongle_dfu_merged.hex cae312a26a513ada6c198fdc59b2bba3860c51726b817a9fd17a4331ee12c882 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -d376cb19e672ab80b9dd25e9df40af7ac833d03ede32f4a2ae21fdfd4e31d365 target/nrf52840_mdk_dfu_merged.hex -ba0e11a0036f167a56864de43db3602a8a855b38be8a53afc3a97fcaa40f2201 target/tab/ctap2.tab +6d125877a207744a73b0b315152188a85329d31e8f85e8205ac6033e46056931 target/nrf52840_mdk_dfu_merged.hex +e6dbbc68daa1b5269dce5ddbc91ea00169f9c8ed8d94a574dac1524e63c21b18 target/tab/ctap2.tab diff --git a/reproducible/reference_elf2tab_macos-10.15.txt b/reproducible/reference_elf2tab_macos-10.15.txt index e701412..dd0b0b2 100644 --- a/reproducible/reference_elf2tab_macos-10.15.txt +++ b/reproducible/reference_elf2tab_macos-10.15.txt @@ -5,8 +5,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. - Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179204 (0x2bc04) bytes. + Adding .stack section. Offset: 179332 (0x2bc84). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -24,8 +24,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. - Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179204 (0x2bc04) bytes. + Adding .stack section. Offset: 179332 (0x2bc84). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -43,8 +43,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. - Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179204 (0x2bc04) bytes. + Adding .stack section. Offset: 179332 (0x2bc84). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -62,8 +62,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171876 (0x29f64) bytes. - Adding .stack section. Offset: 172004 (0x29fe4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179204 (0x2bc04) bytes. + Adding .stack section. Offset: 179332 (0x2bc84). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 diff --git a/reproducible/reference_elf2tab_ubuntu-18.04.txt b/reproducible/reference_elf2tab_ubuntu-18.04.txt index 4810644..6b3b7a2 100644 --- a/reproducible/reference_elf2tab_ubuntu-18.04.txt +++ b/reproducible/reference_elf2tab_ubuntu-18.04.txt @@ -5,8 +5,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. - Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179236 (0x2bc24) bytes. + Adding .stack section. Offset: 179364 (0x2bca4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -24,8 +24,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. - Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179236 (0x2bc24) bytes. + Adding .stack section. Offset: 179364 (0x2bca4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -43,8 +43,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. - Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179236 (0x2bc24) bytes. + Adding .stack section. Offset: 179364 (0x2bca4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -62,8 +62,8 @@ Min RAM size from sections in ELF: 16 bytes Number of writeable flash regions: 0 Adding .crt0_header section. Offset: 64 (0x40). Length: 64 (0x40) bytes. Entry point is in .text section - Adding .text section. Offset: 128 (0x80). Length: 171316 (0x29d34) bytes. - Adding .stack section. Offset: 171444 (0x29db4). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 179236 (0x2bc24) bytes. + Adding .stack section. Offset: 179364 (0x2bca4). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2