User:Sakaki/Sakaki's EFI Install Guide/Configuring Secure Boot

In this section, which has no equivalent in the standard Gentoo handbook, we'll be setting up secure boot on your target machine.

While secure boot has received mixed reviews from the Linux community, it is a useful facility. With it activated, your machine will refuse to boot an executable that has been changed since it was signed (in an 'evil maid attack' for example), thereby closing off an important attack vector.

Windows 10 (and 8)-certified hardware ships with secure boot turned on by default (but only the Windows-sanctioned public keys installed in the machine), which is why, to get things started, we had to turn this feature off in the BIOS earlier in the tutorial. Now, however, we're going to 'take control of the platform' and add our own keys, so that we can use self-signed EFI stub kernels (which our buildkernel utility can create). The original Microsoft keys will be retained as well, so both Windows and our self-signed Gentoo kernels should be able to boot with secure mode on.

The steps we'll be undertaking are as follows (see below for a brief explanation of the terms used):
 * 1) We'll begin by saving off the current contents of the PK, KEK, db and dbx variables, as all four will be cleared when we enter setup mode (in step 4).
 * 2) We will then create three new private / public keypairs, to be used respectively as:
 * 3) our platform key (this will ultimately be stored in the PK signature database);
 * 4) our key exchange key (this will ultimately be appended to the KEK signature database); and
 * 5) our kernel-signing key (this will ultimately be appended to the db</tt> signature database).
 * 6) We'll create a signed signature list for our new PK</tt> (more on what this means later).
 * 7) We will then reboot the machine, and en route use the BIOS GUI to clear the secure variables, thereby entering setup mode.
 * 8) Then we will re-install our saved values of KEK</tt>, db</tt> and dbx</tt>.
 * 9) Next, we'll append our own public keys to KEK</tt> and db</tt>.
 * 10) Then, we'll set our own key in PK</tt>, thereby re-entering user mode. We'll use the signed signature list for this.
 * 11) We will then run buildkernel</tt>, to rebuild our EFI-stub kernel, this time appropriately signed with our new kernel-signing (private) key.
 * 12) Then we will restart the machine, enable secure boot, and check that our signed kernel is permitted to start up by the BIOS (it should be).
 * 13) We'll then reboot into Windows, and check that it is also still permitted to start (again, it should be). When in Windows, we'll take the chance to set the clock format to UTC.
 * 14) Finally, we'll reboot back into our signed kernel, (optionally setting a BIOS password en route) and proceed with the tutorial.

Let's get started!

<span id="secure_boot_intro">Introduction
We'll begin with a (very brief) primer on secure boot. (For a more in-depth review, please refer to James Bottomley's article "The Meaning of all the UEFI Keys", Greg Kroah-Hartman's article "Booting a Self-signed Linux Kernel" , and of course the UEFI specification itself .)

The UEFI specification defines four secure, non-volatile variables, which are used to control the secure boot subsystem. They are:
 * 1) The Platform Key (PK). The PK</tt> variable contains a UEFI (small 's', small 'b') 'signature database' which has at most one entry in it. When PK is emptied (which the user can perform via a BIOS GUI action), the system enters setup mode (and secure boot is turned off). In setup mode, any of the four special variables can be updated without authentication checks. However, immediately a valid platform key is written into PK (in practice, this would be an X.509 public key, using a 2048-bit RSA scheme), the system (aka, 'platform') enters user mode. Once in user mode, updates to any of the four variables must be digitally signed with an acceptable key. The private key counterpart to the public key stored in PK may be used to sign user-mode updates to PK</tt> or KEK</tt>, but not db or dbx (nor can it be used to sign executables).
 * 2) The Key Exchange Key (KEK). This variable holds a signature database containing one (or more) X.509 / 2048-bit RSA public keys (other formats are possible). In user mode, any db</tt>/dbx</tt> (see below) updates must be signed by the private key counterpart of one of these keys (the PK</tt> cannot be used for this). While KEK</tt> keys (or, more accurately, their private-key counterparts) may also be used to sign executables, it is uncommon to do so, since that's really what db</tt> is for (see below).
 * 3) The (caps 'S', caps 'B') Signature Database (db). As the name suggests, this variable holds a UEFI signature database which may contain (any mixture of) public keys, signatures and plain hashes. In practice, X.509 / RSA-2048 public keys are most common. It functions essentially as a boot executable whitelist (described in more detail shortly).
 * 4) The Forbidden Signatures Database (dbx). This variable holds a signature database of similar format to <tt>db</tt>. It functions essentially as a boot executable blacklist.

