Synopsis

wd-security [--help] status|unlock|change-pw|erase device

Description

Manage password protection of Western Digital external drives supported by the proprietary WD Security software.

Common Options

The following options are supported by the main executable and all sub-commands.

--help, -h

Show help.

--verbose, -v

Increase verbosity.

Sub-Commands

version

Show version information.

help [SUB-COMMAND]

Show overview of available sub-commands or usage of a specific SUB-COMMAND.

status [OPTIONS] device

Show encryption status of device.

OPTIONS
--is-locked

Suppress normal output and exit with zero status if device is locked, nonzero otherwise.

unlock [OPTIONS] device

Unlock device.

The password will be prompted for and converted to UTF-16LE to ensure compatibility with the proprietary WD Security software.

OPTIONS
--password password

Use password as the unlock password. The supplied password may not be empty and will be converted to UTF-16LE encoding.

--key-file filename

Use contents of filename as password. The entire file will be read and used as-is for the password.

--salt salt

Use salt as the password salt. The supplied salt will be converted to UTF-16LE. Overrides the password salt stored in the Handy Store Security Block, if it exists, or the default password salt.

--salt-file filename

Use the contents of filename as the password salt. The entire file will be read and used as-is for the password salt. Overrides the password salt stored in the Handy Store Security Block, if it exists, or the default password salt.

--iterations iterations

Perform iterations hash iterations to generate the Key Encryption Key (KEK). Overrides the iterations stored in the Handy Store Security Block, if it exists, or the default iterations.

--write-handy-store

If device is successfully unlocked, write the password salt and iterations to the Handy Store Security Block. This is useful when the values in the current Security Block do not represent the correct values needed to unlock the device. For example, if the proprietary WD Security software was used to change the password when the password salt and iterations were other than the defaults. See Broken behavior when changing password below for an explanation.

--use-backup

Read salt and iterations from the backup Handy Store Security Block.

--no-backup

Do not write the backup Handy Store Security Block, when --write-handy-store is used.

--rescan

If device is successfully unlocked, notify the kernel that the partition table should be re-read.

--no-wdp-utils

Don’t try to detect whether wdpassport-utils.py was used to generate the Handy Store Security Block or enable compatibility quirks.

--wdp-utils

Force-enable compatibility quirks for wdpassport-utils.py.

change-pw [OPTIONS] device

Enable/disable/change encryption status of device.

The old and/or new passwords will be prompted for, as appropriate and converted to UTF-16LE to ensure compatibility with the proprietary WD Security software.

OPTIONS
--disable

Disable password protection.

--no-clear

By default, when password protection is disabled, the Handy Store Security Block will be cleared. This switch will prevent that operation.

--password password

Use password as the current password. The supplied password may not be empty and will be converted to UTF-16LE encoding.

--key-file filename

Use contents of filename as the current password. The entire file will be read and used as-is for the password.

--new-password password

Use password as the new password. The supplied password may not be empty and will be converted to UTF-16LE encoding.

--new-key-file filename

Use contents of filename as the new password. The entire file will be read and used as-is for the password.

--hint hint

Set hint as the new password hint in the Handy Store Security Block.

--salt salt

Use salt as the password salt. The supplied salt will be converted to UTF-16LE. Overrides the password salt stored in the Handy Store Security Block, if it exists, or the default password salt.

Note
Truncated or zero-padded to 8-bytes if enabling password protection.
--salt-file filename

Use the contents of filename as the password salt. The entire file will be read and used as-is for the password salt. Overrides the password salt stored in the Handy Store Security Block, if it exists, or the default password salt.

Note
Truncated or zero-padded to 8-bytes if enabling password protection.
--iterations iterations

Perform iterations hash iterations to generate the Key Encryption Key (KEK). Overrides the iterations stored in the Handy Store Security Block, if it exists, or the default iterations.

Note
Clamped to 32-bits if enabling password protection.
--iter-time milliseconds

Calculate a value for hash iterations such that the generation of the Key Encryption Key (KEK) will consume milliseconds ms. The default is 2000 ms.

