Skip to content

Commit 276a3ef

Browse files
authored
init: check hidraw descriptor to figure out fido or not (#264)
this checks the Usage Page value from report_descriptor against 0xd0f1, similar to how it's done in libfido2 references: - https://github.com/Yubico/libfido2/blob/03c18d396eb209a42bbf62f5f4415203cba2fc50/src/hid_hidapi.c#L146 - https://www.usb.org/sites/default/files/hid1_11.pdf 6.2.2.7 Global Item tested with pico-fido Signed-off-by: Guoxin Pu <[email protected]>
1 parent 30c7da5 commit 276a3ef

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

init/luks.go

+31-5
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,43 @@ func recoverClevisPassword(t luks.Token, luksVersion int) ([]byte, error) {
8989
}
9090
}
9191

92+
func isHidRawFido2(devName string) (bool, error) {
93+
descriptor, err := os.ReadFile("/sys/class/hidraw/" + devName + "/device/report_descriptor")
94+
if err != nil {
95+
return false, fmt.Errorf("unable to read HID descriptor for %s", devName)
96+
}
97+
lenDescriptor := len(descriptor)
98+
for id := 0; id < lenDescriptor; id++ {
99+
itemPrefix := descriptor[id]
100+
itemSize := itemPrefix & 0b11
101+
// References:
102+
// - libfido2 checks Usage Page against 0xd0f1 (FIDO Alliance):
103+
// https://github.com/Yubico/libfido2/blob/03c18d396eb209a42bbf62f5f4415203cba2fc50/src/hid_hidapi.c#L146
104+
// - HID specification 6.2.2.7 Global Item, Usage Page prefix format is 0000 01 nn, nn = length
105+
// https://www.usb.org/sites/default/files/hid1_11.pdf
106+
if itemPrefix&0b11111100 == 0b00000100 &&
107+
itemSize == 2 &&
108+
id+2 < lenDescriptor &&
109+
descriptor[id+1] == 0xd0 && //
110+
descriptor[id+2] == 0xf1 {
111+
return true, nil
112+
}
113+
id += int(itemSize)
114+
}
115+
116+
return false, nil
117+
}
118+
92119
func recoverFido2Password(devName string, credential string, salt string, relyingParty string, pinRequired bool, userPresenceRequired bool, userVerificationRequired bool) ([]byte, error) {
93120
usbhidWg.Wait()
94121

95-
ueventContent, err := os.ReadFile("/sys/class/hidraw/" + devName + "/device/uevent")
122+
isFido2, err := isHidRawFido2(devName)
96123
if err != nil {
97-
return nil, fmt.Errorf("unable to read uevent file for %s", devName)
124+
return nil, fmt.Errorf("unable to check whether %s is a FIDO2 device", devName)
98125
}
99126

100-
// TODO: find better way to identify devices that support FIDO2
101-
if !strings.Contains(string(ueventContent), "FIDO") {
102-
return nil, fmt.Errorf("HID %s does not support FIDO", devName)
127+
if !isFido2 {
128+
return nil, fmt.Errorf("HID %s is not a FIDO2 device", devName)
103129
}
104130

105131
info("HID %s supports FIDO, trying it to recover the password", devName)

0 commit comments

Comments
 (0)