16/12 Update: Added Workaround for Full Disk Encryption.

Working for SatoshiLabs has taught me a lot, especially about privacy and security. One of the main lessons is that passwords, despite our reliance on them as the ultimate gatekeeper, are the weakest link in our digital security. There have been many articles and opinions written on this topic, and I will leave it to them to explain why we should not rely on a combination of letters and numbers as the means of our authentication. Instead, I will introduce you to U2F, a second factor authentication protocol, and guide you how you can conveniently use to log into Unix-based systems, in this case macOS. (Looking for Linux Guide? It’s here!)

Universal Second Factor (U2F) has been developed as a secure method of second factor authentication, as the name suggests. Unlike TOTP, which relies on symmetric keys, U2F uses asymmetric encryption and a challenge-response mechanism to prove you are really you.

TREZOR, the world’s first hardware wallet for cryptocurrencies, is also a wonderful U2F device that can serve as your U2F token. The advantage of TREZOR over other traditional U2F tokens is that it sports a display, and therefore you will always see what you are authenticating with. This feature limits the phishing attack vector against you.

Disclaimer! You are doing this at your own risk. There is no guarantee it will work, and I cannot ascertain that you will not make any mistakes. Errors in PAM configuration may break your computer. If you are not comfortable working with command line, you are not ready to do this! I am not liable for mistakes done by following this guide.

Preparation

In essence, we are going to work with Unix system’s Pluggable Authentication Module (PAM). First we will install the U2F module for PAM (pam-u2f). This is not a standard module in macOS, but it is easily downloadable. Then we are going to configure U2F authentication, and set up PAM to work with U2F.

Special Case: Full Disk Encryption If you have FileVault 2 enabled (FDE), you might want to read the limitations and necessary workaround first. Go to FDE Section.

Step 0 — Install Homebrew

If you do not have Homebrew installed, run the following command in your Terminal:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

What is Homebrew? It is a convenient package manager for macOS, allowing you to install various applications. Check out Homebrew for more info.

Step 1 — Install pam-u2f

Install the pam-u2f module by running the following command:

brew install pam-u2f

For users running macOS without System Integrity Protection, symlink the module into a directory where PAM looks for modules:

sudo ln -s /usr/local/Cellar/pam-u2f/1.0.4/lib/pam/pam_u2f.so /usr/lib/pam/

Alternatively, you can directly copy the module into the pam directory:

sudo cp /usr/local/Cellar/pam-u2f/1.0.4/lib/pam/pam_u2f.so /usr/lib/pam/

If you are using macOS from version 10.11 El Captain onwards, you will probably have System Integrity Protection activated, which protects system folders from being edited. In this case you will not be able to write into /usr/lib/, and will have to write the full path of the module into pam.d rules. This will be explained in Step 4B, but do not skip the next steps. (Or you can turn off SIP, but that’s up to you.)

Step 2— Set Up U2F Credentials in Home Directory

Create a folder where you will store credentials and set up your key. At the moment of running pamu2fcfg plug your TREZOR/U2F device into the computer.

mkdir -p ~/.config/Yubico/

pamu2fcfg > ~/.config/Yubico/u2f_keys

If you want to check if the key was set up correctly, run the following command:

cat ~/.config/Yubico/u2f_keys

WARNING! If you use Full Disk Encryption (FDE), you will need your password to decrypt your disk. Therefore U2F cannot replace your password, otherwise you might not be able to log in. Your disk will only be decrypted after the first successful login, and thus the credentials file cannot be read until after the first login! Detailed description and Workaround at the end of this article.

Step 3 — Set Up Testing PAM.d Rules

Now comes the interesting part. Navigate to /etc/pam.d/ and check out the content of the directory.

cd /etc/pam.d/ && ls

You should be able to see all the setting files:

user@macbook:/etc/pam.d$ ls

authorization cups login.term rshd sshd

checkpw ftpd other screensaver su

chkpasswd login passwd smbd sudo

The most important files for now are sudo, screensaver and authorization, although you can check out others if you want to.

For testing, let’s use the sudo config file. This file defines what authentication methods are allowed/required for sudo command. Open it up in your favorite text editor.

user@macbook:/etc/pam.d$ sudo nano sudo

(In this guide, we will be only editing “auth” realm of PAM. If you want to experiment with other realms, you can, but do so only if you know what you are doing! More info on PAM here.)

WARNING! Keep in mind that if you misconfigure the files, you might lose access to sudo or to login functions, even. For testing, always use the “sufficient” flag.

Now again, there is a different approach depending on your macOS system.

Step 4A — macOS Without System Integrity Protection

If you do not have System Integrity Protection and followed the instructions in Step 1, then add the following line as the second line in the file:

auth sufficient pam_u2f.so

In the end, your sudo config will look like this:

# sudo: auth account password session

auth sufficient pam_u2f.so

auth required pam_opendirectory.so

account required pam_permit.so

password required pam_deny.so

session required pam_permit.so

Save the config file and exit text editor.

Step 4B — macOS With System Integrity Protection

If you do have System Integrity Protection, then you will have to write the full path of the module. If you have installed pam-u2f with Homebrew (like guided in Step 1), then add the following line to the configuration file as the second line in the file:

auth sufficient /usr/local/Cellar/pam-u2f/1.0.4/lib/pam/pam_u2f.so

The resulting config file will look like this:

# sudo: auth account password session

auth sufficient /usr/local/Cellar/pam-u2f/1.0.4/lib/pam/pam_u2f.so

auth required pam_opendirectory.so

account required pam_permit.so

password required pam_deny.so

session required pam_permit.so

Save the config file and exit text editor.

Step 4 — Test Your Setup

Plug in your TREZOR/U2F device and fire up the Terminal. To be sure, run the command sudo -k in order to clear the sudo timestamp. This is necessary to test the new sudo configuration. Then, try the new config with any sudo command.