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

Code before:
}

// 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]) -> arbitrary::Result<()> {
    let mut unstructured = Unstructured::new(data);

    let mut env = TestEnv::new();
    env.rng()
        .seed_rng_from_u64(u64::arbitrary(&mut unstructured)?);

    let data = unstructured.take_rest();
    // Initialize ctap state and hid and get the allocated cid.
    let mut ctap = Ctap::new(env, CtapInstant::new(0));
    let cid = initialize(&mut ctap);
    // Wrap input as message with the allocated cid.
    let mut command = cid.to_vec();
    command.extend(data);
    process_message(&command, &mut ctap);
    Ok(())
}

fn setup_storage(unstructured: &mut Unstructured, env: &mut TestEnv) -> arbitrary::Result<()> {
    if bool::arbitrary(unstructured)? {
        env.set_enterprise_attestation();
    }
    Ok(())
}

fn setup_customization(
    unstructured: &mut Unstructured,
    env: &mut TestEnv,
) -> arbitrary::Result<()> {
    env.customization_mut().enterprise_attestation_mode =
        Option::<EnterpriseAttestationMode>::arbitrary(unstructured)?;
    Ok(())
}

// Interprets the raw data as of the given input type and
// 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) -> arbitrary::Result<()> {
    let mut unstructured = Unstructured::new(data);

    let mut env = TestEnv::new();
    env.rng()
        .seed_rng_from_u64(u64::arbitrary(&mut unstructured)?);

    setup_storage(&mut unstructured, &mut env)?;
    setup_customization(&mut unstructured, &mut env)?;

Review comment (security):
This is closer to how I perceive this change. A storage setup inside a helper library. My enterprise attestation tests are basically integration tests more than unit tests, and they almost call externally available APIs. (They call `process_make_credential` directly, but that's easy to move up one more indirection to something public.) So maybe `set_enterprise_attestation` could move to `tests/helper` or something?

Code after:
// 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: &mut Ctap<TestEnv>) {
    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.process_hid_packet(&pkt_request, Transport::MainHid, CtapInstant::new(0))
            {
                // Only checks for assembling crashes, not for semantics.
                let _ = assembler_reply.parse_packet(ctap.env(), &pkt_reply, CtapInstant::new(0));
            }
        }
    }
}

// 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]) -> arbitrary::Result<()> {
    let mut unstructured = Unstructured::new(data);

    let mut env = TestEnv::new();
    env.rng().seed_from_u64(u64::arbitrary(&mut unstructured)?);

    let data = unstructured.take_rest();
    // Initialize ctap state and hid and get the allocated cid.
    let mut ctap = Ctap::new(env, CtapInstant::new(0));
    let cid = initialize(&mut ctap);
    // Wrap input as message with the allocated cid.
    let mut command = cid.to_vec();
    command.extend(data);
    process_message(&command, &mut ctap);
    Ok(())
}

fn setup_customization(
    unstructured: &mut Unstructured,
    customization: &mut TestCustomization,
) -> FuzzResult<()> {
    customization.setup_enterprise_attestation(
        Option::<EnterpriseAttestationMode>::arbitrary(unstructured)?,
        // TODO: Generate arbitrary rp_id_list (but with some dummies because content doesn't
        // matter), and use the rp ids in commands.
        None,
    );
    if !is_valid(customization) {
        return Err(FuzzError::InvalidCustomization);
    }
    Ok(())