On Fri, Jan 09, 2026 at 07:38:20PM -0700, Andy Bradford wrote: > Hello, > > After upgrading to OpenBSD 7.8, the Yubikey OTP "insert key and press > the button" functionality no longer works in OpenBSD because it no > longer attaches as a keyboard: > > https://cvsweb.openbsd.org/src/sys/dev/usb/ukbd.c?rev=1.91&ipk=jmoO719Mg1QImIC-UsGwegP2ZCM7IeAUQC-ZGChv3ic&content-type=text/x-cvsweb-markup > > I don't see Yubico updating their tools anytime soon, so... > > After a suggestion from mischief in IRC, I realized I could use > usbhidctl to get the data upon pressing the button. Oddly enough, for > some reason on my system the data seems to be buffered (when in a > pipeline) and the script doesn't produce output until I unplug the > device, whereupon I get an error message, but at least I also get the > OTP. > > After finding your uhid number for the Yubikey by looking at dmesg > output, here's the sed script I wrote to extract the OTP upon pressing > the button (and removal of device due to buffering I'm encountering): You can also read from /dev/uhidN directly with perl and not worry about the buffering.
https://gist.github.com/afresh1/1a04e771173d960a6507197e188b77df #!/usr/bin/perl use v5.36; use builtin 'indexed'; # Copyright (c) 2026 Andrew Hewus Fresh <[email protected]> # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. =head1 NAME read-yubikey -- Read output from yubikey OTP on OpenBSD =head1 DESCRIPTION On OpenBSD Yubikeys no longer attach as keyboards, but they do still attach as HID devices. We can read codes from the device with a little work. Running this script should find the appropriate uhid device and loop over reading OTP messages from it. =cut # https://wiki.osdev.org/USB_Human_Interface_Devices#Report_format # https://gist.github.com/mildsunrise/4e231346e2078f440969cdefb6d4caa3 my %MODIFIERS = reverse indexed qw< LEFT_CTRL LEFT_SHIFT LEFT_ALT LEFT_GUI RIGHT_CTRL RIGHT_SHIFT RIGHT_ALT RIGHT_GUI >; sub decode( $mod, $code ) { return 'ENTER' if $code eq 0x28; if ( 0x04 <= $_ <= 0x27 ) { my $shift = $mod & ( $MODIFIERS{LEFT_SHIFT} | $MODIFIERS{RIGHT_SHIFT} ); my $offset = $shift ? 0x41 : 0x61; return chr( $code + $offset - 0x04 ); } return; } while (1) { my $uhid = do { my $u; my $uhidev; open my $fh, '-|', qw< /sbin/dmesg > or die "Unable to spawn dmesg $!"; while (readline $fh) { if (/^(uhidev\d+) .*Yubikey/) { $u = undef; $uhidev = $1; } elsif ($u && /^\Q$u detached/) { $u = undef; $uhidev = undef; } elsif ($uhidev && /^(uhid\d+) at \Q$uhidev:/) { $u = $1; } } close $fh; $u; }; # Could change this to a sleep wait. die "Yubikey uhid not in dmesg" unless $uhid; open my $fh, '<', "/dev/$uhid" or die "Unable to open /dev/$uhid: $!"; my $buf = ''; while ( read $fh, my $rec, 8 ) { my ( $mod, undef, @codes ) = unpack "C*", $rec; for (@codes) { next unless $_; my $key = decode( $mod, $_ ); if ( $key eq "ENTER" ) { say $buf; $buf = ''; next; } $buf .= $key; } } close $fh; }

