ctaphid 0.2.0

Rust implementation of the CTAPHID protocol
Documentation
// Copyright (C) 2022 Robin Krahl <robin.krahl@ireas.org>
// SPDX-License-Identifier: CC0-1.0

//! Executes a CTAP1/U2F command on all available CTAPHID devices that support it.

fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::init();

    let hidapi = hidapi::HidApi::new()?;
    let devices: Vec<_> = hidapi
        .device_list()
        .filter(|device| ctaphid::is_known_device(*device))
        .collect();
    for device_info in devices {
        let device = device_info.open_device(&hidapi)?;
        let device = ctaphid::Device::new(device, device_info.to_owned())?;
        let status = if device.capabilities().has_cbor() {
            let response = device.ctap2(0x04, &[])?;
            let data: std::collections::BTreeMap<u8, serde_cbor::Value> =
                serde_cbor::from_slice(&response)?;
            if let Some(value) = data.get(&0x03) {
                if let serde_cbor::Value::Bytes(value) = value {
                    let value: Vec<_> = value.into_iter().map(|b| format!("{:02x}", b)).collect();
                    value.concat()
                } else {
                    format!("unexpected AAGUID value: {:?}", value)
                }
            } else {
                "no AAGUID".to_owned()
            }
        } else {
            "no CTAP2 support".to_owned()
        };
        println!("- {}: {}", device_info.path().to_string_lossy(), status);
    }
    Ok(())
}