--use-backup

Read salt and iterations from the backup Handy Store Security Block.

--no-backup

Do not write the backup Handy Store Security Block.

--no-wdp-utils

Don’t try to detect whether wdpassport-utils.py was used to generate the Handy Store Security Block or enable compatibility quirks.

--wdp-utils

Force-enable compatibility quirks for wdpassport-utils.py.

erase [OPTIONS] device

Securely erase device.

This is accomplished by causing the device to install a new Device Encryption Key (DEK). Every device should be erased at least once, to replace the possibly insecure factory Device Encryption Key (DEK). See “got HW crypto?”.

Caution
All information on device will become lost and completely unrecoverable.
OPTIONS
--no-clear

By default, when performing a secure erase, the Handy Store Security Block will be cleared. This switch will prevent that operation.

--cipher cipher

Use the cipher named cipher.

--cipher-id id

Use cipher with id id.

--combine

Request mixing encryption key with on-device Random Number Generator.

--key-file filename

Use the contents of filename as the encryption key supplied to device. <key-size> bytes will be read from filename and used as-is for the encryption key.

--key-size bytes

Force encryption key size to be bytes bytes. Overrides the value reported by the device.

handy-store [OPTIONS] info|set|show …​

Show or manipulate the Handy Store. See Handy Store.

config [OPTIONS] device

Show or manipulate configuration parameters of device.

Two SCSI mode pages are used to store Device Configuration parameters and Device Operations parameters. These parameters may be displayed and, if the device allows, modified.

OPTIONS
--disable-ap
--no-disable-ap

Set the DisAP bit in the Device Configuration mode page, or clear it. The meaning of this setting is unknown.

--disable-cdrom
--no-disable-cdrom

Disable, or enable, the emulated CDROM device. (DisCD bit in the Device Configuration mode page)

--disable-ses
--no-disable-ses

Disable, or enable, the SCSI Enclosure Services support. (DisSES bit in the Device Configuration mode page)

--disable-wl
--no-disable-wl

Set the DisWL bit in the Device Configuration mode page, or clear it. The meaning of this setting is unknown.

--2tb-limit
--no-2tb-limit

Limit, or not, the reported drive capacity to two terabytes (2TB). (2TBL bit in the Device Configuration mode page)

--cd-media-valid
--no-cd-media-valid

Set the CDMValid bit in the Device Operations mode page, or clear it. The meaning of this setting is unknown.

--enable-cd-eject
--no-enable-cd-eject

Set the ENCDEJ bit in the Device Operations mode page, or clear it. The meaning of this setting is unknown.

--esata15
--no-esata15

Set the ESATA15 bit in the Device Operations mode page, or clear it. The meaning of this setting is unknown. Perhaps intended to force 150MBps data transfer speeds on the eSATA port for misbehaving SATA 1 chipsets.

--invert-lcd
--no-invert-lcd

Invert, or not, the pixels on devices having an LCD display. (INVLCD bit in the Device Operations mode page)

--lcd-backlight level

Set the brightness of the LCD backlight to level. level must have a value between 0 and 255. (BACKLIGHT BRITE field in the Device Operations mode page)

--loose-sb2
--no-loose-sb2

Set the LOOSESB2 bit in the Device Operations mode page, or clear it. The meaning of this setting is unknown. Perhaps related to Fibre Channel Single-Byte Command Code (SB-2).

--power-led level

Set the brightness of the power LED to level. level must have a value between 0 and 255. (POWER LED BRITE field in the Device Operations mode page)

--quiet

Be quiet and do not display the table of current configuration parameters.

Handy Store

The proprietary WD Security software stores encryption parameters in special sectors on the drive called the Handy Store. The two known blocks are named the Security Block and the User Block.

Security Block

Stores the password hint, as well as the salt and number of iteration rounds to use to generate the Key Encryption Key (KEK).

User Block

Stores a drive label.

Security Block (backup)

Whenever the Security Block is written, wd-security will also try to write a backup of the Security Block to the last Handy Store block if it is empty, or if it contains a previously written Security Block.