Now, here's the key point (excuse the pun): when the system is in user mode, and secure boot is enabled, the machine will only boot EFI executables which:
 * are unsigned, but have a hash (message digest) in <tt>db</tt> and not in <tt>dbx</tt>; or
 * are signed, where that signature appears in <tt>db</tt> but not in <tt>dbx</tt>; or
 * are signed, where that signature is verifiable by a public key in <tt>db</tt>, or a public key in <tt>KEK</tt>, and where neither that key, not the signature itself, appears in <tt>dbx</tt>.

When you buy a new Windows (10 or 8) machine, it will usually be set up as follows:
 * The PK variable will be loaded with a public key issued by the hardware vendor (for example, Panasonic).
 * The KEK variable will be loaded with a public key issued by Microsoft.
 * The db variable will be loaded with a set of public keys issued by various vendors authorized by Microsoft).
 * The dbx variable will generally contain some revoked signatures (although it may also be empty, it depends on the revision of Windows on your machine).

<span id="save_keystore_create_new_keys">Saving Current Keystore Values, and Creating New Keys
We begin by re-establishing an <tt>ssh</tt> connection, as before (as it will make the work of entering commands etc. easier). From the helper PC, issue:

Now proceed as below, using the <tt>ssh</tt> connection to enter all commands unless otherwise specified (incidentally, there is no need to use <tt>screen</tt> at this point, since we'll be rebooting again shortly). Issue:

Ensure only the superuser can access this directory, using <tt>chmod</tt> - issue:

Next, <span id="save_old_secure_vars">we'll use the <tt>efi-readvar</tt> tool (from the ) to store off the current values of <tt>PK</tt>, <tt>KEK</tt>, <tt>db</tt> and <tt>dbx</tt>, in machine-readable signature list format. Issue:

Now we <span id="create_secure_boot_keys">can create a new platform keypair, key-exchange keypair and kernel-signing keypair. We'll use <tt>openssl</tt> to do this. The requested keys will:
 * use X.509 certificate format for the public key (this allows various additional data fields to be passed with the key if desired, for subsequent identification);
 * utilise the RSA asymmetric cryptosystem, with a 2048 bit key length;
 * have 10 years (3650 days) to run until expiry;
 * use SHA-256 as the public key's message digest.

Issue:

This will have created three X.509 public-key certificate files (<tt>PK.crt</tt>, <tt>KEK.crt</tt> and <tt>db.crt</tt>), and three counterpart private key files (<tt>PK.key</tt>, <tt>KEK.key</tt> and <tt>db.key</tt>). We'll make the private keys readable only by root (an extra precaution, since they already in a directory readable only by root). Issue:

The <tt>efi-updatevar</tt> tool (also from the ), which we'll use shortly, can use raw X.509 certificates and keys to update the <tt>KEK</tt>, <tt>db</tt> and <tt>dbx</tt> secure variables. However, it is more picky (as of the time of writing) about the <tt>PK</tt> variable, and will only accept this in the 'signed signature list' ('<tt>.auth</tt>') format. We can create this in a <span id="create_PK_auth">two step process (using two command line tools from ). First, we make a signature list (which requires a unique ID, the value of which is essentially unimportant), and then we use our own (private) platform key to sign it. Let's do both now - issue:

The file we need out of this is <tt>PK.auth</tt>.

<span id="install_new_keys">Entering Setup Mode, and Installing New Keys
With the preparations completed, we're ready to enter setup mode. Reboot the machine:

Immediately your target PC starts to come back up again, enter the BIOS setup screen. As mentioned before, the exact method of entering the BIOS varies greatly from machine to machine (as does the BIOS user interface itself). On the Panasonic CF-AX3, press during startup (you may need to press it repeatedly, and you do this directly on the target machine's keyboard).

Once the BIOS setup screen comes up, using the same navigation techniques as before, perform the following steps:
 * 1) clear the UEFI secure boot variables, thereby entering setup mode; and
 * 2) restart your machine (saving changes).

