From f79a659e6913b7e324f76af908eb882d0e1d6ed8 Mon Sep 17 00:00:00 2001 From: mingxguo27 Date: Tue, 29 Sep 2020 16:30:41 +0000 Subject: [PATCH] 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 9b1a37a..15c8ca1 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 564b779..80c7852 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 63a27ea..d0cd61b 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 0000000..b54bdef --- /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 0000000..2ad1c68 --- /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 ae96924..8c61846 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 0000000..7eb7df3 --- /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 5936564..ee6f8bf 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); });