Categories
DailyOps

How to identify YubiKey using dynamic device manager

Identify YubiKey device using dynamic device manager to send desktop notification.

Inspect device manager information

Inspect device manager events to get the YubiKey serial number.

$ udevadm monitor --property
[...]
UDEV  [375258.194493] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4.1 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4.1
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/002/058
DEVTYPE=usb_device
PRODUCT=1050/407/543
TYPE=0/0/0
BUSNUM=002
DEVNUM=058
SEQNUM=25041
USEC_INITIALIZED=375258188457
ID_VENDOR=Yubico
ID_VENDOR_ENC=Yubico
ID_VENDOR_ID=1050
ID_MODEL=YubiKey_OTP+FIDO+CCID
ID_MODEL_ENC=YubiKey\x20OTP+FIDO+CCID
ID_MODEL_ID=0407
ID_REVISION=0543
ID_SERIAL=Yubico_YubiKey_OTP+FIDO+CCID
ID_BUS=usb
ID_USB_INTERFACES=:030101:030000:0b0000:
ID_VENDOR_FROM_DATABASE=Yubico.com
ID_MODEL_FROM_DATABASE=Yubikey 4/5 OTP+U2F+CCID
ID_PATH=pci-0000:00:1d.0-usb-0:1.4.1
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_4_1
ID_SMARTCARD_READER=1
DRIVER=usb
ID_SECURITY_TOKEN=1
ID_FOR_SEAT=usb-pci-0000_00_1d_0-usb-0_1_4_1
SYSTEMD_WANTS=smartcard.target
SYSTEMD_USER_WANTS=smartcard.target
MAJOR=189
MINOR=185
TAGS=:uaccess:security-device:systemd:seat:
CURRENT_TAGS=:uaccess:security-device:systemd:seat:
[...]

Serial number is not provided by default over USB descriptor.

Add Yubico PPA

Add PPA for stable Yubico software.

$ sudo add-apt-repository ppa:yubico/stable

Update package index.

$ sudo apt-get update

Use command-line utility

Install command-line personalization utility for Yubikey OTP tokens.

$ sudo apt install yubikey-personalization

Display help information.

$ ykpersonalize -h
Usage: ykpersonalize [options]                                                   
-Nkey     use nth key found                                                      
-u        update configuration without overwriting.  This is only available      
          in YubiKey 2.3 and later.  EXTFLAG_ALLOW_UPDATE will be set by
          default                                                                
-1        change the first configuration.  This is the default and
          is normally used for true OTP generation.          
          In this configuration, TKTFLAG_APPEND_CR is set by default.
-2        change the second configuration.  This is for Yubikey II only
          and is then normally used for static key generation.
          In this configuration, TKTFLAG_APPEND_CR, CFGFLAG_STATIC_TICKET,       
          CFGFLAG_STRONG_PW1, CFGFLAG_STRONG_PW2 and CFGFLAG_MAN_UPDATE
          are set by default.                                                    
-x        swap the configuration in slot 1 and 2.  This is for YubiKey 2.3       
          and newer only                                                         
-z        delete the configuration in slot 1 or 2.              
-sFILE    save configuration to FILE instead of key.                             
          (if FILE is -, send to stdout)                  
-iFILE    read configuration from FILE. (only valid for -fycfg)
          (if FILE is -, read from stdin)
-fformat  set the data format for -s and -i valid values are ycfg or legacy.
-a[XXX..] The AES secret key as a 32 (or 40 for OATH-HOTP/HMAC CHAL-RESP)
          char hex value (not modhex) (none to prompt for key on stdin)
          If -a is not used a random key will be generated.
