• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::fs::File;
6 use std::os::raw::c_int;
7 
8 use base::handle_eintr_errno;
9 use base::ioctl_ior_nr;
10 
11 use crate::usb::backend::fido_backend::constants;
12 use crate::usb::backend::fido_backend::error::Error;
13 use crate::usb::backend::fido_backend::error::Result;
14 
15 #[repr(C)]
16 #[derive(Clone)]
17 pub struct HidrawReportDescriptor {
18     pub size: u32,
19     pub value: [u8; constants::HID_MAX_DESCRIPTOR_SIZE],
20 }
21 
22 pub const HID_IO_TYPE: u32 = 'H' as u32;
23 
24 ioctl_ior_nr!(HIDIOCGRDESCSIZE, HID_IO_TYPE, 0x01, c_int);
25 ioctl_ior_nr!(HIDIOCGRDESC, HID_IO_TYPE, 0x02, HidrawReportDescriptor);
26 
27 /// Verifies that the given `hidraw` file handle is a valid FIDO device.
28 /// In case it is not, it returns an `InvalidHidrawDevice` erro.
verify_is_fido_device(hidraw: &File) -> Result<()>29 pub fn verify_is_fido_device(hidraw: &File) -> Result<()> {
30     let mut desc_size: c_int = 0;
31     // SAFETY:
32     // Safe because:
33     // - We check the return value after the call.
34     // - ioctl(HIDIOCGRDDESCSIZE) does not hold the descriptor after the call.
35     unsafe {
36         let ret = handle_eintr_errno!(base::ioctl_with_mut_ref(
37             hidraw,
38             HIDIOCGRDESCSIZE,
39             &mut desc_size
40         ));
41         if ret < 0 || (desc_size as usize) < constants::HID_REPORT_DESC_HEADER.len() {
42             return Err(Error::InvalidHidrawDevice);
43         }
44     }
45 
46     let mut descriptor = HidrawReportDescriptor {
47         size: desc_size as u32,
48         value: [0; constants::HID_MAX_DESCRIPTOR_SIZE],
49     };
50 
51     // SAFETY:
52     // Safe because:
53     // - We check the return value after the call.
54     // - ioctl(HIDIOCGRDESC) does not hold the descriptor after the call.
55     unsafe {
56         let ret = handle_eintr_errno!(base::ioctl_with_mut_ref(
57             hidraw,
58             HIDIOCGRDESC,
59             &mut descriptor
60         ));
61         if ret < 0 {
62             return Err(Error::InvalidHidrawDevice);
63         }
64     }
65 
66     if descriptor.value[..constants::HID_REPORT_DESC_HEADER.len()]
67         != *constants::HID_REPORT_DESC_HEADER
68     {
69         return Err(Error::InvalidHidrawDevice);
70     }
71     Ok(())
72 }
73