Repository: google/OpenSK
File: fuzz/fuzz_helper/src/lib.rs (Rust)

Code before:

// 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]);
        }
    }

Review comment (suggestion):
It would be clearer to have a more specific function name than `process_input`. In a way, all functions process some input and return some output.

Code after:
        }
    }
    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 == 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 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<CheckUserPresence>(
    data: &[u8],
    ctap_state: &mut CtapState<ThreadRng256, CheckUserPresence>,
    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