-c[XXX..] A 12 char hex value (not modhex) to use as access code for programming
          (this does NOT SET the access code, that's done with -oaccess=)
          If -c is provided without argument a code is prompted for
-nXXX..   Write NDEF URI to YubiKey NEO, must be used with -1 or -2
-tXXX..   Write NDEF text to YubiKey NEO, must be used with -1 or -2
-mMODE    Set the USB device configuration of the YubiKey.
          See the manpage for details. This is for YubiKey 3 and 4 only.
-S0605..  Set the scanmap to use with the YubiKey. Must be 45 unique bytes,
          in hex.  Use with no argument to reset to the default. This is for
          YubiKey 3.0 and newer only.
-D0403..  Set the deviceinfo to use with this YubiKey. YubiKey 5 and newer only.
-oOPTION  change configuration option.  Possible OPTION arguments are:
          fixed=xxxxxxxxxxx   The public identity of key, in MODHEX.
                              This is 0-32 characters long.
          uid[=xxxxxx]        The uid part of the generated ticket, in HEX.
                              MUST be 12 characters long.
                              If argument is omitted uid is prompted for on stdin.
          access[=xxxxxx]     New access code to set, in HEX.
                              MUST be 12 characters long.
                              If argument is omitted code is prompted for on stdin.
          oath-imf=IMF        OATH Initial Moving Factor to use.
          oath-id[=h:OOTT...] OATH Token Identifier (none for serial-based)

          Ticket flags for all firmware versions:
          [-]tab-first           set/clear TAB_FIRST
          [-]append-tab1         set/clear APPEND_TAB1
          [-]append-tab2         set/clear APPEND_TAB2
          [-]append-delay1       set/clear APPEND_DELAY1
          [-]append-delay2       set/clear APPEND_DELAY2
          [-]append-cr           set/clear APPEND_CR

          Ticket flags for firmware version 2.0 and above:
          [-]protect-cfg2        set/clear PROTECT_CFG2

          Ticket flags for firmware version 2.1 and above:
          [-]oath-hotp           set/clear OATH_HOTP

          Ticket flags for firmware version 2.2 and above:
          [-]chal-resp           set/clear CHAL_RESP

          Configuration flags for all firmware versions:
          [-]send-ref            set/clear SEND_REF
          [-]pacing-10ms         set/clear PACING_10MS
          [-]pacing-20ms         set/clear PACING_20MS
          [-]static-ticket       set/clear STATIC_TICKET

          Configuration flags for firmware version 1.x only:
          [-]ticket-first        set/clear TICKET_FIRST
          [-]allow-hidtrig       set/clear ALLOW_HIDTRIG

          Configuration flags for firmware version 2.0 and above:
          [-]short-ticket        set/clear SHORT_TICKET
          [-]strong-pw1          set/clear STRONG_PW1
          [-]strong-pw2          set/clear STRONG_PW2
          [-]man-update          set/clear MAN_UPDATE

          Configuration flags for firmware version 2.1 and above:
          [-]oath-hotp8          set/clear OATH_HOTP8
          [-]oath-fixed-modhex1  set/clear OATH_FIXED_MODHEX1
          [-]oath-fixed-modhex2  set/clear OATH_FIXED_MODHEX2
          [-]oath-fixed-modhex   set/clear OATH_MODHEX

          Configuration flags for firmware version 2.2 and above:
          [-]chal-yubico         set/clear CHAL_YUBICO
          [-]chal-hmac           set/clear CHAL_HMAC
          [-]hmac-lt64           set/clear HMAC_LT64
          [-]chal-btn-trig       set/clear CHAL_BTN_TRIG

          Extended flags for firmware version 2.2 and above:
          [-]serial-btn-visible  set/clear SERIAL_BTN_VISIBLE
          [-]serial-usb-visible  set/clear SERIAL_USB_VISIBLE
          [-]serial-api-visible  set/clear SERIAL_API_VISIBLE

          Extended flags for firmware version 2.3 and above:
          [-]use-numeric-keypad  set/clear USE_NUMERIC_KEYPAD
          [-]fast-trig           set/clear FAST_TRIG
          [-]allow-update        set/clear ALLOW_UPDATE
          [-]dormant             set/clear DORMANT

          Extended flags for firmware version 2.4/3.1 and above:
          [-]led-inv             set/clear LED_INV

-y        always commit (do not prompt)

-d        dry-run (don't write anything to key)

-v        verbose
-V        tool version
-h        help (this text)

Display utility version.

$ ykpersonalize -V
1.20.0

Dry-run operation on the first configuration slot.

$ ykpersonalize -v -d -y -u -1  -o serial-usb-visible -o serial-api-visible -o serial-btn-visible 
Firmware version 5.4.3 Touch level 1285 Program sequence 1
Serial number : 18654472

Configuration data to be updated in key configuration 1:

fixed: m:
uid: 000000000000
key: h:00000000000000000000000000000000
acc_code: h:000000000000
ticket_flags: APPEND_CR
config_flags: 
extended_flags: SERIAL_BTN_VISIBLE|SERIAL_USB_VISIBLE|SERIAL_API_VISIBLE|ALLOW_UPDATE

Commit? (y/n) [n]: yes
Attempting to write configuration to the yubikey...Not writing anything to key due to dry_run requested.

Perform operation on the first configuration slot.

$ ykpersonalize -v -y -u -1  -o serial-usb-visible -o serial-api-visible -o serial-btn-visible 
Firmware version 5.4.3 Touch level 1285 Program sequence 1
Serial number : 18654472

Configuration data to be updated in key configuration 1:

fixed: m:
uid: 000000000000
key: h:00000000000000000000000000000000
acc_code: h:000000000000
ticket_flags: APPEND_CR
config_flags: 
extended_flags: SERIAL_BTN_VISIBLE|SERIAL_USB_VISIBLE|SERIAL_API_VISIBLE|ALLOW_UPDATE

Commit? (y/n) [n]: yes
Attempting to write configuration to the yubikey... success

Use GUI utility

Install GUI personalization utility for Yubikey OTP tokens.

$ sudo apt install yubikey-personalization-gui

Execute GUI personalization utility.

$ yubikey-personalization-gui

Open settings tab and ensure that serial number visibility over USB descriptor is enabled.

Click update settings.

Ensure that configuration slot is selected and click update.

Inspect device manager information

Inspect device manager events to get the YubiKey serial number.

$ udevadm monitor --property
[...]
UDEV  [375336.271312] add      /devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4.1 (usb)
ACTION=add
DEVPATH=/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4.1
SUBSYSTEM=usb
DEVNAME=/dev/bus/usb/002/059
DEVTYPE=usb_device
PRODUCT=1050/407/543
TYPE=0/0/0
BUSNUM=002
DEVNUM=059
SEQNUM=25091
USEC_INITIALIZED=375336265108
ID_VENDOR=Yubico
ID_VENDOR_ENC=Yubico
ID_VENDOR_ID=1050
ID_MODEL=YubiKey_OTP+FIDO+CCID
ID_MODEL_ENC=YubiKey\x20OTP+FIDO+CCID
ID_MODEL_ID=0407
ID_REVISION=0543
ID_SERIAL=Yubico_YubiKey_OTP+FIDO+CCID_0018654472
ID_SERIAL_SHORT=0018654472
ID_BUS=usb
ID_USB_INTERFACES=:030101:030000:0b0000:
ID_VENDOR_FROM_DATABASE=Yubico.com
ID_MODEL_FROM_DATABASE=Yubikey 4/5 OTP+U2F+CCID
ID_PATH=pci-0000:00:1d.0-usb-0:1.4.1
ID_PATH_TAG=pci-0000_00_1d_0-usb-0_1_4_1
ID_SMARTCARD_READER=1
DRIVER=usb
ID_SECURITY_TOKEN=1
ID_FOR_SEAT=usb-pci-0000_00_1d_0-usb-0_1_4_1
SYSTEMD_WANTS=smartcard.target
SYSTEMD_USER_WANTS=smartcard.target
MAJOR=189
MINOR=186
TAGS=:security-device:seat:systemd:uaccess:
CURRENT_TAGS=:security-device:seat:systemd:uaccess:
[...]

YubiKey serial number is now visible in device manager.

Create custom device manager rules

Create device manager rules to execute custom shell script.

$ cat <<EOF | sudo tee /etc/udev/rules.d/90-yubikey.rules
ACTION=="add",    SUBSYSTEM=="usb",    ATTR{idVendor}=="1050",  ATTR{idProduct}=="0407", RUN+="/usr/bin/yubikey-notify.sh"
ACTION=="remove", SUBSYSTEM=="input", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0407", RUN+="/usr/bin/yubikey-notify.sh"
EOF
ACTION=="add",    SUBSYSTEM=="usb",    ATTR{idVendor}=="1050",  ATTR{idProduct}=="0407", RUN+="/usr/bin/yubikey-notify.sh"
ACTION=="remove", SUBSYSTEM=="input", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0407", RUN+="/usr/bin/yubikey-notify.sh"

Create custom shell script and assign names to serial numbers.

$ cat <<EOF | sudo tee /usr/bin/yubikey-notify.sh 
#!/bin/bash
# Send notification about YubiKey device
# https://sleeplessbeastie.eu/2022/01/03/how-to-identify-yubikey-using-dynamic-device-manager/

# user run directory
user_run_directory="/run/user"

# udev actions
declare -A msg_acts=( [add]=connected [remove]=disconnected )

# YubiKey names
declare -A msg_keys=( [0018654472]=Red [0018654473]=Green [0018654474]=Blue )

# set message icon
export msg_icon="/usr/share/icons/hicolor/scalable/status/bluetooth-paired.svg"

# set message action
export msg_act="\${msg_acts[\$ACTION]:-changed}"

# set message key
export msg_key="\${msg_keys[\$ID_SERIAL_SHORT]:-unknown}"

# send notification using dbus as each active user
find \$user_run_directory -maxdepth 1 ! -path \$user_run_directory -prune -type d -exec bash -c '
  for directory do
    uid=\$(basename \$directory)
    sudo -u "#\${uid}" \\
      bash -c "
        export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/\${uid}/bus;
        notify-send -i \"\${msg_icon}\" \"YubiKey action!\" \"<b>\${msg_key}</b> key <b>\${msg_act}</b>\"
      "
  done' bash {} \;
EOF
#!/bin/bash
# Send notification about YubiKey device
# https://sleeplessbeastie.eu/2022/01/03/how-to-identify-yubikey-using-dynamic-device-manager/

# user run directory
user_run_directory="/run/user"

# udev actions
declare -A msg_acts=( [add]=connected [remove]=disconnected )

# YubiKey names
declare -A msg_keys=( [0018654472]=Red [0018654473]=Green [0018654474]=Blue )

# set message icon
export msg_icon="/usr/share/icons/hicolor/scalable/status/bluetooth-paired.svg"

# set message action
export msg_act="${msg_acts[$ACTION]:-changed}"

# set message key
export msg_key="${msg_keys[$ID_SERIAL_SHORT]:-unknown}"

# send notification using dbus as each active user
find $user_run_directory -maxdepth 1 ! -path $user_run_directory -prune -type d -exec bash -c '
  for directory do
    uid=$(basename $directory)
    sudo -u "#${uid}" \
      bash -c "
        export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/${uid}/bus;
        notify-send -i \"${msg_icon}\" \"YubiKey action!\" \"<b>${msg_key}</b> key <b>${msg_act}</b>\"
      "
  done' bash {} \;

Ensure that executable bit is set.

$ sudo chmod +x  /usr/bin/yubikey-notify.sh

Inform systemd-udevd to reload the rules.

$ sudo udevadm control --reload

Connect or disconnect YubiKey devices to see notifications.

Do you catch my drift? I love this!

Additional notes

The command-line/GUI personalization utility does not need to be installed on the operating system as it is used only to alter internal YubiKey configuration.