It's impossible to be precise about the GUI actions required to achieve the above, as they will vary from BIOS to BIOS. However, to give you some idea, here's how you go about it on the Panasonic CF-AX3 (which has an AMT BIOS).

To achieve step 1, use the arrow keys to navigate across to the 'Security' tab. Then, navigate down to the 'Secure Boot' item, and press. This enters a special 'Security' sub-page. Navigate down to the 'Clear Secure Boot Keys' item, and press. Confirm that you wish to proceed by selecting 'Yes' in the popup which appears, then press. If asked to reconfirm, select 'Yes' and press again:

Note that on some UEFI implementations it is required to set a supervisor password in order for the option to clear the Secure Boot keys to be available.

Next, ensure that your boot USB key is still inserted, then press to restart (step 2), and confirm if prompted.

The machine should restart, and, just as before, you will see the <tt>plymouth</tt> passphrase screen. Enter your LUKS keyfile <tt>gpg</tt> passphrase (the one you created earlier), directly at the target machine keyboard, and wait for the text console login to appear.

Then, re-connect to the machine via <tt>ssh</tt>. From the helper PC, issue:

Now proceed as below, using the <tt>ssh</tt> connection to enter all commands unless otherwise specified (again, we will not need <tt>screen</tt>). Issue:

You can verify that the secure variables have been cleared. To do so, enter:

and review the output.

Next, we'll reload the old contents of <tt>KEK</tt>, <tt>db</tt> and <tt>dbx</tt>, which we saved off above, thereby ensuing that Windows will still be permitted to load under secure boot (if we don't do this, it will be blocked). Issue:

The <tt>-e</tt> option specifies that an EFI signature list file is to be loaded (and the <tt>-f</tt> option precedes the filename itself). Because we are in setup mode, no private key is required for these operations (which it would be, if we were in user mode).

Assuming that completed successfully, we can now append our own key-exchange and kernel-signing public keys, which we created and stored into <tt>KEK.crt</tt> and <tt>db.crt</tt> (respectively) earlier. Issue:

Note that here, we are using the <tt>-a</tt> option to append (rather than replace), and a slightly different format for the input file (since it is a X.509 certificate, rather than a signature list, we drop the <tt>-e</tt>, and use <tt>-c</tt> rather than <tt>-f</tt> to introduce the pathname). More details can be found in the <tt>efi-updatevar</tt> manpage.

Having made our changes, we can now write our own platform key into PK, using the signed signature list we created earlier. Issue:

If this succeeds, the target machine will have been switched back to user mode (although secure boot is not yet enabled).

Display the contents of all the secure variables now. Issue:

and verify that both your new keys, and Microsoft's original set, are present.

Now, let's make a backup (in machine readable signature list format) of the current state of the variables. Issue:

<span id="test_secure_boot">Testing Secure Boot with a Signed Kernel
Our next step is to create an appropriately signed kernel. The <tt>buildkernel</tt> script will do this automatically for us, provided that the files (the private kernel-signing key) and  (its public key counterpart) exist (which they now do). Ensure that the boot USB key is still inserted, then issue:

This should not take long to complete (as by default it does not <tt>make clean</tt>).

Assuming the kernel build completed successfully, we can now restart, turn on secure boot, and try it out! Issue:

Immediately your target PC starts to come back up again, enter the BIOS setup screen. As mentioned before, the exact method of entering the BIOS varies greatly from machine to machine (as does the BIOS user interface itself). On the Panasonic CF-AX3, press during startup (you may need to press it repeatedly, and you do this directly on the target machine's keyboard).

Once the BIOS setup screen comes up, using the same navigation techniques as before, perform the following steps:
 * 1) turn on secure boot; and
 * 2) restart your machine (saving changes).

It's impossible to be precise about the GUI actions required to achieve the above, as they will vary from BIOS to BIOS. However, to give you some idea, here's how you go about it on the Panasonic CF-AX3 (which has an AMT BIOS).