Tip
Pass /dev/zero as the filename argument of the handy-store write sub-command to clear a Handy Store block.

This can be useful to recover from the primary Security Block being overwritten or otherwise corrupted. For example, if the proprietary WD Security software was used to change the password when the password salt and iterations were other than the defaults. See Broken behavior when changing password for an explanation.

Sub-Commands

handy-store info [OPTIONS] device

Show geometry of Handy Store.

Last Block

Address of last block.

Block Size

Size (bytes) of each block.

Xfer Max

Maximum number of blocks that may be transferred at a time.

handy-store set [OPTIONS] device name=value [name=value …​]

For each name/value pair, set field name to value in Handy Store.

The backup Security Block will only be updated if the salt and iterations values match those in the primary Security Block. If they differ, or if the backup is missing, then it will not be written.

Configurable Fields
hint hint

Set the password hint to hint.

label label

Set the drive label to label.

OPTIONS
--no-backup

Don’t write backup Security Block.

handy-store show [OPTIONS] device

Display Security and User blocks of Handy Store.

OPTIONS
--backup

Display the backup Security Block.

--no-wdp-utils

Don’t try to detect whether wdpassport-utils.py was used to generate the Handy Store Security Block or enable compatibility quirks.

--wdp-utils

Force-enable compatibility quirks for wdpassport-utils.py.

handy-store read [OPTIONS] device block-addr

Read Handy Store block block-addr and display in human-readable form.

block-addr should be in the range 0 to [Last Block], or one of the following named blocks:

"security" or "sec"

Security Block

"user"

User Block

"security-backup" or "sec-backup"

backup Security Block

OPTIONS
-n num

Read num blocks (see [Xfer Max]).

-o filename

Write raw binary output to filename.

handy-store write [OPTIONS] filename device block-addr

Write contents of filename to Handy Store block block_addr.

The file will be read in units of the Handy Store [Block Size].

block-addr should be in the range 0 to [Last Block], or one of the following named blocks:

"security" or "sec"

Security Block

"user"

User Block

"security-backup" or "sec-backup"

backup Security Block

OPTIONS
--full

Read whole file.

-n num

Write num blocks (see [Xfer Max]).

Automatic Unlocking

If the 00-wd-security.rules rules file has been installed, then udev(7) will perform the following operations when a Western Digital external drive is attached:

  1. Check for the existence of a corresponding Key File for the device

  2. Check whether the device is locked

  3. Attempt to use the Key File to unlock the device

  4. Notify the kernel to re-read the partition table of the device

Key File Naming

The Key File should be placed in the /etc/keys directory and given a name containing the model and serial number of the device that it corresponds to. It should have the following form:

WD_MODEL_SERIAL.key

where MODEL refers to the model of the device as reported by udev, with all spaces and slashes, etc. converted to underscores, and SERIAL refers to the serial number of the device.

The udevadm utility can be used to determine the appropriate values for MODEL and SERIAL as follows:

$ udevadm info --query=property \
    --property='ID_USB_MODEL,ID_USB_SERIAL_SHORT' /dev/sdX
ID_USB_MODEL=My_Passport_0820
ID_USB_SERIAL_SHORT=12345678901234567C89012C

where sdX should be replaced by the name of the device file for your device. Using the above values, the Key File should be named:

WD_My_Passport_0820_12345678901234567C89012C.key

The wd-security-devices.sh script will provide this information in an easier to use and more pleasant format.

Key File Contents

Drive WILL be shared with Windows/MacOS

If the proprietary WD Security software will also be used to unlock the device, then the Key File should contain the unlock password encoded in UTF-16LE. The length of the UTF-16LE encoded password should be 25 characters or less, and not more than 50 bytes in total.

The iconv(1) utility can be used to convert a password to UTF-16LE as follows:

$ echo -n 'my-secret-password' >password.utf8
$ iconv -f UTF-8 -t UTF-16LE -o WD_MODEL_SERIAL.key password.utf8
$ rm password.utf8

