@@ -89,17 +89,43 @@ func recoverClevisPassword(t luks.Token, luksVersion int) ([]byte, error) {
89
89
}
90
90
}
91
91
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
+
92
119
func recoverFido2Password (devName string , credential string , salt string , relyingParty string , pinRequired bool , userPresenceRequired bool , userVerificationRequired bool ) ([]byte , error ) {
93
120
usbhidWg .Wait ()
94
121
95
- ueventContent , err := os . ReadFile ( "/sys/class/hidraw/" + devName + "/device/uevent" )
122
+ isFido2 , err := isHidRawFido2 ( devName )
96
123
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 )
98
125
}
99
126
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 )
103
129
}
104
130
105
131
info ("HID %s supports FIDO, trying it to recover the password" , devName )
0 commit comments