To achieve step 1 on the CF-AX3, use the arrow keys to select the 'Security' tab, then navigate down to the 'Secure Boot' item, and select it by pressing. This enters a 'Security' page; navigate to the 'Secure Boot control' item, and press. In the popup that appears, select 'Enabled' using the arrow keys, and press :

Next, ensure that your USB boot key is still inserted, then press to restart (step 2), and confirm if prompted.

The machine should restart, and, if all goes well, you should shortly be prompted with the <tt>plymouth</tt> passphrase screen. If so, then congratulations, you are running a self-signed kernel under secure boot! Enter your LUKS keyfile <tt>gpg</tt> passphrase (the one you created earlier), directly at the target machine keyboard, and wait for the text console login to appear, as previously.

<span id="verify_win8_secure_boot">Verifying Secure Boot with Windows (and Fixing RTC)
Having successfully booted our own self-signed kernel, we next have to check that Windows still works. Remove the boot USB key from the target machine, then (while it is still running Gentoo) log in directly at the target machine's keyboard (at the login prompt, enter 'root' as the user (without quotes), and then type the root password you set up earlier). Then issue (directly at the machine's keyboard):

As the boot USB key is not inserted, Windows should start automatically. If it does boot, you have just verified that Windows also starts properly under your modified secure boot settings (and if it does not, follow the troubleshooting hints above).

Now, while Windows is running, let's take the chance to switch its clock to UTC, to match that used by <tt>systemd</tt> (which we set earlier in the tutorial).

To achieve this, login to your Windows account (which must have administrator rights - the first user created on a new Windows install has these by default), as usual. Next, perform the following steps (I have noted where things differ between Windows 10, 8.1 and 8):


 * 1) First we'll check the Windows time, date and timezone is correct. Hit the, which will bring up the start menu in Windows 10 (or the "start screen" in Windows 8.1 and 8), and type  . Then click on the 'Date and Time' item which appears (in Windows 10 and 8.1; Windows 8 users will need to click the 'Settings' icon to see this result; note also that in Windows 8.1 and 8, the item you need to click is entitled 'Date and time settings'). A 'Date and time' dialog appears. Set appropriate values for your locale.
 * 2) Next, we'll instruct Windows to use UTC (this will require a registry edit). Hit the, which will bring up the start menu in Windows 10 (or the "start screen" in Windows 8.1 and 8), and type  . Then click on the 'regedit' item that appears. If prompted (via a dialog) whether to allow it to make changes to your computer, click 'Yes'. The <tt>regedit</tt> program now opens; using the navigation tree-view on the left, select <tt>HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation</tt> (you need to click on the little arrows to see the lower levels of the tree). Once this item has been selected, various time-zone related information will display on the right-hand pane. Right-click in the white area at the bottom of this pane, and choose <tt>New->DWORD (32-bit Value)</tt> from the context menu that appears. A fresh DWORD entry is added to the end of the list with its name selected - overtype this with   then press . Now double-click on the name, and a dialog will appear, in which you can edit the key's value. Type in   (the number one) for the value, as shown below:Win8Regedit.png Close the dialog by clicking on 'OK'. Then exit the <tt>regedit</tt> application (using the menu item <tt>File->Exit</tt>).
 * 3) Now we'll disable the Windows Time Service. This is most easily done from the Windows command line. Hit the , which will bring up the start menu in Windows 10 (or the "start screen" in Windows 8.1 and 8), and type  . Now right-click on the 'Command Prompt' icon that appears, then click on 'Run as administrator' item in the context menu (in Windows 10 and 8.1; it appears at the bottom of the screen in Windows 8). If asked whether you wish to proceed, click 'Yes'. You will be presented with an open command window. Now enter  . Hopefully, this should report <tt>SUCCESS</tt>. Close out the command window (by clicking on the 'x' in its title bar).
 * 4) Next, we'll force Windows to update the time. Hit the, which will bring up the start menu in Windows 10 (or the "start screen" in Windows 8.1 and 8), and type  . Then click on the 'Date and Time' item which appears (in Windows 10 and 8.1; Windows 8 users will need to click the 'Settings' icon to see this result; note also that in Windows 8.1 and 8, the item you need to click is entitled 'Date and time settings'). A 'Date and time' dialog (which we used above) appears again. Now, on Windows 10, select the 'Internet Time' tab, click on 'Change settings...' and click 'Update now', then press 'OK'. On Windows 8.1 and 8, instead move the 'Set time automatically' slider to 'Off', and then back to 'On' again. In either case, assuming you have a network connection, the time should immediately update when you do this (and, assuming your locale is set correctly, it should be accurate). Close out the dialog once complete.