Drive will NOT be shared with Windows/MacOS

If the proprietary WD Security software will not be used to unlock the device, then it is not necessary to impose any restrictions on the contents of the Key File. For example, it may be populated with 32 bytes of random data:

$ dd if=/dev/urandom of=WD_MODEL_SERIAL.key bs=32 count=1

Test the Key File

Test the Key File by using it to unlock the device:

$ sudo wd-security unlock --key-file WD_MODEL_SERIAL.key /dev/sdX

Install the Key File

Place the Key File, with the appropriate name, into the /etc/keys directory:

$ sudo mkdir -m 700 /etc/keys
$ sudo cp WD_MODEL_SERIAL.key /etc/keys/
$ sudo chmod 400 /etc/keys/WD_MODEL_SERIAL.key

Once the Key File is in place, the corresponding device will be unlocked automatically when it is attached.

Examples

Example 1. Show security status of /dev/sdb
# wd-security status /dev/sdb
Status: (0x01) Locked
Cipher: (0x30) Full Disk Encryption
Example 2. Unlock device and rescan the partition table of /dev/sdb
# wd-security unlock --rescan /dev/sdb
Enter password> _My Secret Password_
Successfully unlocked drive
Example 3. Unlock device, overriding salt/iterations and write to Handy Store
# wd-security unlock --salt 'abcd' --iterations 123456 \
    --write-handy-store /dev/sdb
Enter password> _My Secret Password_
Successfully unlocked drive
Example 4. Set the password hint of /dev/sdb
# wd-security handy-store set /dev/sdb hint='My password hint'
Writing password hint to Handy Store Security Block...done.
Example 5. Set the drive label of /dev/sdb
# wd-security handy-store set /dev/sdb label="My Book 25EE (6TB)"
Writing drive label to Handy Store User Block...done.
Example 6. Show contents of the Handy Store of /dev/sdb
# wd-security handy-store show /dev/sdb
 Password Salt: "钋ꪂ㵏좪" 0x8b 0x94 0x82 0xaa 0x4f 0x3d 0xaa 0xc8
 Password Hint: "My password hint"
Iteration Rnds: 8635497
   Drive Label: "My Book 25EE (6TB)"
Example 7. Change password using a Key File for the new password
# wd-security change-pw --new-key-file mykeyfile.key /dev/sdb
Enter current password (hint: My password hint)> _My Secret Password_
Enter new password hint> _My New Hint_
Example 8. Disable password protection for device /dev/sdb
# wd-security change-pw --disable /dev/sdb
Enter current password (hint: My New Hint)> _My Secret Password_
Example 9. Securely erase device /dev/sdb
# wd-security erase /dev/sdb
Erasing device using the following parameters:
  Cipher: 0x30 (Full Disk Encryption)
Key size: 32
Do not Combine key with on-device RNG
Continue? [y/N]> _y_
Clearing Handy Store Security Block...
Example 10. Disable emulated CDROM device associated with /dev/sdb
# wd-security config --disable-cdrom /dev/sdb

--- Device Configuration
        *Disable SES: no
      *Disable CDROM: yes
          Disable AP: no
  Disable White List: no
           2TB Limit: no

--- Device Operations
             eSATA15: no
           Loose SB2: no
    *Enable CD Eject: no
     *CD Media Valid: yes
          *Power LED: 255
       LCD Backlight: 0
          Invert LCD: no
Example 11. Clear Handy Store block 15 on /dev/sdb
# wd-security handy-store write /dev/zero /dev/sdb 15

Exit Status

wd-security exits with a non-zero status on failure and zero for success.

Environment

WDS_DEBUG

May be set to an integer to indicate the desired debug level of the wd-security library (e.g. 1, 2, 3, etc.). Higher numbers will produce more verbose output.

Files

/etc/keys/WD_MODEL_SERIAL.key

Key File used by udev(7) rules to automatically unlock device corresponding to MODEL and SERIAL. See Key File Naming.

