From 3a42ab15ae92364b8b8e3fce830d4ce7466e16f3 Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Fri, 25 Sep 2020 19:03:45 +0000 Subject: [PATCH 1/6] Added fuzzing helper library to increase code reusability and refactored first fuzz target --- fuzz/fuzz_helper/Cargo.toml | 14 ++ fuzz/fuzz_helper/src/lib.rs | 178 ++++++++++++++++++ .../fuzz_target_split_assemble.rs | 50 +---- 3 files changed, 195 insertions(+), 47 deletions(-) create mode 100644 fuzz/fuzz_helper/Cargo.toml create mode 100644 fuzz/fuzz_helper/src/lib.rs diff --git a/fuzz/fuzz_helper/Cargo.toml b/fuzz/fuzz_helper/Cargo.toml new file mode 100644 index 00000000..3b70f43f --- /dev/null +++ b/fuzz/fuzz_helper/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "fuzz_helper" +version = "0.1.0" +authors = ["Mingxiao Guo "] +license = "Apache-2.0" +edition = "2018" + +[dependencies] +arrayref = "0.3.6" +libtock_drivers = { path = "../../third_party/libtock-drivers" } +crypto = { path = "../../libraries/crypto", features = ['std'] } +cbor = { path = "../../libraries/cbor", features = ['std'] } +ctap2 = { path = "../..", features = ['std', 'ram_storage'] } +lang_items = { path = "../../third_party/lang-items", features = ['std'] } diff --git a/fuzz/fuzz_helper/src/lib.rs b/fuzz/fuzz_helper/src/lib.rs new file mode 100644 index 00000000..53a53759 --- /dev/null +++ b/fuzz/fuzz_helper/src/lib.rs @@ -0,0 +1,178 @@ +// Copyright 2019 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This explicit "extern crate" is needed to make the linker aware of the +// `libtock_alloc_init` symbol. +extern crate lang_items; + +use arrayref::array_ref; +use core::convert::TryFrom; +use crypto::rng256::ThreadRng256; +use ctap2::ctap::command::{ AuthenticatorMakeCredentialParameters, + AuthenticatorGetAssertionParameters, AuthenticatorClientPinParameters}; +use ctap2::ctap::hid::receive::MessageAssembler; +use ctap2::ctap::hid::send::HidPacketIterator; +use ctap2::ctap::hid::{HidPacket, ChannelID, CtapHid, Message}; +use ctap2::ctap::status_code::Ctap2StatusCode; +use ctap2::ctap::CtapState; +use libtock_drivers::timer::{ClockValue, Timestamp}; + +const COMMAND_INIT: u8 = 0x06; +const CHANNEL_BROADCAST: ChannelID = [0xFF, 0xFF, 0xFF, 0xFF]; +const PACKET_TYPE_MASK: u8 = 0x80; + +const CLOCK_FREQUENCY_HZ: usize = 32768; +const DUMMY_TIMESTAMP: Timestamp = Timestamp::from_ms(0); +const DUMMY_CLOCK_VALUE: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ); + +#[derive(Clone, PartialEq)] +pub enum InputType { + CborMakeCredentialParameter, + CborGetAssertionParameter, + CborClientPinParameter, + Ctap1, +} + +// Converts a byte slice into Message +fn raw_to_message(data: &[u8]) -> Message { + if data.len() <= 4 { + let mut cid = [0; 4]; + cid[..data.len()].copy_from_slice(data); + Message { + cid, + cmd: 0, + payload: vec![], + } + } else { + Message { + cid: array_ref!(data, 0, 4).clone(), + cmd: data[4], + payload: data[5..].to_vec(), + } + } +} + +// Returns an initialized ctap state, hid and the allocated cid +// after processing the init command. +fn initialize( + ctap_state: &mut CtapState, + ctap_hid: &mut CtapHid, +) -> ChannelID +where + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, +{ + let nonce = vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0]; + let message = Message { + cid: CHANNEL_BROADCAST, + cmd: COMMAND_INIT, + payload: nonce.clone(), + }; + let mut assembler_reply = MessageAssembler::new(); + let mut result_cid: ChannelID = Default::default(); + for pkt_request in HidPacketIterator::new(message.clone()).unwrap() { + for pkt_reply in ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, ctap_state) { + if let Ok(Some(result)) = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP) { + result_cid.copy_from_slice(&result.payload[8..12]); + } + } + } + result_cid +} + +// Checks whether the given data can be interpreted as the given type. +fn is_type(data: &[u8], input_type: InputType) -> bool { + if input_type.clone() == InputType::Ctap1 { + return true; + } + match cbor::read(data) { + Err(_) => false, + Ok(decoded_cbor) => { + match input_type { + InputType::CborMakeCredentialParameter => { + AuthenticatorMakeCredentialParameters::try_from(decoded_cbor).is_ok() + } + InputType::CborGetAssertionParameter => { + AuthenticatorGetAssertionParameters::try_from(decoded_cbor).is_ok() + } + InputType::CborClientPinParameter => { + AuthenticatorClientPinParameters::try_from(decoded_cbor).is_ok() + } + _ => true + } + } + } +} + +// Interprets the raw data as of the given input type and +// invokes message splitting, assembling and packet processing at CTAP HID level. +pub fn process_input(data: &[u8], input_type: InputType) { + if !is_type(data, input_type.clone()) { + return (); + } + // Initialize ctap state and hid and get the allocated cid. + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + let mut ctap_hid = CtapHid::new(); + let cid = initialize(&mut ctap_state, &mut ctap_hid); + // Wrap input as message with allocated cid and command type. + let mut command = cid.to_vec(); + match input_type { + InputType::CborMakeCredentialParameter => { + command.extend(&[0x10, 0x01]); + } + InputType::CborGetAssertionParameter => { + command.extend(&[0x10, 0x02]); + } + InputType::CborClientPinParameter => { + command.extend(&[0x10, 0x06]); + } + InputType::Ctap1 => { + command.extend(&[0x03]); + } + } + command.extend(data); + // Process message at HID level. + let message = raw_to_message(&command); + if let Some(hid_packet_iterator) = HidPacketIterator::new(message) { + let mut assembler_reply = MessageAssembler::new(); + for pkt_request in hid_packet_iterator { + for pkt_reply in + ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, &mut ctap_state) + { + // Only checks for assembling crashes, not for semantics. + let _ = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP); + } + } + } +} + +// Splits and reassembles the given data as HID packets. +pub fn split_assemble(data: &[u8]) { + let mut message = raw_to_message(data); + if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) { + let mut assembler = MessageAssembler::new(); + let packets: Vec = hid_packet_iterator.collect(); + if let Some((last_packet, first_packets)) = packets.split_last() { + for packet in first_packets { + assert_eq!(assembler.parse_packet(packet, DUMMY_TIMESTAMP), Ok(None)); + } + message.cmd &= !PACKET_TYPE_MASK; + assert_eq!( + assembler.parse_packet(last_packet, DUMMY_TIMESTAMP), + Ok(Some(message)) + ); + } + } +} diff --git a/fuzz/fuzz_targets/fuzz_target_split_assemble.rs b/fuzz/fuzz_targets/fuzz_target_split_assemble.rs index 6dc42f0b..59365645 100644 --- a/fuzz/fuzz_targets/fuzz_target_split_assemble.rs +++ b/fuzz/fuzz_targets/fuzz_target_split_assemble.rs @@ -1,53 +1,9 @@ #![no_main] -// This explicit "extern crate" is needed to make the linker aware of the -// `libtock_alloc_init` symbol. -extern crate lang_items; - -use arrayref::array_ref; -use ctap2::ctap::hid::receive::MessageAssembler; -use ctap2::ctap::hid::send::HidPacketIterator; -use ctap2::ctap::hid::{HidPacket, Message}; +use fuzz_helper::split_assemble; use libfuzzer_sys::fuzz_target; -use libtock_drivers::timer::Timestamp; - -const DUMMY_TIMESTAMP: Timestamp = Timestamp::from_ms(0); -const PACKET_TYPE_MASK: u8 = 0x80; - -// Converts a byte slice into Message -fn raw_to_message(data: &[u8]) -> Message { - if data.len() <= 4 { - let mut cid = [0; 4]; - cid[..data.len()].copy_from_slice(data); - Message { - cid, - cmd: 0, - payload: vec![], - } - } else { - Message { - cid: array_ref!(data, 0, 4).clone(), - cmd: data[4], - payload: data[5..].to_vec(), - } - } -} -/* Fuzzing HID packets splitting and assembling functions*/ +// Fuzzing HID packets splitting and assembling functions. fuzz_target!(|data: &[u8]| { - let mut message = raw_to_message(data); - if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) { - let mut assembler = MessageAssembler::new(); - let packets: Vec = hid_packet_iterator.collect(); - if let Some((last_packet, first_packets)) = packets.split_last() { - for packet in first_packets { - assert_eq!(assembler.parse_packet(packet, DUMMY_TIMESTAMP), Ok(None)); - } - message.cmd &= !PACKET_TYPE_MASK; - assert_eq!( - assembler.parse_packet(last_packet, DUMMY_TIMESTAMP), - Ok(Some(message)) - ); - } - } + split_assemble(data); }); From e8e52ff58a36c84204d37a0c3f510cff4d5e4c87 Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Fri, 25 Sep 2020 19:05:07 +0000 Subject: [PATCH 2/6] Added more fuzz targets --- fuzz/Cargo.toml | 19 +++++++++++++------ .../fuzz_targets/fuzz_target_process_ctap1.rs | 9 +++++++++ ...zz_target_process_ctap2_make_credential.rs | 9 +++++++++ 3 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 fuzz/fuzz_targets/fuzz_target_process_ctap1.rs create mode 100644 fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index d9e42166..9b1a37a4 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -10,17 +10,24 @@ cargo-fuzz = true [dependencies] libfuzzer-sys = { version = "0.3"} -arrayref = "0.3.6" -libtock_drivers = { path = "../third_party/libtock-drivers" } -crypto = { path = "../libraries/crypto", features = ['std'] } -cbor = { path = "../libraries/cbor", features = ['std'] } -ctap2 = { path = "..", features = ['std', 'ram_storage'] } -lang_items = { path = "../third_party/lang-items", features = ['std'] } +fuzz_helper = { path = "fuzz_helper" } # Prevent this from interfering with workspaces [workspace] members = ["."] +[[bin]] +name = "fuzz_target_process_ctap1" +path = "fuzz_targets/fuzz_target_process_ctap1.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_target_process_ctap2_make_credential" +path = "fuzz_targets/fuzz_target_process_ctap2_make_credential.rs" +test = false +doc = false + [[bin]] name = "fuzz_target_split_assemble" path = "fuzz_targets/fuzz_target_split_assemble.rs" diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs new file mode 100644 index 00000000..63a27eab --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs @@ -0,0 +1,9 @@ +#![no_main] + +use fuzz_helper::{process_input, InputType}; +use libfuzzer_sys::fuzz_target; + +// Fuzz inputs as CTAP1 U2F raw message. +fuzz_target!(|data: &[u8]| { + process_input(data, InputType::Ctap1); +}); diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs new file mode 100644 index 00000000..ae969242 --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs @@ -0,0 +1,9 @@ +#![no_main] + +use fuzz_helper::{process_input, InputType}; +use libfuzzer_sys::fuzz_target; + +// Fuzz inputs as CTAP2 make credential command parameters encoded in cbor. +fuzz_target!(|data: &[u8]| { + process_input(data, InputType::CborMakeCredentialParameter); +}); From 8231c89207c17a2e9236163abbb165c2c72405ef Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Fri, 25 Sep 2020 19:26:35 +0000 Subject: [PATCH 3/6] Formatting --- fuzz/fuzz_helper/src/lib.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/fuzz/fuzz_helper/src/lib.rs b/fuzz/fuzz_helper/src/lib.rs index 53a53759..564b7794 100644 --- a/fuzz/fuzz_helper/src/lib.rs +++ b/fuzz/fuzz_helper/src/lib.rs @@ -19,11 +19,13 @@ extern crate lang_items; use arrayref::array_ref; use core::convert::TryFrom; use crypto::rng256::ThreadRng256; -use ctap2::ctap::command::{ AuthenticatorMakeCredentialParameters, - AuthenticatorGetAssertionParameters, AuthenticatorClientPinParameters}; +use ctap2::ctap::command::{ + AuthenticatorClientPinParameters, AuthenticatorGetAssertionParameters, + AuthenticatorMakeCredentialParameters, +}; use ctap2::ctap::hid::receive::MessageAssembler; use ctap2::ctap::hid::send::HidPacketIterator; -use ctap2::ctap::hid::{HidPacket, ChannelID, CtapHid, Message}; +use ctap2::ctap::hid::{ChannelID, CtapHid, HidPacket, Message}; use ctap2::ctap::status_code::Ctap2StatusCode; use ctap2::ctap::CtapState; use libtock_drivers::timer::{ClockValue, Timestamp}; @@ -97,20 +99,18 @@ fn is_type(data: &[u8], input_type: InputType) -> bool { } match cbor::read(data) { Err(_) => false, - Ok(decoded_cbor) => { - match input_type { - InputType::CborMakeCredentialParameter => { - AuthenticatorMakeCredentialParameters::try_from(decoded_cbor).is_ok() - } - InputType::CborGetAssertionParameter => { - AuthenticatorGetAssertionParameters::try_from(decoded_cbor).is_ok() - } - InputType::CborClientPinParameter => { - AuthenticatorClientPinParameters::try_from(decoded_cbor).is_ok() - } - _ => true + Ok(decoded_cbor) => match input_type { + InputType::CborMakeCredentialParameter => { + AuthenticatorMakeCredentialParameters::try_from(decoded_cbor).is_ok() } - } + InputType::CborGetAssertionParameter => { + AuthenticatorGetAssertionParameters::try_from(decoded_cbor).is_ok() + } + InputType::CborClientPinParameter => { + AuthenticatorClientPinParameters::try_from(decoded_cbor).is_ok() + } + _ => true, + }, } } From f79a659e6913b7e324f76af908eb882d0e1d6ed8 Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Tue, 29 Sep 2020 16:30:41 +0000 Subject: [PATCH 4/6] Resolved PR comments and added more fuzz targets. --- fuzz/Cargo.toml | 18 +++++ fuzz/fuzz_helper/src/lib.rs | 72 +++++++++++++------ .../fuzz_targets/fuzz_target_process_ctap1.rs | 8 ++- .../fuzz_target_process_ctap2_client_pin.rs | 11 +++ ...fuzz_target_process_ctap2_get_assertion.rs | 11 +++ ...zz_target_process_ctap2_make_credential.rs | 6 +- .../fuzz_target_process_ctap_command.rs | 9 +++ .../fuzz_target_split_assemble.rs | 4 +- 8 files changed, 110 insertions(+), 29 deletions(-) create mode 100644 fuzz/fuzz_targets/fuzz_target_process_ctap2_client_pin.rs create mode 100644 fuzz/fuzz_targets/fuzz_target_process_ctap2_get_assertion.rs create mode 100644 fuzz/fuzz_targets/fuzz_target_process_ctap_command.rs diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index 9b1a37a4..15c8ca12 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -16,12 +16,30 @@ fuzz_helper = { path = "fuzz_helper" } [workspace] members = ["."] +[[bin]] +name = "fuzz_target_process_ctap_command" +path = "fuzz_targets/fuzz_target_process_ctap_command.rs" +test = false +doc = false + [[bin]] name = "fuzz_target_process_ctap1" path = "fuzz_targets/fuzz_target_process_ctap1.rs" test = false doc = false +[[bin]] +name = "fuzz_target_process_ctap2_client_pin" +path = "fuzz_targets/fuzz_target_process_ctap2_client_pin.rs" +test = false +doc = false + +[[bin]] +name = "fuzz_target_process_ctap2_get_assertion" +path = "fuzz_targets/fuzz_target_process_ctap2_get_assertion.rs" +test = false +doc = false + [[bin]] name = "fuzz_target_process_ctap2_make_credential" path = "fuzz_targets/fuzz_target_process_ctap2_make_credential.rs" diff --git a/fuzz/fuzz_helper/src/lib.rs b/fuzz/fuzz_helper/src/lib.rs index 564b7794..80c78525 100644 --- a/fuzz/fuzz_helper/src/lib.rs +++ b/fuzz/fuzz_helper/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ const CLOCK_FREQUENCY_HZ: usize = 32768; const DUMMY_TIMESTAMP: Timestamp = Timestamp::from_ms(0); const DUMMY_CLOCK_VALUE: ClockValue = ClockValue::new(0, CLOCK_FREQUENCY_HZ); -#[derive(Clone, PartialEq)] +#[derive(Clone, Copy, PartialEq)] pub enum InputType { CborMakeCredentialParameter, CborGetAssertionParameter, @@ -78,11 +78,11 @@ where let message = Message { cid: CHANNEL_BROADCAST, cmd: COMMAND_INIT, - payload: nonce.clone(), + payload: nonce, }; let mut assembler_reply = MessageAssembler::new(); let mut result_cid: ChannelID = Default::default(); - for pkt_request in HidPacketIterator::new(message.clone()).unwrap() { + for pkt_request in HidPacketIterator::new(message).unwrap() { for pkt_reply in ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, ctap_state) { if let Ok(Some(result)) = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP) { result_cid.copy_from_slice(&result.payload[8..12]); @@ -94,7 +94,7 @@ where // Checks whether the given data can be interpreted as the given type. fn is_type(data: &[u8], input_type: InputType) -> bool { - if input_type.clone() == InputType::Ctap1 { + if input_type == InputType::Ctap1 { return true; } match cbor::read(data) { @@ -114,10 +114,50 @@ fn is_type(data: &[u8], input_type: InputType) -> bool { } } +// Interprets the raw data as a complete message (with channel id, command type and payload) and +// invokes message splitting, packet processing at CTAP HID level and response assembling. +fn process_message( + data: &[u8], + ctap_state: &mut CtapState, + ctap_hid: &mut CtapHid, +) where + CheckUserPresence: Fn(ChannelID) -> Result<(), Ctap2StatusCode>, +{ + let message = raw_to_message(data); + if let Some(hid_packet_iterator) = HidPacketIterator::new(message) { + let mut assembler_reply = MessageAssembler::new(); + for pkt_request in hid_packet_iterator { + for pkt_reply in + ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, ctap_state) + { + // Only checks for assembling crashes, not for semantics. + let _ = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP); + } + } + } +} + +// Interprets the raw data as any ctap command (including the command byte) and +// invokes message splitting, packet processing at CTAP HID level and response assembling +// using an initialized and allocated channel. +pub fn process_ctap_any_type(data: &[u8]) { + // Initialize ctap state and hid and get the allocated cid. + let mut rng = ThreadRng256 {}; + let user_immediately_present = |_| Ok(()); + let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); + let mut ctap_hid = CtapHid::new(); + let cid = initialize(&mut ctap_state, &mut ctap_hid); + // Wrap input as message with the allocated cid. + let mut command = cid.to_vec(); + command.extend(data); + process_message(&command, &mut ctap_state, &mut ctap_hid); +} + // Interprets the raw data as of the given input type and -// invokes message splitting, assembling and packet processing at CTAP HID level. -pub fn process_input(data: &[u8], input_type: InputType) { - if !is_type(data, input_type.clone()) { +// invokes message splitting, packet processing at CTAP HID level and response assembling +// using an initialized and allocated channel. +pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) { + if !is_type(data, input_type) { return (); } // Initialize ctap state and hid and get the allocated cid. @@ -143,23 +183,11 @@ pub fn process_input(data: &[u8], input_type: InputType) { } } command.extend(data); - // Process message at HID level. - let message = raw_to_message(&command); - if let Some(hid_packet_iterator) = HidPacketIterator::new(message) { - let mut assembler_reply = MessageAssembler::new(); - for pkt_request in hid_packet_iterator { - for pkt_reply in - ctap_hid.process_hid_packet(&pkt_request, DUMMY_CLOCK_VALUE, &mut ctap_state) - { - // Only checks for assembling crashes, not for semantics. - let _ = assembler_reply.parse_packet(&pkt_reply, DUMMY_TIMESTAMP); - } - } - } + process_message(&command, &mut ctap_state, &mut ctap_hid); } // Splits and reassembles the given data as HID packets. -pub fn split_assemble(data: &[u8]) { +pub fn split_assemble_hid_packets(data: &[u8]) { let mut message = raw_to_message(data); if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) { let mut assembler = MessageAssembler::new(); diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs index 63a27eab..d0cd61bf 100644 --- a/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap1.rs @@ -1,9 +1,11 @@ #![no_main] -use fuzz_helper::{process_input, InputType}; +use fuzz_helper::{process_ctap_specific_type, InputType}; use libfuzzer_sys::fuzz_target; -// Fuzz inputs as CTAP1 U2F raw message. +// Fuzz inputs as CTAP1 U2F raw messages. +// For a more generic fuzz target including all CTAP commands, you can use +// fuzz_target_process_ctap_command. fuzz_target!(|data: &[u8]| { - process_input(data, InputType::Ctap1); + process_ctap_specific_type(data, InputType::Ctap1); }); diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap2_client_pin.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap2_client_pin.rs new file mode 100644 index 00000000..b54bdefa --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap2_client_pin.rs @@ -0,0 +1,11 @@ +#![no_main] + +use fuzz_helper::{process_ctap_specific_type, InputType}; +use libfuzzer_sys::fuzz_target; + +// Fuzz inputs as CTAP2 client pin command parameters encoded in cbor. +// For a more generic fuzz target including all CTAP commands, you can use +// fuzz_target_process_ctap_command. +fuzz_target!(|data: &[u8]| { + process_ctap_specific_type(data, InputType::CborClientPinParameter); +}); diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap2_get_assertion.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap2_get_assertion.rs new file mode 100644 index 00000000..2ad1c685 --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap2_get_assertion.rs @@ -0,0 +1,11 @@ +#![no_main] + +use fuzz_helper::{process_ctap_specific_type, InputType}; +use libfuzzer_sys::fuzz_target; + +// Fuzz inputs as CTAP2 get assertion command parameters encoded in cbor. +// For a more generic fuzz target including all CTAP commands, you can use +// fuzz_target_process_ctap_command. +fuzz_target!(|data: &[u8]| { + process_ctap_specific_type(data, InputType::CborGetAssertionParameter); +}); diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs index ae969242..8c618462 100644 --- a/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap2_make_credential.rs @@ -1,9 +1,11 @@ #![no_main] -use fuzz_helper::{process_input, InputType}; +use fuzz_helper::{process_ctap_specific_type, InputType}; use libfuzzer_sys::fuzz_target; // Fuzz inputs as CTAP2 make credential command parameters encoded in cbor. +// For a more generic fuzz target including all CTAP commands, you can use +// fuzz_target_process_ctap_command. fuzz_target!(|data: &[u8]| { - process_input(data, InputType::CborMakeCredentialParameter); + process_ctap_specific_type(data, InputType::CborMakeCredentialParameter); }); diff --git a/fuzz/fuzz_targets/fuzz_target_process_ctap_command.rs b/fuzz/fuzz_targets/fuzz_target_process_ctap_command.rs new file mode 100644 index 00000000..7eb7df3d --- /dev/null +++ b/fuzz/fuzz_targets/fuzz_target_process_ctap_command.rs @@ -0,0 +1,9 @@ +#![no_main] + +use fuzz_helper::process_ctap_any_type; +use libfuzzer_sys::fuzz_target; + +// Generically fuzz inputs as CTAP commands. +fuzz_target!(|data: &[u8]| { + process_ctap_any_type(data); +}); diff --git a/fuzz/fuzz_targets/fuzz_target_split_assemble.rs b/fuzz/fuzz_targets/fuzz_target_split_assemble.rs index 59365645..ee6f8bf0 100644 --- a/fuzz/fuzz_targets/fuzz_target_split_assemble.rs +++ b/fuzz/fuzz_targets/fuzz_target_split_assemble.rs @@ -1,9 +1,9 @@ #![no_main] -use fuzz_helper::split_assemble; +use fuzz_helper::split_assemble_hid_packets; use libfuzzer_sys::fuzz_target; // Fuzzing HID packets splitting and assembling functions. fuzz_target!(|data: &[u8]| { - split_assemble(data); + split_assemble_hid_packets(data); }); From 9493014b13ee0f1ccd08bf073ee0101b59211abe Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Fri, 2 Oct 2020 17:18:36 +0000 Subject: [PATCH 5/6] Resolved PR comments --- fuzz/fuzz_helper/src/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fuzz/fuzz_helper/src/lib.rs b/fuzz/fuzz_helper/src/lib.rs index 80c78525..a6dc1a75 100644 --- a/fuzz/fuzz_helper/src/lib.rs +++ b/fuzz/fuzz_helper/src/lib.rs @@ -46,6 +46,10 @@ pub enum InputType { Ctap1, } +fn user_immediately_present(_: ChannelID) -> Result<(), Ctap2StatusCode> { + Ok(()) +} + // Converts a byte slice into Message fn raw_to_message(data: &[u8]) -> Message { if data.len() <= 4 { @@ -143,7 +147,6 @@ fn process_message( pub fn process_ctap_any_type(data: &[u8]) { // Initialize ctap state and hid and get the allocated cid. let mut rng = ThreadRng256 {}; - let user_immediately_present = |_| Ok(()); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_hid = CtapHid::new(); let cid = initialize(&mut ctap_state, &mut ctap_hid); @@ -158,11 +161,10 @@ pub fn process_ctap_any_type(data: &[u8]) { // using an initialized and allocated channel. pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) { if !is_type(data, input_type) { - return (); + return; } // Initialize ctap state and hid and get the allocated cid. let mut rng = ThreadRng256 {}; - let user_immediately_present = |_| Ok(()); let mut ctap_state = CtapState::new(&mut rng, user_immediately_present); let mut ctap_hid = CtapHid::new(); let cid = initialize(&mut ctap_state, &mut ctap_hid); @@ -186,7 +188,7 @@ pub fn process_ctap_specific_type(data: &[u8], input_type: InputType) { process_message(&command, &mut ctap_state, &mut ctap_hid); } -// Splits and reassembles the given data as HID packets. +// Splits the given data as HID packets and reassembles it, verifying that the original input message is reconstructed. pub fn split_assemble_hid_packets(data: &[u8]) { let mut message = raw_to_message(data); if let Some(hid_packet_iterator) = HidPacketIterator::new(message.clone()) { From cc0c9eefeb225419f0aef773e6b7f626b9c61178 Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Mon, 5 Oct 2020 10:17:09 +0000 Subject: [PATCH 6/6] changed reproducible --- .../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 6d0a1383..b7b57c01 100644 --- a/reproducible/reference_binaries_macos-10.15.sha256sum +++ b/reproducible/reference_binaries_macos-10.15.sha256sum @@ -1,9 +1,9 @@ dd5920dfb172d9371b29d019b6a37fae1a995bf9d814000944d9ef36bad31513 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -fe868d9398863ff6e484742d93a4266ee7afa1ac34f9fa5ed570f8309272156a target/nrf52840dk_merged.hex +cf2fb98364ab8520d771090aa59859c1e628c32c01c7b73c000162f579411fc7 target/nrf52840dk_merged.hex e4acfa602a5cc5d7c61d465f873918e8e0858628d0e5f8e0db26a7b7dd0b94d4 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -acca7d690ecc4733be4606ff9cd491fbc62dc3216ce0b98132e5669c8b2cba29 target/nrf52840_dongle_merged.hex +588c55ece0bf45d783ca513e12d4072668d9749b9320a13380fcc498a2855a7b target/nrf52840_dongle_merged.hex c0ace9f13ef3fd18c576a735ae23b3956bf8dd346f20c6217086e748d6bad8a2 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -e5cf030db968b0d78a30683d7278e7481d5e2d385b80e6509e76cfb9392899b2 target/nrf52840_dongle_dfu_merged.hex +4b3f87e9bb992198f5885cc689e1cf1f8e93519f107614d316473ef43f8be7a4 target/nrf52840_dongle_dfu_merged.hex 06a38a0d6d356145467a73c765e28a945878f663664016f888393207097bfe10 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -3735572cccfc0c39540f77e2c55d0a25aa82dd22ad698824fd2630fcbd87f611 target/nrf52840_mdk_dfu_merged.hex -4d36b3b456de9340e4e18fd595ae25e71298431f73ef17653bb7fb707830a9af target/tab/ctap2.tab +c35a1501eed3024821f0f17f2a50e1c27925ccabee4c633e10fa10e5bcd197ac target/nrf52840_mdk_dfu_merged.hex +17cd41e1ab1bfa683b5ec79333779a95965668fea146d2a178ca35ab20b16ece target/tab/ctap2.tab diff --git a/reproducible/reference_binaries_ubuntu-18.04.sha256sum b/reproducible/reference_binaries_ubuntu-18.04.sha256sum index 4e9f5037..e20ee78c 100644 --- a/reproducible/reference_binaries_ubuntu-18.04.sha256sum +++ b/reproducible/reference_binaries_ubuntu-18.04.sha256sum @@ -1,9 +1,9 @@ 2426ee9a6c75e325537818081d45445d95468a4c0a77feacdc6133d7d9aa227a third_party/tock/target/thumbv7em-none-eabi/release/nrf52840dk.bin -b4248106097b9d54b882cd1dd1f88710585a3e274ee5edff334dcb2b26c8af51 target/nrf52840dk_merged.hex +c0cdbad7d4d7d9bd64ad7db43046ada19990b8f43a88e6ec3f508bb233827966 target/nrf52840dk_merged.hex c53d1e1db72df25950fa6d28699a2d38757def0dcbeb0d09d2366481cf0149a6 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle.bin -ac2d36a3c7f8326496c66d1e4aa8a82bbe2d689fe9cd86308f1304393bc125ec target/nrf52840_dongle_merged.hex +7bb26ae63b60e136852133c0da1d1cbf550a98012f9ba3bb4d27fc682a504880 target/nrf52840_dongle_merged.hex 233b5ba4459523759e3171cee83cdb3a383bbe65727c8ece64dfe5321d6ebe34 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_dongle_dfu.bin -aff4b19511486548529f02be3a32bd47bd6329f813aef6e761c15dce8284bfa7 target/nrf52840_dongle_dfu_merged.hex +fbcc441dc5faf87baffe57226fd52c8e63804cd0d76f04057474954a74985217 target/nrf52840_dongle_dfu_merged.hex 1baaf518a74c6077cb936d9cf178b6dd0232e7562fa56174886b05b77886cc32 third_party/tock/target/thumbv7em-none-eabi/release/nrf52840_mdk_dfu.bin -a2f1e440b9c875f0ca1dd0952fd435686dfd1c29d708771b08827ae21fc31c51 target/nrf52840_mdk_dfu_merged.hex -5eb8a111c5eb1554785e86bb8168180ee984ee69bc110d859cad1043b79daa2e target/tab/ctap2.tab +80c430b911c967dcf1d60d7456d381162a342733e4e42a6f64f855120339de35 target/nrf52840_mdk_dfu_merged.hex +62b4bea855a5757fe70c2690f8c05d8ed0078d688de07b6695f9f73bc265f2f6 target/tab/ctap2.tab diff --git a/reproducible/reference_elf2tab_macos-10.15.txt b/reproducible/reference_elf2tab_macos-10.15.txt index 0be6bb77..73602668 100644 --- a/reproducible/reference_elf2tab_macos-10.15.txt +++ b/reproducible/reference_elf2tab_macos-10.15.txt @@ -6,8 +6,8 @@ Min RAM size from segments in ELF: 20 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: 187352 (0x2dbd8) bytes. - Adding .stack section. Offset: 187480 (0x2dc58). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187320 (0x2dbb8) bytes. + Adding .stack section. Offset: 187448 (0x2dc38). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -30,8 +30,8 @@ Min RAM size from segments in ELF: 20 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: 187352 (0x2dbd8) bytes. - Adding .stack section. Offset: 187480 (0x2dc58). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187320 (0x2dbb8) bytes. + Adding .stack section. Offset: 187448 (0x2dc38). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -54,8 +54,8 @@ Min RAM size from segments in ELF: 20 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: 187352 (0x2dbd8) bytes. - Adding .stack section. Offset: 187480 (0x2dc58). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187320 (0x2dbb8) bytes. + Adding .stack section. Offset: 187448 (0x2dc38). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -78,8 +78,8 @@ Min RAM size from segments in ELF: 20 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: 187352 (0x2dbd8) bytes. - Adding .stack section. Offset: 187480 (0x2dc58). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187320 (0x2dbb8) bytes. + Adding .stack section. Offset: 187448 (0x2dc38). 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 39375f48..7e58539b 100644 --- a/reproducible/reference_elf2tab_ubuntu-18.04.txt +++ b/reproducible/reference_elf2tab_ubuntu-18.04.txt @@ -6,8 +6,8 @@ Min RAM size from segments in ELF: 20 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: 187344 (0x2dbd0) bytes. - Adding .stack section. Offset: 187472 (0x2dc50). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187008 (0x2da80) bytes. + Adding .stack section. Offset: 187136 (0x2db00). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -30,8 +30,8 @@ Min RAM size from segments in ELF: 20 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: 187344 (0x2dbd0) bytes. - Adding .stack section. Offset: 187472 (0x2dc50). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187008 (0x2da80) bytes. + Adding .stack section. Offset: 187136 (0x2db00). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -54,8 +54,8 @@ Min RAM size from segments in ELF: 20 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: 187344 (0x2dbd0) bytes. - Adding .stack section. Offset: 187472 (0x2dc50). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187008 (0x2da80) bytes. + Adding .stack section. Offset: 187136 (0x2db00). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2 @@ -78,8 +78,8 @@ Min RAM size from segments in ELF: 20 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: 187344 (0x2dbd0) bytes. - Adding .stack section. Offset: 187472 (0x2dc50). Length: 16384 (0x4000) bytes. + Adding .text section. Offset: 128 (0x80). Length: 187008 (0x2da80) bytes. + Adding .stack section. Offset: 187136 (0x2db00). Length: 16384 (0x4000) bytes. Searching for .rel.X sections to add. TBF Header: version: 2 0x2