<span id="set_bios_password">Setting BIOS Password (Optional), and Restarting Gentoo Linux
Next, we will <span id="reboot_from_win8_to_linux">reboot back into Gentoo. Re-insert the boot USB key into the target PC. Then, in Windows-8, hit, then click on the power icon at the bottom right of the screen, and choose 'Restart' from the pop-up menu.

Immediately your target PC starts to come back up again, enter the BIOS setup screen. As mentioned a number of times now, the exact method of entering the BIOS varies greatly from machine to machine (as does the BIOS user interface itself). On the Panasonic CF-AX3, press during startup (you may need to press it repeatedly, and you do this directly on the target machine's keyboard).

Once you have the BIOS configuration screen up, you need to perform the following steps:
 * 1) select the "<tt>Gentoo Linux (USB Key)</tt>" EFI boot item as top priority;
 * 2) (optionally) set a BIOS password; then
 * 3) restart your machine (saving changes).

It's impossible to be precise about the GUI actions required to achieve the above, as they will vary from BIOS to BIOS. However, to give you some idea, here's how you go about it on the Panasonic CF-AX3 (which has an AMT BIOS).

To <span id="set_boot_order_gentoo">achieve step 1 on the CF-AX3, use the arrow keys the arrow keys to navigate to the 'Boot' tab, and then down to the 'UEFI Priorities' item. Press, and a sub-page is displayed. Ensure the item 'UEFI Boot from USB' is enabled (if it isn't, enable it now, and then press to restart, and come back to this point). Navigate down to 'Boot Option #1' and press. In the pop-up menu that appears, select the "<tt>Gentoo Linux (USB Key)</tt>" item (which was added to the boot list when we ran <tt>buildkernel</tt> earlier):

Press to set this as the top boot option. Finally, press to exit the subpage.

<span id="set_bios_pw">The next step (#2, installing a BIOS password) is optional, but it is sensible to ensure that secure boot cannot be switched off by an attacker with temporary access to your machine (to permit a tampered kernel to run without your knowledge, for example). Most machines support some form of BIOS password, but the means of setting it varies widely. On the CF-AX3, use the arrow keys to navigate to the 'Security' tab, and then move down to the 'Set Supervisor Password' item, and press. Type your password into the pop-up that appears: When done, press. Then, when prompted, re-type the password to confirm and press.

It is then sensible (on the CF-AX3, at any rate) to disable the BIOS's boot password prompt (otherwise, you'll have to type in the BIOS (supervisor) password every time you boot from USB). On the CF-AX3, navigate up to the 'Password On Boot' item, and press. Then, in the pop-up that appears, use the arrow keys to select 'Disabled', and press to select:

That's it! Now ensure that the boot USB key is still inserted, then press to restart (step 3), and confirm if prompted.

The machine should restart, and, if all goes well, you should shortly be prompted with the (by now familiar) <tt>plymouth</tt> passphrase screen. Enter your LUKS keyfile <tt>gpg</tt> passphrase (the one you created earlier), directly at the target machine keyboard, and wait for the text console login to appear, just as before.

Then, re-connect to the machine via <tt>ssh</tt>. From the helper PC, issue:

Use the <tt>ssh</tt> connection to enter all subsequent commands unless otherwise specified (do not start up <tt>screen</tt> at this point, we'll do so again shortly).

The final thing thing we must do here is to check that our system time details have not been messed up by Windows (which, given the changes we have just made, they should not have been). Issue:

and make sure the time and date are still correct, and in particular that the "<tt>RTC in local TZ</tt>" field reports as <tt>no</tt>.

<span id="next_steps">Next Steps
Congratulations, setup of secure boot is complete! Next, we can install the GNOME 3 graphical environment. Click here to go to the next chapter, "Setting up the GNOME 3 Desktop".