/usr/lib/udev/rules.d/00-wd-security.rules

udev(7) rules implementing automatic device unlock.

/usr/share/doc/wd-security/wd-security-devices.sh

Helper script to list attached Western Digital external drives along with the name of the Key File that should be created if automatic unlocking is desired.

Compatibility Notes

Proprietary WD Security software

Poor default salt and iteration settings

The default salt and iteration count are “WDC.” and 1000. The proprietary WD Security software always uses these values when creating a password. Not only is 1000 a pathetically low iteration count for even ancient CPUs, but using fixed values completely negates the value of having a salt and performing multiple rounds of hashing. Fixed values means that it is possible to pre-generate a rainbow table of all possible (or likely) passwords and use it to instantly unlock any drive that has been configured with the proprietary WD Security software on Windows or MacOS.

When wd-security enables password protection on a device it will generate a new 8-byte salt randomly and calculate an appropriate iteration count based on timing the hash operation. This significantly increases the difficulty of brute force attempts to derive the unlock password and is completely compatible with the proprietary WD Security software.

Broken behavior when changing password

When the proprietary WD Security software is used to change the encryption password, it will do so using the existing salt and iteration count configured on the drive, which is the correct behavior. After changing the password, it will then overwrite the existing Security Block with the !!DEFAULT!! salt and iteration count, making it impossible to unlock the drive again unless the old salt and iteration count are known and can be restored.

For this reason, it is a good idea to backup the salt and iteration count. If these are known, then access to the drive can be restored by overriding the salt and iteration count on the wd-security command-line when unlocking the drive with the new password, and optionally restoring the Security Block. By default, wd-security will create a backup of the Security Block when enabling password protection, which may then be used to unlock a drive. See Security Block (backup).

Tip
Never use the proprietary WD Security software to change the password.

wdpassport-utils.py

Broken password salt mangling

wdpassport-utils.py is a Python utility designed for much the same purpose as this project, but, unfortunately, it does not handle the password salt correctly.

When wdpassport-utils.py sets the password on a device that does not have an existing Security Block, it will populate a new Security Block with iterations set to the proprietary WD Security default of 1000, and with an 8-byte salt randomly generated from ASCII characters. So far this is less than ideal, but still fine. The problem arises in the way that wdpassport-utils.py processes the password salt. Instead of using all 8-bytes as-is from the Security Block, wdpassport-utils.py will first convert the 8-byte salt into a 4-byte salt by dropping every other byte. Then it will treat the 4-byte salt as a 4-character ASCII string and convert it to UTF-16 with platform endianness, resulting in a new 8-byte salt, which it will then use in the algorithm to produce the Key Encryption Key (KEK). This procedure is incompatible with the proprietary WD Security software.

This has 3 consequences:

  1. This procedure will happen to work correctly with any salt that is composed entirely of UTF-16LE encoded ASCII characters, e.g. the default salt used by the proprietary WD Security software: “WDC.”, but it will not work correctly with any other salt.

  2. The proprietary WD Security software will not be able to unlock any drive that has a Security Block created by wdpassport-utils.py.

  3. It will behave differently on big-endian platforms, resulting in a drive that even it cannot unlock when run on a little-endian platform.

Luckily wdpassport-utils.py populates the password hint field with a specific string that can be used to identify a Security Block created by it. By default, wd-security will detect this string and enable compatibility quirks to allow managing a drive that has a Security Block created by wdpassport-utils.py.

Importantly, if wdpassport-utils.py is used to set a password on a device that is not currently protected with a password, but that has an existing Security Block, then it will still perform the salt mangling described above when setting the new password. The proprietary WD Security software will not be able to unlock the device and wd-security will not be able to detect that the password was set using wdpassport-utils.py. In this case it will be necessary to explicitly enable the workaround quirks by passing the --wdp-utils switch.

Bugs

Please report all problems, especially on drives not using the Full Disk Encryption cipher, since I did not have access to such drives during development.

See Also

iconv(1), udevadm(8), udev(7), WD_Encryption_API.txt, got HW crypto?