Atom feed – Twitter Blog/Full


Jethro Beekman on
Technology & Policy

Lenovo ThinkPad HDD Password

by Jethro Beekman – Mar 8, 2015 . Filed under: English, Technology, Security, Lenovo ThinkPad.

Modern SSDs (at least the ones made by Intel, Samsung) always encrypt all stored data using AES. The encryption key used is stored in nonvolatile memory on the SSD. One of the reasons for this is that to securely wipe the drive now you just need to overwrite the encryption key with a new random one. This way, you don’t need to erase every flash block, which is very bad for durability reasons. The encryption key can optionally be encrypted using a 32-byte “security password”, the configuration of which is overloaded on the ATA security feature set. If you trust the hardware manufacturer to actually implement this securely, this would seem to provide a very solid and fast option for encrypted persistent storage.

To be able to boot off of such an encrypted drive, it needs to be unlocked before the OS’s bootloader can be read, which requires BIOS support. Luckily, my Lenovo ThinkPad T420s does support this: you can configure a drive password in BIOS the setup screen and from then on the BIOS will ask for a password upon startup. Now here’s the catch: it turns out that when you take this drive and put it in a different machine, it is impossible to unlock the drive. This would mean that if my laptop dies but the drive were still intact I would be unable to access the data on the drive, even though I know the password!

A couple of weeks ago I finally decided to get to the bottom of this by reverse engineering the Lenovo UEFI BIOS on my laptop. The goal was simple: to find the code path from password input to ATA security unlock output and reproduce it. I have detailed the reverse engineering process in another blog post. Here’s the algorithm:

\textit{AtaPassword} \gets \textrm{SHA}_{256}\left( \textrm{SHA}_{256}(\textit{Password}) \parallel \textit{AtaIdentity}_\textit{SerialNumber} \parallel \textit{AtaIdentity}_\textit{ModelNumber} \right)

The inputs are \textit{Password} which is the user-supplied password and \textit{AtaIdentity} which is the ATA Identify Device data structure. The output \textit{AtaPassword} gets sent to the drive. Why do they use this algorithm? It’s actually somewhat clever: the S/N and M/N act as a salt, such that a hash sniffed off of the ATA bus will only be able to unlock that one drive, and not any other drives that use the same password.

That’s the good part. The bad part is that the algorithm above is not quite complete. Here is the actual algorithm:

\textit{PasswordHash} \gets \textrm{SHA}_{256}\left( \left( \textrm{ToScanCodes}(\textrm{LowerCase}(\textit{Password})) \parallel ␀^{64} \right)_{1:64} \right)_{1:12}
\textit{SN} \gets \textit{AtaIdentity}_\textit{SerialNumber} \qquad \textit{MN} \gets \textit{AtaIdentity}_\textit{ModelNumber}
\textit{AtaPassword} \gets \textrm{SHA}_{256}\left( \textit{PasswordHash} \parallel \textrm{SwapBytes}(\textit{SN}) \parallel \textrm{SwapBytes}(\textit{MN}) \right)

The function \textrm{ToScanCodes} translates the characters 1234567890qwertyuiopasdfghjkl;zxcvbnm␣ to integers in the ranges 2–11, 16–25, 30–39, 44–50, 57–57, respectively, while dropping other characters. \textrm{SHA}_{256} is the well-known hash function. \textrm{SwapBytes} is the POSIX swab function, it swaps odd and even bytes.

There are a couple of peculiarities in the algorithm that reduce the security. First of all, I’m not sure why the characters get converted into scancodes. The UEFI BIOS is well-equiped to deal with keyboard layouts, so that just seems unnecessary. It also reduces the entropy to only 5.3 bits per character, making short passwords very insecure. What’s worse though, is that only 12 bytes of the password hash are used, putting an upper bound of 96 bits on the entropy. If your password is sampled uniformly at random from the available scancodes, don’t bother making it longer than 18 characters.

The other weird thing is the \textrm{SwapBytes} function. This means that if your model number is Samsung␣SSD␣840␣EVO␣500GB␣…, that part of the input to the hash function will be aSsmnu␣gSS␣D48␣0VE␣O05G0␣B…. Why is that? Between the ATA Identify Device data structure being defined in terms of 16-bit words and the UEFI specification using 16-bit wide characters, while the model and serial number are encoded as 8-bit ASCII, I can only assume that someone messed up some endianness conversion somewhere.

Today, am I releasing a tool to unlock your drive. If despite all the above—96 bits is more entropy than most passwords have—you still decide to use the Lenovo BIOS to do your password management, you can use this to unlock your drive in the event of hardware failure. You will need hdparm to talk to your drive. If the password hash contains a ␀ character, you’ll need to patch hdparm to be able to use that. I tested this on my own setup, but you may want to verify it actually works before you start depending on it.